排序算法初步总结
来源:互联网 发布:%20是什么网络用语 编辑:程序博客网 时间:2024/05/23 18:45
排序算法按照不同的原则可以分为不同的类。如根据排序的稳定性可以分为稳定排序和不稳定排序;根据排序过程所涉及到的存储器分为内部排序和外部排序等等。这里将根据排序采用的策略进行分类,可分为:插入排序、交换排序、选择排序、归并排序和基数排序等。
插入排序
插入排序中最简单和基础的是直接插入排序和希尔排序。
1.直接插入排序
基本思想:依次取出原始序列中元素,然后将其有序插入有序的序列中。
特征:设置监视哨,其作用一方面是在循环中监视下标是否越界,省略了设置循环判断条件;另一方面在进入循环之前可以作为缓冲区域,这样可以保证记录的后移不会失去原值。
code:时间复杂度O(n^2),空间复杂度O(1),稳定排序。
void InsertSort(NOde list[],int n){ int i,j; for(i=1;i<n;i++){ list[0]=list[i]; //设置监视哨</span><span style="font-family:SimSun;font-size:14px;">list[0]</span><span style="font-size:18px;"> j=i-1; while(list[0]<list[j]){//当前值小于前面的值,则记录后移,直到正确位置 list[j+1]=list[j]; j--; } list[j+1] = list[0];//找到正确位置后将list[0]的原记录值插入 }}
2.希尔排序
基本思想:又称为缩小增量排序,是对直接插入排序的一种改进排序。其先将整个待排序列分割成若干子序列,分别对子序列进行直接插入排序,等到整个序列中的记录基本有序时,再对整个序列进行一次直接插入排序。
特征:其对增量序列的选择没有严格要求,一般而言,对于n个序列,可以选择分组数依次为d1=n/2,d2=d1/2,d3=d2/2,...,di=1。
code:时间复杂度O(nlog2(n))-O(n^2),不稳定排序。
<span style="font-size:14px;">void ShellSort(NOde list[],int n){ int i,j,d; for(d=n/2;d>0;d=d/2){//初始增量为n/2,每次缩小增量为d/2 for(i=d+1;i<=n;i++){ list[0]=list[i]; //设置监视哨 j=i-d; //前后记录增量为d,而不是1 while(j>=0 && list[0]<list[j]){//当前值小于前面的值,则记录后移,直到正确位置 list[j+d]=list[j]; j-=d; } list[j+1] = list[0];//找到正确位置后将list[0]的原记录值插入 } }}</span>
交换排序
交换排序中最典型的两个是冒泡排序和快速排序。
1.冒泡排序
基本思想:冒泡排序是最直观的一种排序方法,其排序过程中,相邻的两个元素进行比较,若前面的值大于后边的值则进行交换,否则则不交换。或者是较大值的前移。
特征:设置中间变量,进行数据存储。
code:时间复杂度O(n^2),稳定排序。
<span style="font-size:14px;">void Bubble_sort(NOde list[],int n){ int i,j,temp; for(i=0;i<n;i++){ temp=0; //交换标志变量,初始化为未交换 for(j=0;j<n;j++){ if(list[j]>list[j+1]){//前者大于后者则交换 list[0]=list[j+1]; list[j+1]=list[j]; list[j]=list[0]; temp=1; } } if(temp==0) break; //未交换,排序结束 }}</span>
2.快速排序
基本思想:快速排序是对冒泡的一种改进,不同之处在于冒泡每次的比较和交换都是在相邻的单元进行的,只能左移或右移一个单元。而快排比较和交换式从两端向中间进行,大大减少了比较和移动的次数。
特征:任取序列中的某个数据作为基准线,通过一次的排序,将原始序列分为两个子序列,左子序列小于或等于该基准线,右子序列大于或等于该基准线,然后一次循环,直到最后排成有序序列。
code:时间复杂度O(nlog2(n)),不稳定排序。
int Partition(NOde list[],int low,int high){ list[0]=list[low]; while(low<high){ while(low<high && list[high]>=list[0])//在high端寻找一个比list[low]小的记录放入low --high; list[low]=list[high]; while(low<high && list[high]<=list[0])//在low端寻找一个比list[low]大的记录放入high ++low; list[high]=list[low]; } list[low]=list[0]; return low;//返回基准线位置}void Quick_sort(NOde list[],int low,int high){ int loc; if(low<high){ loc=Partition(list,low,high);//进行快排 Quick_sort(list,low,loc-1);//对前半区域进行划分 Quick_sort(list,loc+1,high);//对后半区域进行划分 }}
选择排序
选择排序中分为简单选择排序和堆排序。
1.简单选择排序
基本思想:顾名思义,即首先选择最小的数据放在第一个位置,再选取次小的数据放在第二个位置,以此类推,直至选出n-1个为止。
特征:选取每次的最小值min。
code:时间复杂度O(n^2),不稳定排序。
<span style="font-size:14px;">void Select_sort(NOde list[],int n){ int i,j,min; for(i=0;i<n;i++){ min=i; for(j=i+1;j<=n;j++){//在i-n的范围内寻找 if(list[min]>list[j]) min=j; if(min!=j){ list[0]=list[min]; list[min]=list[i]; list[i]=list[0]; } } }}</span>
2.堆排序
基本思想:堆排序是利用堆特性进行排序的,根据其性质可知,堆的根为整个序列的最大值或最小值,因此将原始序列进行建堆,再对输出堆顶原始后进行维护,可以实现堆排序。
特征:建堆以及堆维护。
code:时间复杂度O(nlog2(n)),不稳定排序。
void Createtheap(NOde list[],int m,int n){ int i,j,flag; i=m;j=2*i; list[0]=list[i]; flag=0; while(j<=n && flag!=1){//沿值较小的分支向下筛选 if(j<n && list[j]>list[j+1])//选取孩子中值较小的分支 j++; if(list[0]<list[j]) flag=1; else{//继续向下筛选 list[i]=list[j]; i=j; j=2*i; list[i]=list[0] } }}void Heap_sort(NOde list[],int n){ for(int i=n/2;i>=1;i--)//初始化堆 Createtheap(list,i,n); for(int i=n;i>=1;i--){//list[1]为堆顶元素,可以设置循环输出 list[1]=list[i];//将堆尾元素移至堆顶 Createtheap(list,1,i);//整理堆 }}
归并排序
归并排序可分为多路归并排序和二路归并排序。这里只对二路归并排序进行总结。
1.二路归并排序
基本思想:将原始序列分为若干子序列,先将每个子序列进行排序,再将已排序的子序列进行合并,得到完整排序序列。
特征:先将排序长度设置为1,然后两两归并为n/2个子序表,依次下去,直到长度为n的有序表。
code:时间复杂度O(nlog2(n)),空间复杂度O(n),稳定排序。
<span style="font-size:14px;">void Merge(NOde a[],NOde b[],int i,int m,int n){ int la,lb,lc; la=i;lb=m+1;lc=i; //序列la,lb,lc的始点 while(la<=m && lb<=n){ if(a[la]<a[lb]) //有序合并 b[lc++] = a[la++]; else b[lc++] = a[lb++]; } while(la<=m) //复制第一个序列中剩下的元素 b[lc++] = a[la++]; while(lb<=n) //复制第二个序列中剩下的元素 b[lc++] = a[lb++];}void MergPass(NOde list[],NOde A[],int n,int c){ int i=0,j; while(i+2*c-1<=n-1){ //长度均为c的两个子序列合并为一个序列 Merge(list,A,i,i+c-1,i+2*c-1); i+=2*c; } if(i+c-1<n) //长度不相等的两个子序列合并为一个序列 Merge(list,A,i,i+c-1,n-1); else //只剩一个序列时直接复制到A中 for(j=i;j<=n-1;j++) A[j]=list[j];}void Merge_sort(NOde list[],int n){ int c=1; //初始归并长度为1 NOde A[MAXN]; //需要一个辅助空间 while(c<n){ MergPass(list,A,n,C); //一次合并,结果写入A中 c*=2; //序列长度扩大一倍 MergPass(A,list,n,C); //再次合并,结果写入list中 c*=2; }}</span>
其它排序
更新ing...
- 排序算法初步总结
- 七大排序算法初步实现
- 算法初步之插入排序
- 算法--排序算法总结
- 算法:排序算法总结
- 算法:排序算法总结
- 算法-排序算法总结
- 算法-排序算法总结
- 【排序算法】排序算法总结
- 【算法】算法初步:聊一聊常见排序的算法
- 排序算法总结---希尔排序
- 排序算法总结---冒泡排序
- 排序算法总结----快速排序
- 排序算法总结---希尔排序
- 排序算法总结【内排序】
- 排序算法之内排序总结
- 排序算法总结:冒泡排序
- 【排序算法总结】冒泡排序
- DDoS攻击愈演愈烈如何成功防御?
- 你有才华为什么得不到重用?
- x86上安装Android虚拟机
- 2014.7.10 Hive Hdfs整合尝试
- .net调用存储过程详解
- 排序算法初步总结
- gdb中设置共享库断点问题
- C语言 gets()和scanf()函数的区别
- 从头开始写项目Makefile(六):参数传递、条件判断、include
- 离开你上的来看你你你你你你你你你你你你你你你你你你你你你你
- Jetty总览
- 动画push推送到另一个页面
- 2097 Sky数
- Android中Parcelable接口用法