第八章学习小结

本章学习了排序这一操作,排序方法分为两大类:

内部排序:不需要访问外存,分为插入类、交换类、选择类、归并类(2-路归并排序)和分配类(基数排序)。    

外部排序:不可能在内存中完成。

(一)插入排序

1、直接插入排序----稳定排序,更适合于初始记录基本有序(正序)的情况

 1 void InsertSort(SqList &L)
 2 {
 3     for(i=2; i<L.length; ++i)
 4     if(L.r[i].key<L.r[i-1].key) 
 5     {
 6         L.r[0]=L.r[i];     
 7            L.r[i]=L.r[i-1];      
 8            for(j=i-2; L.r[0].key<L.r[j].key; --j) 
 9                L.r[j+1]=L.r[j];    
10         L.r[j+1]=L.r[0];    
11     }
12 }

时间复杂度为O(n²),空间复杂度为O(1)。

2、折半插入排序----稳定排序,只能用于顺序结构,适合初始记录无序、n较大的情况

 1 void BiInsertSort(SqList &L) 
 2 {
 3     for(i=2; i<=L.length; ++i) 
 4     {
 5         L.r[0]=L.r[i];   
 6         low=l;  high=i-1;     
 7         while(low<=high)  
 8         {
 9             m=(low+high)/2;   
10             if(L.r[0].key<L.r[m].key)   high=m-1;    
11             else low=m+l;    
12         }    //while 
13         for(j=i-l;j>=high+l; --j)    
14             L.r[j+l]=L.r[j];  
15         L.r[high+l]=L.r[0];     
16     }
17 }

时间复杂度为O(n²),空间复杂度为O(1)。

3、希尔排序----不稳定排序,只能用于顺序结构,最后一个增量值必须等于1,适合初始记录无序、n较大时的情况

 1 void ShellInsert(SqList &L, int dk) 
 2 {//对顺序表L做一趟增量是dk的希尔插入排序 
 3     for(i=dk+l; i<=L.length; ++i) 
 4     if(L.r[i].key<L.r[i-dk].key)  
 5     {
 6         L.r[0]=L.r[i];    
 7         for(j=i-dk; j>0 && L.r[0].key<L.r[j].key; j-=dk) 
 8             L.r[j+dk]=L.r[j];  
 9         L.r[j+dk]=L.r[0];  
10     }  
11 }
12 void ShellSort(SqList &L, int dt[], int t) 
13 {
14     for (k=0; k<t; ++k) 
15     ShellInsert(L, dt[k]);  
16 }

时间复杂度为O(n3/2),空间复杂度为O(1)。

(二)交换排序

1、冒泡排序----稳定排序,算法平均性能比直接插入排序差

 1 void BubbleSort(SqList &L)
 2 {
 3     m=L.length-1; flag=1;     //flag用来标记某一趟排序是否发生交换
 4     while((m>0)&&(flag==1))
 5     {
 6         flag=0;   //flag置0,如果本趟排序没有发生交换,则不会执行下一趟排序
 7         for(j=1; j<=m; j++)
 8             if(L.r[j].key>L.r[j+1].key)
 9             {
10                flag=1;      //flag置为1,表示本趟排序发生了交换
11                t=L.r[j]; L.r[j]=L.r[j+1]; L.r[j+1]=t;//交换
12             }
13             --m;
14     }
15 }

时间复杂度为O(n²),空间复杂度为O(1)。

2、快速排序----不稳定排序,适合用于顺序结构,适合初始记录无序、n较大时的情况

 1 int Partition(SqList &L, int low, int high) 
 2 {//对顺序表1中的子表r[low .. high)进行一趟排序,返回枢轴位置 
 3     L.r[0]=L.r[low];  
 4     pivotkey=L.r[low].key;    //枢轴记录关键字保存在pivotkey中
 5     while(low<high)  
 6     { 
 7         while(low<high && L.r[high].key>=pivotkey)  --high; 
 8         L.r[low]=L.r[high];   //将比枢轴记录小的记录移到低端 
 9         while(low<high && L.r[low].key<=pivotkey)   ++low; 
10         L.r[high]=L.r[low];   //将比枢轴记录大的记录移到高端 
11     }
12     L.r[low]=L.r[0];   
13     return low;   
14 }
15 void QSort(SqList &L, int low, int high) 
16 {
17     if(low<high) 
18     {
19         pivotloc=Partition(L, low, high);    
20         QSort(L, low, pivotloc-1);     //对左子表递归排序 
21         QSort(L, pivotloc+l, high);    //对右子表递归排序 
22     }
23 }
24 void QuickSort(SqList &L) 
25 {
26     QSort(L, 1, L.length); 
27 }

平均情况下,快速排序的时间复杂度为O(nlog2n)。

最好情况下的空间复杂度为O(log2n)--递归要用到栈空间,最坏情况下为O(n)。

(三)选择排序

1、简单选择排序/直接选择排序----稳定排序,比直接插入排序快

 1 void SelectSort(SqList &L) 
 2 {
 3     for(i=1; i<L.length; ++i)
 4     { 
 5         k=i;  
 6         for(j=i+l; j<=L.length; ++j) 
 7         if(L.r[j].key<L.r[k].key)   k=j;   
 8         if(k!=i) 
 9             {t=L.r[i; L.r[i]=L.r[k]; L.r[k]=t;}   
10     }//for
11 }

时间复杂度为O(n²),空间复杂度为O(1)。

2、树形选择排序/锦标赛排序

3、堆排序----不稳定排序,只能用于顺序排序

 1 //1.调整堆----筛选法
 2 void HeapAdjust(SqList &L, int s, int m)
 3 {
 4     rc=L.r[s];
 5     for(j=2*s; j<m; j*=2)  
 6     {
 7         if(j<m && L.r[j].key<L.r[j+1].key)    ++j;    
 8             if(rc.key>=L.r[j].key)   break; 
 9             L.r[s]=L.r[j];   s=j;
10     }
11     L.r[s]=rc;   
12 }
13 //2.初建堆
14 void CreatHeap(SqList &L) 
15 {//把无序序列L.r[l..n]建成大根堆 
16     n=L.length; 
17     for(i=n/2;i>O; --i)  
18         HeapAdjust(L,i,n); 
19 } 
20 //3.堆排序算法的实现 
21 void HeapSort(SqList &L) 
22 {
23     CreatHeap(L);  
24     for(i=L.length; i>l; --i) 
25     {
26         x=L.r[1];
27         L.r[1]=L.r[i]; 
28         L.r[i]=x; 
29         HeapAdjust(L, 1, i-1)   
30     }
31 } 

堆排序在最坏的情况下,其时间复杂度也为O(nlog2n),空间复杂度为O(1)。

实验研究表明,平均性能接近于最坏性能。

(五)归并排序----稳定排序

 1 void MSort(RedType R[], RedType &T[], int low, int high) 
 2 { 
 3     if(low==high)   T[low]=R[low]; 
 4     else 
 5     {
 6         mid=(low+high)/2;   
 7         MSort(R, S, low, mid); 
 8         MSort(R, S, mid+l, high);
 9         Merge(S, T, low, mid, high);
10     } 
11 } 
12 void MergeSort(SqList &L) 
13 {
14     MSort(L.r, L.r, 1, L.length); 
15 }

时间复杂度为O(nlog2n),空间复杂度为O(n)。

各种内部排序方法的比较:

posted on 2020-07-12 18:12  周淑霞  阅读(149)  评论(0编辑  收藏  举报