中级天翼
一、sort快排:
知识点:sort()
排序
sort()
默认从小到大排序
加头文件#include<algotithm>
数组长度为n,
给a[1] a[2] a[3]......a[n]
这n 个数排序
sort(a+1,a+n+1);
给a[0] a[1] a[2]......a[n-1]
这n 个数排序
sort(a,a+n);
sort()
自定义函数cmp,实现从大到小排序
bool cmp(int a,int b) { return a>b; } int a[100005]; int main(){ int n; cin>>n; for(int i=1;i<=n;i++) cin>>a[i]; sort(a+1,a+n+1,cmp); for(int i=1;i<=n;i++) cout<<a[i]<<' '; return 0; }
自定义函数是bool 类型,自定义函数cmp 的形参和待排序的数组类型有关。
3. sort()
按照特定条件排序
二、冒泡排序:
冒泡排序是一种简单的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有元素再需要交换,也就是说该数列已经排序完成。
这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端。
(12比上面的数都小,经过多次与相邻数字交换,最后浮到了顶端)
如果我们要将下面的数从大到小排序,冒泡排序的过程是这样的
原序列:12 35 99 18 76
第一轮(从第一个数开始,相邻数字相比较、交换):
12 35 99 18 76
35 12 99 18 76
35 99 12 18 76
35 99 18 12 76
35 99 18 76 12
此时末尾确定了最小的数 12
第二轮(还是从第1个数开始,相邻数字相比较、交换):
35 99 18 76 12
99 35 18 76 12 (这里是35和18进行比较,不需要交换位置,18比35小)
99 35 18 76 12
99 35 76 18 12 (最后一位的12是确定的,不需要比较)
第二轮在末尾确定了第2小的数 18
第三轮:
99 35 76 18 12
99 35 76 18 12
99 76 35 18 12
第三轮在末尾确定了第3小的数 35
第四轮:
99 76 35 18 12
99 76 35 18 12
这里对于5个数,需要4轮排序,每轮确定第i小的数。
每轮比较的数字对数比上一轮少一对。
代码实现冒泡排序(将a数组中a[1]~a[n]的元素从小到大排序)
for(int i=1;i<=n-1;i++)//表示排序的轮数,共需n-1轮 for(int j=1;j<=n-i;j++)//第i轮要确定第i大的数,放在后面,需要比较n-i对数字(因为后面i-1个数已经确定下来,不需要比较) if(a[j]>a[j+1]) //相邻的数字比较,如果前大后小,就需要交换位置 swap(a[j],a[j+1]);
二、冒泡排序优化
下面是一个大小为6的数组,经过一轮冒泡排序就是有序的了。
第一轮中,46分别与20、33、38、43比较并交换了位置,与60比较后不交换位置,此时数组中元素20,33,38,43,46,60已经是有序的了,后面就没必要再继续进行排序。
冒泡排序优化的原理:基本冒泡排序算法的代码中共进行了n-1轮冒泡排序。但实际上当某一轮排序过后序列已有序时,显然不需要再继续排序,排序轮数可能远小于n-1轮。
冒泡排序优化的代码实现
for(int i=1;i<=n-1;i++) { bool flag=false; //定义一个标志位,用来记录某轮排序是否有数据交换发生 for(int j=1;j<=n-i;j++) { if(a[j]>a[j+1]) { swap(a[j],a[j+1]); flag=true; //有数据交换,则改变标志位的值 } } if(flag==false) //如果标志位的值没改变,说明本轮排序没有数据交换,即数组本身已经有序了,那么退出循环 break; }
三、本节知识点脉络
三、桶排序:
利用桶数组记录序列中每个数字出现的次数。由于用桶数组的下标对应序列中的数字,所以只要按下标从小到大的顺序,将桶数组记录的数字输出即可(注意桶数组的下标是对应数字,而桶元素的值对应该数字出现的次数)
如果需要排序的数据在一个明显有限范围内(整型)时,我们可以用数组下标与数值一一对应,将每个数值放进与它对应的数组元素(桶)中,然后按照顺序输出各桶的值,将得到有序的序列。
比如:对于序列
从小到大排序:
定义一个桶(即数组)数组a[10]
桶数组a的所有元素赋初值为0,然后将每个数字计入对应桶元素中,
最后,按照从小到大的顺序遍历桶数组,如果桶元素a[i]的值非0,说明该元素下标对应的数字出现过,并且a[i]的值就是i这个数的个数,即要输出a[i]个i。
代码实现
如果要输入n个不超过1000的数字,使用桶排序从小到大输出,代码如下:
int a[1001]; //每个数的范围在1~1000 ,所以定义a[1001] (1~1000的桶) int main(){ int n ,t; cin>>n; for(int i=1;i<=n;i++){ //输入n个数 cin>>t; a[t]++; //用桶的下标存这个数,桶的值++ } for(int i=1;i<=1000;i++){ //遍历桶数组 for(int j=1;j<=a[i];j++){ //输出a[i]个i(a[i]为0则不输出) cout<<i<<' '; } } return 0; }
三.本节知识点脉络
中级启示者
冒泡排序
原序列:76 18 99 35 12(这里从小到大排)
第一趟:
76 18 99 35 12
76 18 99 12 35
76 18 12 99 35
76 12 18 99 35
12 76 18 99 35
此时确定了最小的数 12
第二趟:
12 76 18 99 35
12 76 18 35 99
12 76 18 35 99 (这里是35和18进行比较,不需要交换位置,18比35小)
12 18 76 35 99
第二趟确定了第2小的数
第三趟:
12 18 76 35 99
12 18 76 35 99
12 18 35 76 99
第三趟确定了第3小的数
第四趟:
12 18 35 76 99
12 18 35 76 99
这里对于5个数,需要4趟,每次确定第i小的数,放在最前面。
每趟把没排好序的序列里最大的(或者最小的)找出来,通过相邻两个数两两交换这种方式,像冒泡一样。
冒泡排序是一种稳定的排序,每次比较相邻两个数的大小,若要求逆序输出,前一个数如果大于后一个数则不用交换,否则交换两个数的顺序。总共进行n-1轮排序,第i轮比较n-i次。
循环写法
for(int i=1;i<=n-1;i++)//表示趟数,共n-1趟(确定n个数的顺序)
for(int j=1;j<=n-i;j++)//每次确定第i大的数,放在后面,所以这里是n-i。
if(a[j]>a[j+1])
swap(a[j],a[j+1]);