查找和排序
查找
-
静态查找表
-
顺序查找
(1)对表的限制少
(2)同时适用于顺序存储结构和链式存储结构
(3)时间性能最差
(4)等概率查找成功ASL:(n+1)/ 2
-
折半查找
(1)要求:必须是顺序存储且按关键字值有序排列
(2)效率高
-
-
动态查找表
- 二叉排序树
- 平衡二叉树
-
哈希表
内部排序
-
插入类
-
直接插入排序
(1)稳定
(2)时间复杂度:n^2
(3)代码:
void InsertionSort ( SqList &L ) { // 对顺序表 L 作直接插入排序。 for ( i=2; i<=L.length; ++i ) if (L.r[i].key < L.r[i-1].key) { L.r[0] = L.r[i]; // 复制为监视哨 for ( j=i-1; L.r[0].key < L.r[j].key; -- j ) L.r[j+1] = L.r[j]; // 记录后移 L.r[j+1] = L.r[0]; // 插入到正确位置 } } // InsertSort
-
折半插入排序
(1)稳定
(2)时间复杂度:nlogn
-
希尔排序(缩小增量排序)
(1)不稳定
(2)时间复杂度:n*(logn)^2
(3)代码
void ShellInsert ( SqList &L, int dk ) { for ( i=dk+1; i<=n; ++i ) if ( L.r[i].key< L.r[i-dk].key) { L.r[0] = L.r[i]; // 暂存在R[0] for (j=i-dk; j>0&&(L.r[0].key<L.r[j].key); j-=dk) L.r[j+dk] = L.r[j]; // 记录后移,查找插入位置 L.r[j+dk] = L.r[0]; // 插入 } // if } // ShellInsert void ShellSort (SqList &L, int dlta[], int t) { // 增量为dlta[]的希尔排序 for (k=0; k<t; ++k) ShellInsert(L, dlta[k]); //一趟增量为dlta[k]的插入排序 } // ShellSort
-
-
交换类
-
冒泡排序
(1)稳定的
(2)时间复杂度:n^2
(3)代码
void BubbleSort( SqList &L ) { //对顺序表L作冒泡排序 for(i=2; i<=L.length; i++) { //进行n-1趟扫描 move=False ; //move是交换与否的标志 for( j=n; j<=i; j- - ) if( L.R[ j ] < L.R[ j-1] ) { //如逆序则交换 L.R[ j ]↔L.R[ j-1]; //这里只是描述 move=True; } if ( !move ) return; //如果没有移动发生,则结束 } }
-
快速排序
(1)不稳定
(2)平均时间复杂度:nlogn
(3)代码
int partition( SqList &L, int low, int high ) { //对排序区间L.R[low..high]进行一次分区,返回基准位置下标 pivotkey=L.R[low].key; i=low; j=high; L.R[0]=L.R[low]; while( i<j ) { while(j>i&&L.R[ j ].key>=pivotkey) j--; //i指向基准,j向左扫描 L.R[ i ] = L.R[ j ]; // 比基准小的记录移到低端 while(i<j&&L.R[ i ].key<=pivotkey) i++; //j指向基准,i向右扫描 L.R[ j ] = L.R[ i ]; // 比基准大的记录移到高端 } L.R[ i ] = L.R[0]; //基准到位 return i; //返回基准的位置下标 } void Qsort( SqList &L, int low, int high ) { //对排序区间L.R[low..high]进行快速排序 if( low < high ) { pivotloc=partition( L, low, high ); //进行分区,返回基准下标 Qsort(L, low, pivotloc-1) ; // 对左半区进行快速排序 Qsort(L, pivotloc+1, high) ; // 对右半区进行快速排序 } } void QuickSort( SqList &L) { // 对整个顺序表进行快速排序 Qsort( L, 1, L.length ); }
-
-
选择类
-
简单选择排序
(1)不稳定
(2)时间复杂度:n^2
(3)代码
void SelectSort( SqList &L ) { //对顺序表L作简单选择排序 for(i=1; i<L.length; i++){ min=i; for (j=i+1;j<=L.length;j++) //选最小的记录 if (L.R[j].key<L.R[min].key) min=j; if (i!=min) L.R[min]↔L.R[i]; //与无序区第一条记录交换 }//end for }
-
堆排序
(1)不稳定
(2)时间复杂度:n*logn
(3)代码:
void HeapAdjust ( SqList &H, int s, int m ) { //已知H.R[s+1..m]满足大顶堆定义 //调整H.R[s],使得H.R[s..m]成为大顶堆 rc=H.R[s]; for(j=2*s; j<=m; j*=2){ if(j<m && H.R[j].key<H.R[j+1].key) j++; if(rc.key>=H.R[j].key) break; H.R[s]=H.R[j]; s=j; } H.R[s]=rc; } void HeapSort ( SqList &H ) { //把H.R[1..H.length]建成大顶堆 for (i=H.length/2; i>0; i--) HeapAdjust(H, i, H.length); //堆排序 for(i=H.length; i>1; i--) { H.R[1]<->H.R[i]; HeapAdjust(H, 1, i-1); } }
-
-
归并类
-
归并排序
(1)稳定
(2)时间复杂度:nlogn
(3)代码
//递归 void Merge(RecType SR[], RecType &TR[], int i, int m, int n){ //将有序的SR[i..m]和SR[m+1..n]归并为有序的TR[i..n] for(j=m+1,k=i; i<=m&&j<=n; ++k){ if(SR[i].key<=SR[j].key) TR[k]=SR[i++]; else TR[k]=SR[j++]; } if(i<=m) TR[k..n]=SR[i..m]; if(j<=n) TR[k..n]=SR[j..n]; } //end Merge void MSort(RecType SR[], RecType &TR1[], int s, int t){ //将SR[s..t]归并排序为TR1[s..t] RecType TR2[n]; //定义辅助数组TR2 if(s==t) TR1[s] = SR[s]; else { m=(s+t)/2; //将SR[s..t]平分为SR[s..m]和SR[m+1..t] MSort(SR, TR2, s, m); //SR[s..m]排序成TR2[s..m] MSort(SR, TR2, m+1, t);//SR[m+1..t]排序成TR2[m+1..t] Merge(TR2, TR1, s, m, t); //两个有序的相邻区间归并 } } //end MSort void MergeSort(SqList &L) //对顺序表L作归并排序 MSort(L.r, L.r, 1, L.length); } //end MergeSort //非递归 void Merge(RcdType SR[ ], RcdType TR[ ], int i, int m, int n) { //将有序的SR[i..m]和SR[m+1..n]异地归并为有序的TR[i..n] for (j=m+1, k=i; i<=m&&j<=n; k++) { if ( SR[ i ].key<=SR[ j ].key ) TR[ k ]=SR[ i++ ]; else TR[ k ]=SR[ j++ ]; } if ( i<=m ) TR[ k . . n ]=SR[ i . . m ]; if ( j<=m ) TR[ k . . n ]=SR[ j . . n ]; } void MergePass(RcdType SR[ ], RcdType TR[ ], int L, int n) { //对SR[1..n]进行趟归并排序,结果放入TR中,L是子表的长度 for (i=1; i+2*L-1<=n; i+=2*L) Merge(SR,TR,i,i+L-1,i+2*L-1); //相邻子表SR[i..i+L-1]和SR[i+L..i+2*L-1]进行归并 if(i+L-1)<n) //还剩两个子表, 但最后一个子表长度不足L Merge(SR,TR,i,i+L-1,n); else //还剩一个子表,直接抄入TR TR[i..n]=SR[i..n]; } void MergeSort ( SqList &L ) { //对排序表L进行归并排序 RcdType *TR; TR=new [(sizeof(RcdType)*L.length)]; //辅助数组 for(int L=1; L<n; L*=2){ MergePass(L.R,TR,L,L.length); //一趟归并,结果存入TR中 L*=2; //将子表长度扩大一倍 MergePass(TR,L.R,L,L.length); //一趟归并,结果存入L.r中 } //end for free(TR); }
-
-
其他类
- 基数排序
- 注意:代码中涉及一些没有写完整的部分,本文中的代码块仅仅是提供一些思路。