七大排序

来源:互联网 发布:约瑟夫环c语言视频 编辑:程序博客网 时间:2024/05/04 04:37

排序的分类:


ps:我在这里实现的排序算法,都是用数组来实现的。

1.插入排序

基本思想:将一个数插入到已排好序的数组中,从而得到一个新的,个数加1的数组。

ps:index为要插入的数的下标,pos为已排好序的数组的最后一个数的下标。

时间复杂度为:O(n^2)

void InsertSort(int* a,size_t n)  //按升序{for(size_t index=1;index<n;++index){int pos=index-1;int tmp=a[index];while(pos>=0&&a[pos]>tmp){a[pos+1]=a[pos];--pos;}a[pos+1]=tmp;}}
2.希尔排序

基本思想:它分为预排序和插入排序,预排序:实现跳跃性的排序。

时间复杂度为:O(nlogn)~O(n^2)

void ShellSort(int* a,size_t n){//1.预排序int gap=n;while(gap>1){gap=gap/3+1;  for(int index=gap;index<n;++index){    int tmp=a[index];int pos=index-gap;while(pos>=0&&a[pos]>tmp){a[pos+gap]=a[pos];pos-=gap;}a[pos+gap]=tmp;}}//2.插入排序InsertSort(a,n);}
3.选择排序

基本思想:每一趟选出一个最小值和最大值,分别插入到左右两边的位置。

时间复杂度:O(n^2)

void SelectSort(int* a,size_t n){int left=0;int right=n-1;int min,max;while(left<right){min=max=left;for(size_t i=left;i<=right;++i){if(a[i]<a[min])min=i;if(a[i]>a[max])max=i;}swap(a[left],a[min]);if(left==max)max=min;swap(a[right],a[max]);left++;--right;}}

4.堆排序

基本思想:将待排序的序列构成一个大堆,此时,整个序列的最大值就在堆顶,将它与堆数组的最后一位数交换,此时末尾就是最大值,将剩余的n-1个数重新调整为大堆,就会得到次大值,在交换,反复执行,就会得到一个语序序列。

时间复杂度为:O(nlogn)

void AdjustDown(int* a,int parent,size_t n)  //建大堆{int sub=parent*2+1;while(sub<n){if(sub<n-1&&a[sub]<a[sub+1])     ++sub;if(a[sub]>a[parent]){swap(a[sub],a[parent]);        parent=sub;            sub=parent*2+1;}elsebreak;}}void HeapSort(int* a,size_t n){//建大(小)堆for(int i=(n-2)/2;i>=0;--i){AdjustDown(a,i,n);}//排序for(int j=n-1;j>0;--j){swap(a[0],a[j]);AdjustDown(a,0,j);}}

5.冒泡排序

基本思想:亮亮比较相邻的数,如果反序就交换,知道没有反序的数为止。

时间复杂度为:0(n^2)

void BubbleSort(int* a,size_t n){int flag=false;for(int i=0;i<n-1;++i)  //趟数{for(int j=0;j<n-1-i;++j){if(a[j]>a[j+1]){swap(a[j],a[j+1]);flag=true;}}if(flag==false)break;}}

6.快速排序

基本思想:通过一趟排序将待排序的序列分割为独立的两部分,其中一部分的值均比另一部分的值小,则可分别对这两部分值继续进行排序,以达到整个序列有序的目的。

时间复杂度为:O(nlogn)


递归的写法:

void QuickSort(int* a,int begin,int end){//一趟排序//int pivo=PartSort1(a,begin,end);//int pivo=PartSort2(a,begin,end);int pivo=PartSort3(a,begin,end);if(begin<pivo-1)  //不止一个数QuickSort(a,begin,pivo-1);if(pivo+1<end)QuickSort(a,pivo+1,end);}
单趟排序有三种方法:

(1).左右指针法

//左右指针法int PartSort1(int* a,int begin,int end){int left=begin;int right=end;//int key=a[end];//三数取中法int mid=GetMidNum(a,begin,end);swap(a[mid],a[end]);int key=a[end];while(left<right){while(left<right&&a[left]<=key)left++;while(left<right&&a[right]>=key)right--;if(left<right)swap(a[left],a[right]);}swap(a[left],a[end]);return left;}
(2).挖坑法

//挖坑法int PartSort2(int* a,int begin,int end){//int key=a[end];//三数取中法int mid=GetMidNum(a,begin,end);swap(a[mid],a[end]);int key=a[end];int left=begin;int right=end;while(left<right){while(left<right&&a[left]<=key)left++;a[right]=a[left];while(left<right&&a[right]>=key)right--;a[left]=a[right];}a[left]=key;return left;}
(3).前后指针法

//前后指针法int PartSort3(int* a,int begin,int end){int prev=begin-1;int cur=begin;//找比key小的值就停下int mid=GetMidNum(a,begin,end);swap(a[mid],a[end]);int key=a[end];while(cur<end){if(a[cur]<key&&++prev!=cur)swap(a[prev],a[cur]);++cur;}swap(a[++prev],a[end]);return prev;}


非递归的写法:

void QuickSortNonR(int* a,int begin,int end){stack<int> s;s.push (begin);s.push (end);while(!s.empty ()){int right=s.top ();s.pop();int left=s.top();s.pop();int pivo=PartSort1(a,left,right);if(left<pivo-1)//不止一个数{s.push(left);s.push(pivo-1);}if(pivo+1<end){s.push(pivo+1);s.push(end);}}}


7.归并排序

时间复杂度为:O(nlogn)

void _MergeSort(int* a,int* tmp,int begin,int end){int mid=begin+(end-begin)/2;if(begin<mid)  //不止一个数{_MergeSort(a,tmp,begin,mid);}if(mid+1<end){_MergeSort(a,tmp,mid+1,end);}int begin1=begin;int end1=mid;int begin2=mid+1;int end2=end;int index=begin;while(begin1<=end1&&begin2<=end2)   //两个数组都不为空{if(a[begin1]<a[begin2])tmp[index++]=a[begin1++];elsetmp[index++]=a[begin2++];}while(begin1<=end1)  //不为空{tmp[index++]=a[begin1++];}while(begin2<=end2)  //不为空{tmp[index++]=a[begin2++];}for(size_t i=begin;i<=end;++i){a[i]=tmp[i];}}void MergeSort(int* a,size_t n){int* tmp=new int[n];_MergeSort(a,tmp,0,n-1);delete[] tmp;}









            

0 0
原创粉丝点击