希尔排序数组
这里内部用了直接插入的方法;优化
1 void HashSort(int a[],int n){ 2 int i,j,temp; 3 int gap=n; 4 do{ 5 gap=gap/3+1; 6 for(i=gap;i<n;i++){ 7 if(a[i]<a[i-gap]){ 8 temp=a[i]; 9 //注:这里要手动检测越界问题 10 for(j=i-gap;a[j]>temp && j>=0;j-=gap) 11 a[j+gap]=a[j]; 12 a[j+gap]=temp; 13 } 14 } 15 }while(gap>1); 16 }
堆排序ui
对选择排序的改进,每次找最小值的时候没有利用上次的结果,因此将记录所有存入彻底二叉树中,构造大顶堆或小顶堆,每次取一个极值,这样就能够利用前一次的比较结果了spa
彻底二叉树的特色:code
其实也不须要构造二叉树,须要将数组放弃0下标位置用其余下标对应相应彻底二叉树结点便可blog
1 //i:规范位置;n:堆的结点树 2 void HeapAdjust(int a[],int i,int n){ 3 int k=a[i],j=i; 4 for(j*=2;j<n;j*=2){ 5 //找到子结点中较大的那个 6 if(j+1<n && a[j+1]>a[j]) 7 j++; 8 //较大的子结点小于根节点就退出 9 if(k>=a[j]) 10 break; 11 //较大的子结点覆盖双亲结点 12 //覆盖后,较大子结点这个位置就是新的规范位置 13 a[i]=a[j]; 14 i=j; 15 } 16 //退出循环后就说明,位置是已经规范,直接将规范值赋到该处便可 17 a[i]=k; 18 } 19 20 void HeapSort(int a[],int n){ 21 int i,k; 22 //构建大顶堆 23 for(i=n/2;i>0;i--){ 24 HeapAdjust(a,i,n); 25 } 26 //循环将顶部最大值与尾部交换 27 for(;n>1;n--){ 28 k=a[1]; 29 a[1]=a[n-1]; 30 a[n-1]=k; 31 //交换后恢复大顶堆 32 HeapAdjust(a,1,n-1); 33 } 34 }
快速排序排序
冒泡排序有类似的原理递归
1 int partition(int a[],int low,int high){ 2 //令0下标位置记录为标准数 3 int sign=a[low]; 4 while(low<high){ 5 //注:下面两循环中若与标志为相等也交换的话,那么将死循环,这个与标志数相等的数将和标准数互相一直换下去 6 //比标准数大的放左边 7 //由于上面的标志数直接取了low位置,因此下面直接覆盖便可,不须要交换,退出循环后直接将标志数赋在应有位置 8 while(low<high && a[high]>=sign) 9 high--; 10 a[low]=a[high]; 11 //比标准数小的放右边 12 while(low<high && a[low]<=sign) 13 low++; 14 a[high]=a[low]; 15 } 16 //退出循环以后low=high,且这个位置存放的就是标准数 17 a[low]=sign; 18 return low; 19 } 20 21 void QSort(int a[],int low,int high){ 22 int sign; 23 if(low<high){ 24 sign=partition(a,low,high); 25 QSort(a,low,sign-1); 26 QSort(a,sign+1,high); 27 } 28 } 29 30 void QuickSort(int a[],int n){ 31 QSort(a,0,n-1); 32 }
其实快速排序法适用于规模较大的排序,而直接插入法则对规模较小的排序效率较高(长度分界为7),因此在快速排序中对长度小于7的排序段用直接插入法就能够进一步优化快速排序it
1 void QSort(int a[],int low,int high){ 2 int sign; 3 if((high-low)>7){ 4 sign=partition(a,low,high); 5 QSort(a,low,sign-1); 6 QSort(a,sign+1,high); 7 }else{ 8 InsertSort(k+low,high-low+1); 9 } 10 }
固然,快速排序法中有两次递归调用,也是能够利用伪递归的方法对其进行更深一步的优化io