常用排序算法总结
2015-12-14 19:44
232 查看
1.直接插入排序
直接插入排序是一种最为简单的排序方法。
直接插入排序的基本思想:第i趟排序将序列中的第i+1个元素k[i+1]插入到一个已经按值有序的子序列(k[1],k[2],...k[i])中的合适的位置,使得插入后的序列依然按值有序。
直接插入排序(straight insertion sort)的做法是:每次从无序表中取出第一个元素,把它插入到有序表的合适位置,使有序表仍然有序。第一趟比较前两个数,然后把第二个数按大小插入到有序表中;
第二趟把第三个数据与前两个数从后向前扫描,把第三个数按大小插入到有序表中;依次进行下去,进行了(n-1)趟扫描以后就完成了整个排序过程。
代码如下:
2.选择排序
选择排序(Selection sort)是一种简单直观的排序算法。它的工作原理是每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完。
3.冒泡排序:
冒泡排序(Bubble Sort),是一种计算机科学领域的较简单的排序算法。
原理:
1.比较相邻的元素。如果第一个比第二个小,就交换他们两个。
2.对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最小的数。
3.针对所有的元素重复以上的步骤,除了最后一个。
4.持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
4.希尔排序
希尔排序(Shell Sort)是插入排序的一种。也称缩小增量排序,是直接插入排序算法的一种更高效的改进版本。希尔排序是非稳定排序算法。该方法因DL.Shell于1959年提出而得名。
希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止。
基本思想:
先取一个小于n的整数d1作为第一个增量,把文件的全部记录分组。所有距离为d1的倍数的记录放在同一个组中。先在各组内进行直接插入排序;然后,取第二个增量d2<d1重复上述的分组和排序,直至所取的增量
=1(
<
…<d2<d1),即所有记录放在同一组中进行直接插入排序为止。
该方法实质上是一种分组插入方法
比较相隔较远距离(称为增量)的数,使得数移动时能跨过多个元素,则进行一次比[2] 较就可能消除多个元素交换。D.L.shell于1959年在以他名字命名的排序算法中实现了这一思想。算法先将要排序的一组数按某个增量d分成若干组,每组中记录的下标相差d.对每组中全部元素进行排序,然后再用一个较小的增量对它进行,在每组中再进行排序。当增量减到1时,整个要排序的数被分成一组,排序完成。
一般的初次取序列的一半为增量,以后每次减半,直到增量为1。
5.快速排序
快速排序(Quicksort)是对冒泡排序的一种改进。快速排序由C. A. R. Hoare在1962年提出。它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
设要排序的数组是A[0]……A[N-1],首先任意选取一个数据(通常选用数组的第一个数)作为关键数据,然后将所有比它小的数都放到它前面,所有比它大的数都放到它后面,这个过程称为一趟快速排序。值得注意的是,快速排序不是一种稳定的排序算法,也就是说,多个相同的值的相对位置也许会在算法结束时产生变动。
一趟快速排序的算法是:
1)设置两个变量i、j,排序开始的时候:i=0,j=N-1;
2)以第一个数组元素作为关键数据,赋值给key,即key=A[0];
3)从j开始向前搜索,即由后开始向前搜索(j--),找到第一个小于key的值A[j],将A[j]和A[i]互换;
4)从i开始向后搜索,即由前开始向后搜索(i++),找到第一个大于key的A[i],将A[i]和A[j]互换;
5)重复第3、4步,直到i=j; (3,4步中,没找到符合条件的值,即3中A[j]不小于key,4中A[i]不大于key的时候改变j、i的值,使得j=j-1,i=i+1,直至找到为止。找到符合条件的值,进行交换的时候i, j指针位置不变。另外,i==j这一过程一定正好是i+或j-完成的时候,此时令循环结束)。
6.堆排序
堆排序(Heapsort)是指利用堆这种数据结构所设计的一种排序算法。堆是一个近似完全二叉树的结构,并同时满足堆性质:即子结点的键值或索引总是小于(或者大于)它的父节点。
堆排序这里只列出了简单代码,随后会详细介绍。
直接插入排序是一种最为简单的排序方法。
直接插入排序的基本思想:第i趟排序将序列中的第i+1个元素k[i+1]插入到一个已经按值有序的子序列(k[1],k[2],...k[i])中的合适的位置,使得插入后的序列依然按值有序。
直接插入排序(straight insertion sort)的做法是:每次从无序表中取出第一个元素,把它插入到有序表的合适位置,使有序表仍然有序。第一趟比较前两个数,然后把第二个数按大小插入到有序表中;
第二趟把第三个数据与前两个数从后向前扫描,把第三个数按大小插入到有序表中;依次进行下去,进行了(n-1)趟扫描以后就完成了整个排序过程。
代码如下:
#include<stdio.h> void insertsort(int a[],int n) { int i,j; for(i=2;i<=n;i++) { a[0]=a[i]; j=i-1; while(j>0&&a[0]>a[j]) { a[j+1]=a[j--]; a[j+1]=a[0]; } } } int main() { int i; int a[11]={-1,2,4,6,7,18,3,48,21,1,0}; //a[0]作为哨兵,用来存储每次待插入的元素,节省系统空间 printf("排序前的数组:\n"); for(i=1;i<=10;i++) printf("%d ",a[i]); printf("\n"); insertsort(a,10); printf("直接插入排序后的数组:\n"); for(i=1;i<=10;i++) printf("%d ",a[i]); }
2.选择排序
选择排序(Selection sort)是一种简单直观的排序算法。它的工作原理是每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完。
#include<stdio.h> void select_sort(int a[],int n) { int i,j,m,temp; for(i=0;i<n-1;i++) { for(j=i+1;j<n;j++) { if(a[j]>a[i]) { temp=a[i]; a[i]=a[j]; a[j]=temp; } } } } int main() { int i; int a[10]={2,4,6,7,18,3,48,21,1,0}; printf("排序前的数组:\n"); for(i=0;i<10;i++) printf("%d ",a[i]); printf("\n"); select_sort(a,10); printf("选择排序后的数组:\n"); for(i=0;i<10;i++) printf("%d ",a[i]); }
3.冒泡排序:
冒泡排序(Bubble Sort),是一种计算机科学领域的较简单的排序算法。
原理:
1.比较相邻的元素。如果第一个比第二个小,就交换他们两个。
2.对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最小的数。
3.针对所有的元素重复以上的步骤,除了最后一个。
4.持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
#include<stdio.h> void bubble_sort(int a[],int n) { int i,j,temp; for (j=0;j<n-1;j++) for (i=0;i<n-1-j;i++) { if(a[i]<a[i+1]) { temp=a[i]; a[i]=a[i+1]; a[i+1]=temp; } } } int main() { int i; int a[10]={2,4,6,7,18,3,48,21,1,0}; printf("排序前的数组:\n"); for(i=0;i<10;i++) printf("%d ",a[i]); printf("\n"); bubble_sort(a,10); printf("冒泡排序后的数组:\n"); for(i=0;i<10;i++) printf("%d ",a[i]); }
4.希尔排序
希尔排序(Shell Sort)是插入排序的一种。也称缩小增量排序,是直接插入排序算法的一种更高效的改进版本。希尔排序是非稳定排序算法。该方法因DL.Shell于1959年提出而得名。
希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止。
基本思想:
先取一个小于n的整数d1作为第一个增量,把文件的全部记录分组。所有距离为d1的倍数的记录放在同一个组中。先在各组内进行直接插入排序;然后,取第二个增量d2<d1重复上述的分组和排序,直至所取的增量
=1(
<
…<d2<d1),即所有记录放在同一组中进行直接插入排序为止。
该方法实质上是一种分组插入方法
比较相隔较远距离(称为增量)的数,使得数移动时能跨过多个元素,则进行一次比[2] 较就可能消除多个元素交换。D.L.shell于1959年在以他名字命名的排序算法中实现了这一思想。算法先将要排序的一组数按某个增量d分成若干组,每组中记录的下标相差d.对每组中全部元素进行排序,然后再用一个较小的增量对它进行,在每组中再进行排序。当增量减到1时,整个要排序的数被分成一组,排序完成。
一般的初次取序列的一半为增量,以后每次减半,直到增量为1。
#include<stdio.h> void shell_sort(int a[],int n) { int i,j,temp,gap=n; while(gap>0) { for (i=0;i<n-gap;i++) //子序列采用冒泡排序 { if(a[i]<a[i+gap]) { temp=a[i]; a[i]=a[i+gap]; a[i+gap]=temp; } } gap--; //增量减小 } } int main() { int i; int a[10]={2,4,6,7,18,3,48,21,1,0}; printf("排序前的数组:\n"); for(i=0;i<10;i++) printf("%d ",a[i]); printf("\n"); shell_sort(a,10); printf("希尔排序后的数组:\n"); for(i=0;i<10;i++) printf("%d ",a[i]); }
5.快速排序
快速排序(Quicksort)是对冒泡排序的一种改进。快速排序由C. A. R. Hoare在1962年提出。它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
设要排序的数组是A[0]……A[N-1],首先任意选取一个数据(通常选用数组的第一个数)作为关键数据,然后将所有比它小的数都放到它前面,所有比它大的数都放到它后面,这个过程称为一趟快速排序。值得注意的是,快速排序不是一种稳定的排序算法,也就是说,多个相同的值的相对位置也许会在算法结束时产生变动。
一趟快速排序的算法是:
1)设置两个变量i、j,排序开始的时候:i=0,j=N-1;
2)以第一个数组元素作为关键数据,赋值给key,即key=A[0];
3)从j开始向前搜索,即由后开始向前搜索(j--),找到第一个小于key的值A[j],将A[j]和A[i]互换;
4)从i开始向后搜索,即由前开始向后搜索(i++),找到第一个大于key的A[i],将A[i]和A[j]互换;
5)重复第3、4步,直到i=j; (3,4步中,没找到符合条件的值,即3中A[j]不小于key,4中A[i]不大于key的时候改变j、i的值,使得j=j-1,i=i+1,直至找到为止。找到符合条件的值,进行交换的时候i, j指针位置不变。另外,i==j这一过程一定正好是i+或j-完成的时候,此时令循环结束)。
#include<stdio.h> #include<stdlib.h> void swap(int &m,int &n) //序列中元素交换 { int temp; temp=m; m = n; n=temp; } void quick_sort(int a[],int m,int n) { int i,j; if(m<n) { i=m; j=n+1; while(1) { do i++; while(!(a[m]>=a[i]||i==n)); //重复i++操作 do j--; while(!(a[m]<=a[j]||j==m)); //重复j--操作 if(i<j) swap(a[i],a[j]); //交换a[i]和a[j]位置 else break; } swap(a[m],a[j]); quick_sort(a,m,j-1); quick_sort(a,j+1,n); } } int main() { int i; int a[10]={2,4,6,7,18,3,48,21,1,0}; printf("排序前的数组:\n"); for(i=0;i<10;i++) printf("%d ",a[i]); printf("\n"); quick_sort(a,0,9); printf("快速排序后的数组:\n"); for(i=0;i<10;i++) printf("%d ",a[i]); }
堆排序(Heapsort)是指利用堆这种数据结构所设计的一种排序算法。堆是一个近似完全二叉树的结构,并同时满足堆性质:即子结点的键值或索引总是小于(或者大于)它的父节点。
#include<stdio.h> void adjust(int a[],int i,int n) { int j; int temp; temp=a[i]; j=2*i; while(j<n) { if(j<n&&a[j]>a[j+1]) { j++; //j为i的左右孩子中较小孩子的序号 } if(temp<=a[j]) { break; //temp为最小的孩子,不需要元素的交换 } a[j/2]=a[j]; j=2*j; } a[j/2]=temp; } void heap_sort(int a[],int n) { int i; int temp; for(i=n/2;i>=1;i--) //将原序列初始化为一个小顶堆 { adjust(a,i,n); } for(i=n-1;i>=1;i--) //调整序列元素 { temp=a[i+1]; a[i+1]=a[1]; a[1]=temp; adjust(a,1,i); } } int main() { int i; int a[11]={-11,5,2,12,6,9,0,3,6,15,20}; printf("排序前的数组:\n"); for(i=1;i<=10;i++) printf("%d ",a[i]); printf("\n"); heap_sort(a,10); printf("堆排序后的数组:\n"); for(i=1;i<=10;i++) printf("%d ",a[i]); }
堆排序这里只列出了简单代码,随后会详细介绍。
相关文章推荐
- CentOS SVN SHOW LOG 只显示版本号和NO DATE的解决方法
- Java:String和Date、Timestamp之间的转换
- 关于StatusBar,TitleBar,ActionBar之间的区别以及他们的高度的计算。
- C#字符串加密
- Android开发 接入支付宝移动支付
- linux安装 mysql问题
- Ubuntu配置Maven
- 最简单的定时随机切换图片
- CF 149 D Coloring Brackets(区间DP)
- pair RDD groupByKey countByKey countByValue aggregateByKey reduceByKey 测试
- POJ-3259 Wormholes
- findViewById自定义控制时出现空指针异常
- 跟我一起写 Makefile(二)
- 如何破解加密软件
- Java进阶(五十二)利用LOG4J生成服务日志
- UI 手势 点击
- 《剑指offer》——替换空格
- hadoop在子节点上没有datanode进程
- Java进阶(五十二)利用LOG4J生成服务日志
- POJ 3187 Backward Digit Sums 【穷竭搜索 next_permutation函数】