稳定不稳定看相等元素排序前和排序后的相对顺序是否改变。
O(n2)
直接选择(不稳定):选择出最小的放在第一位;选择出次小的放在第二位;……
代码:
#include <iostream> using namespace std; //直接选择排序算法描述: /* 1、第一层遍历:以未排序的第一个元素作为最小值 2、第二层遍历:对剩下的未排序元素进行遍历,小于最小值则交换值 3、得到最小的元素组成排序序列,以此类推,第二小的元素也会排入到排序好的序列中。 4、重复直至排序完全 */ //==》O(n^2) void Swap08(int a[], int i,int j) { int tmp; tmp=a[i]; a[i]=a[j]; a[j]=tmp; } void SelectSeq(int a[],int num) { int min=0; for(int i=0;i<num-1;i++) //最后一个序列是单独的一个元素,不需要再排序 { min=i;//1、选择未排序序列的第一个值为最小的值 for(int j=i+1;j<num;j++) //遍历其余未排序的值,如果小于最小值,则交换值 { if(a[i]>a[j]) Swap08(a,i,j); } } } int main08() { int a[]={12,8,20,5,9,16,7,30}; int num=sizeof(a)/sizeof(a[0]); SelectSeq(a,num); for(int i=0;i<num;i++) { cout<<a[i]<<" "; } return 0; }
冒泡(稳定):两两比较,最大的放后边;直到最大的放在末尾。
代码:
#include <iostream> using namespace std; //冒泡排序算法描述: /* 1、比较相邻元素,如果前一个比后一个大,则交换位置。 2、对每一对相邻的元素做同样的工作,从第一对到最后一对,做完一次循环后,最后元素则是最大的。 3、针对以上元素重复以上步骤,除了最后一个。 4、重复对越来越少的元素做以上动作,直至没有可交换的对。 */ //==》O(n^2) void Swap09(int a[], int i,int j) { int tmp; tmp=a[i]; a[i]=a[j]; a[j]=tmp; } void BubbleSeq(int a[],int len) { for(int j=0;j<len-1;j++) { for(int i=0;i<len-1-j;i++) { if(a[i]>a[i+1]) Swap09(a,i,i+1); } } return; } int main09() { int a[]={12,8,20,5,9,16,7,30}; int len=sizeof(a)/sizeof(a[0]); BubbleSeq(a,len); for(int i=0;i<len;i++) { cout<<a[i]<<" "; } return 0; }
==》改进:鸡尾酒排序
代码:
#include <iostream> using namespace std; //鸡尾酒排序算法描述: /* 1、设两个索引,一个索引第一位,一个索引最末尾。 2、单层循环,一遍最大冒泡,一次最小冒泡。 3、重复做以上动作,直到排序好。 */ //==》O(n^2) void Swap11(int a[], int i,int j) { int tmp; tmp=a[i]; a[i]=a[j]; a[j]=tmp; } void CocktailSeq(int a[],int len) { int left=0; int right=len-1; while(left<right) { for(int i=left;i<right;i++) { if(a[i]>a[i+1]) Swap11(a,i,i+1); } right--; for(int j=right;j>left;j--) { if(a[j]<a[j-1]) Swap11(a,j,j-1); } left++; } return; } int main11() { int a[]={12,8,20,5,9,16,7,30}; int len=sizeof(a)/sizeof(a[0]); CocktailSeq(a,len); for(int i=0;i<len;i++) { cout<<a[i]<<" "; } return 0; }
直接插入(稳定):拿到一张新牌,从后往前看;大于新牌,则往后移一位;小于或等于,则将新牌插入到后一位;
#include <iostream> using namespace std; //直接插入排序算法描述: /* 1、第一层循环:拿到元素。 2、第二层循环:从该元素的前一个位置开始,一直向前循环,若大于拿到的元素,则向后移一位;若小于该元素,则把该元素插入到后面一位的位置上 3、重复做以上动作,直至最后一个元素也插好了。 */ //==》O(n^2) void InsertSeq(int a[],int len) { for(int i=0;i<len;i++) { int tmp = a[i]; int j=i-1; while(j>=0 && a[j] > tmp) { a[j+1]=a[j]; j--; } a[j+1]=tmp; } return; } int main() { int a[]={12,8,20,5,9,16,7,30}; int len=sizeof(a)/sizeof(a[0]); InsertSeq(a,len); for(int i=0;i<len;i++) { cout<<a[i]<<" "; } }
==》改进1:二分插入排序(稳定)
代码:
#include <iostream> using namespace std; //直接插入排序的改进算法——二分查找定位插入算法描述: /* 1、第一层循环:拿到元素。 2、二分法定位插入位置(插入改位置的后面) 3、把定位后右面的元素 从后往前 依次向后移动一位。 4、把拿到的元素插进去 */ //==》O(n^2) void DivInsertSeq(int a[],int len) { for(int i=0;i<len;i++) { int tmp = a[i]; int left=0; int right=i-1; while(left<=right) { int mid=(left+right)/2; if(a[mid]>tmp) right=mid-1; else left=mid+1; } for(int j=i-1;j>left;j--) { a[j+1]=a[j]; } a[left]=tmp; } return; } int main() { int a[]={12,8,20,5,9,16,7,30}; int len=sizeof(a)/sizeof(a[0]); DivInsertSeq(a,len); for(int i=0;i<len;i++) { cout<<a[i]<<" "; } return 0; }
==》改进2:希尔排序(不稳定)
O(nlogn)
归并(稳定)
快排(不稳定)
堆排(不稳定)