【C/C++】排序总结
#pragmaonce#include<iostream>#include<assert.h>usingnamespacestd;//直接排序:指的是设定2个下标/指针。然后从下标1开始进行比较,//升序情况下:若在前的下标/指针大于当前比较数值。就进行数组的后移。//直到满足当前序列值。然后最终将当前比较数值进行替换。//PS:总有一个指针遍历比较数组(k,arry[i])//时间复杂度为:0(n^2),空间复杂度0(1)voidInsertSort(int*arry,intlen){assert(arry);for(inti=1;i<len;++i){intj=i-1;intk=arry[i];while(j>-1&&arry[j]>k){arry[j+1]=arry[j];--j;}arry[j+1]=k;}}//希尔排序:在直接排序的基础上增加分组Gap值,//利用Gap值,比较对应(len/gap)*i的位置。每个位置代表一个分组//然后将i的值依次增加到len-gap的位置相当于我已经比较了每个对应分组,使当前序列趋近于有序。//然后我们缩小gap值的范围,使其接近于2,证明还需要进行分组排序。//0(n^2),0(1);voidShellSort(int*arry,intlen){assert(arry);intgap=len;while(gap>1){gap=gap/3+1;for(inti=0;i<len-gap;++i){intj=i;intk=arry[i+gap];while(j>-1&&arry[j]>k){arry[j+gap]=arry[j];j-=gap;}arry[j+gap]=k;}}}//选择排序:其实这个排序的思路比较简单,我们只需要每次遍历数组//得到最小/最大(或者2者都选),然后将最大值最小值分别丢到数组的最左端还有最右端然后缩小范围就可以了。//然后值得注意的是。我们在同时得出当前最大最小值时候,需要注意//当前选出的最大值最小值在进行其中一次交换后,会不会将max与min相交换。//0(n^2),0(1)voidSelectSort(int*arry,intlen){assert(arry);for(inti=0,j=len-1;i<j;++i,--j){intmin=i;intmax=j;for(intk=i;k<=j;++k){if(arry[k]<arry[min]){min=k;}if(arry[k]>arry[max]){max=k;}if(min!=i){inttemp=arry[min];arry[min]=arry[i];arry[i]=temp;if(max==i)max=min;}if(max!=j){inttemp=arry[max];arry[max]=arry[j];arry[j]=temp;}}}}//冒泡排序:冒泡排序比较简单,就不多说了。//需要注意的是我们可以利用一个标记值来确定我们需不需要进行这一次的冒泡//如果需要进行冒泡的话我们的标记值就会设置位开关。//然后我们就可以减少我们所需要排序的次数。//0(n^2),0(1)voidBubbleSort(int*arry,intlen){assert(arry);for(inti=0;i<len-1;++i){for(intj=len-1;j>=i;--j){if(arry[j]<arry[j-1]){inttemp=arry[j];arry[j]=arry[j-1];arry[j-1]=temp;}}}}//快速排序:我们快速排序的大概思路就是选择一头一尾的2个下标/指针,然后我们利用指针选择法//将大数与小数集中排列。将我们所选的key值建为关键值,大于放左边,小于放右边。然后不断缩小范围就好了//提高效率的办法就是我们可以在当前序列的值小于某个数值的时候我们选择使用插入排序。//这可以有效的提高我们排序的效率。//一前一后只适用于数组。//0(nlogn),0(logn)int_QuickSort(int*arry,intleft,intright){assert(arry);if(left>=right)return0;inttmp=arry[right];intindex=right;--right;while(left<right){while(left<right&&arry[left]<=tmp)++left;while(left<right&&arry[right]>=tmp)++right;if(left<right){swap(arry[left],arry[right]);}}if(tmp<=arry[right]){swap(arry[right],arry[index]);}returnright;}voidQuickSort(int*arry,intleft,intright){assert(arry);if(left<right){intmid=_QuickSort(arry,left,right);QuickSort(arry,mid+1,right);QuickSort(arry,left,mid-1);}}//快速排序:前后指针,我们选择一个紧紧跟随的2个指针,原理跟一前一后相同,知识进行了大数小数的堆置、//这样的方法可以利用到指针中,当然了,key值得选择很重要,//最坏的情况就是选择到了有序数组的最大数/最小数,就会出现最坏的情况。//选择3数取中法可以有效地避免这个情况的出现。voidswap(int*arry,intleft,intright){inttmp;tmp=arry[left];arry[left]=arry[right];arry[right]=tmp;}voidQuickSort_On(int*arry,intleft,intright){inti,last;if(left>=right)return;swap(arry,left,(left+(right-left)/2));last=left;for(i=left+1;i<=right;++i){if(arry[i]<arry[left])swap(arry,++last,i);}swap(arry,left,last);QuickSort_On(arry,left,last-1);QuickSort_On(arry,last+1,right);}//归并排序:利用树的分支然后在利用区间的整合,实现排序完成。//每次我们确定一个区间(n/2),然后不断进行2分的拆分。//在没2个区间中我们进行比较排序,对每个区间的首部进行比较,然后规整到我们需要保存的数组中。//最后我们通过不断的拆分,不断地归并复制,就可以出现相对的排序序列了。//0(nlogn),0(n)voidMerge(int*arry,int*dest,intbegin1,intend1,intbegin2,intend2){intindex=begin1;while(begin1<=end1&&begin2<=end2){if(arry[begin1]<arry[begin2]){dest[index++]=arry[begin1++];}else{dest[index++]=arry[begin2++];}}if(begin1<=end1){while(begin1<=end1){dest[index++]=arry[begin1++];}}else{while(begin2<=end2)dest[index++]=arry[begin2++];}}void_Merge(int*arry,int*dest,intleft,intright){//因为是左闭右开。intmid=left+((right-left)/2);if(left<right-1){//intmid=left+((right-left)>>1);_Merge(arry,dest,left,mid);_Merge(arry,dest,mid+1,right);Merge(arry,dest,left,mid,mid+1,right);//memcpy(arry+left,dest+left,sizeof(int)*(right-left+1));}Merge(arry,dest,left,mid,mid+1,right);memcpy(arry+left,dest+left,sizeof(int)*(right-left+1));}voidMergeSort(int*arry,size_tsize){int*dest=newint[size];_Merge(arry,dest,0,size-1);//memcpy(arry,dest,sizeof(int)*(11));delete[]dest;}
总结:
其中时间复杂度为nlogn的有快速排序,归并排序,堆排序。其中快速排序最坏的情况是n^2,其余都是n^2,希尔排序介于n-n^2之间。
对于稳定性来说,冒泡排序,插入排序,归并排序是稳定的,其他的排序在不同的情况下稳定性会不同。
对于空间复杂度来说,快速排序的空间复杂度是0(logn),归并排序是0(n)
下面是只能在限定条件里面使用的基数排序和计数排序:
计数排序:时间复杂度:O(N), 空间复杂度O(最大数-最小数)
基数排序:时间复杂度:O(N*位数),空间辅助度O(N)
//基数排序:利用哈希桶原理把数据排序,可选择从低位到高位或从高位到低位//利用稀疏矩阵压缩存储进行数据定位intGetDigit(int*arr,size_tsize){intmaxDigit=1;intmaxNum=10;for(inti=0;i<size;++i){if(arr[i]>=maxNum){intcount=maxDigit;while(maxNum<=arr[i]){maxNum*=10;++count;}maxDigit=count;}}returnmaxDigit;}voidLSDSort(int*arr,size_tsize)//从低位开始排MSD从高位开始排{intcounts[10]={0};//存位数对应数据个数intstartCounts[10]={0};int*bucket=newint[size];intdigit=1;//表示先取各位intmaxDigit=GetDigit(arr,size);intdivider=1;//除数while(digit++<=maxDigit){memset(counts,0,sizeof(int)*10);memset(startCounts,0,sizeof(int)*10);for(inti=0;i<size;++i)counts[(arr[i]/divider)%10]++;for(inti=1;i<10;++i)startCounts[i]=startCounts[i-1]+counts[i-1];for(inti=0;i<size;++i){bucket[startCounts[(arr[i]/divider)%10]++]=arr[i];}divider*=10;memcpy(arr,bucket,sizeof(int)*size);}memcpy(arr,bucket,sizeof(int)*size);delete[]bucket;}//计数排序voidCountSort(int*arr,size_tsize,intlen){int*bitMap=newint[len];memset(bitMap,0,sizeof(int)*len);for(inti=0;i<size;++i){intindex=arr[i]>>5;//除以32intcount=arr[i]%32;bitMap[index]|=(1<<count);}intindex=0;for(inti=0;i<len;++i){intcount=0;while(count<32&&index<size){if(bitMap[i]&(1<<count))arr[index++]=i*32+count;++count;}}delete[]bitMap;}
这两个排序的使用环境只能够在特定的条件下使用,所以没有纳入常规的排序手法中,但是可以看出他的效率十分惊人。
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。