尋找有多少種
/*
1.順序尋找法
2.折半尋找法
3.分塊尋找法
*/
折半尋找法
/*1.前提是必須採用順序儲存2.必須按照關鍵字大小有序排序*/int BinSearch(RecordList l,KeyType k){int low=1,high=l.length;while(low <= high){mid=(low+high)/2;if(k == l.r[mid].key)return mid;else if(k < l.r[mid].key)high=mid-1;elselow=mid+1;}return -1;}基於樹的尋找法
/*
二叉排序樹又稱為二叉尋找樹,是一種特殊的二叉樹
二叉排序樹的插入與建立(演算法思想)
1.若二叉樹是空樹,則S成為二叉排序樹的根
2.若二叉樹非空,則將S.key與二叉排序樹根節點的關鍵字進行比較
2.1如果key的值等於根節點的值,則停止插入
2.2如果key的值小於根節點的值,則S插入左子樹
2.3如果key的值大於根節點的值,則S插入右子樹
*/
二叉樹尋找的遞迴演算法
BSTree SearchBST(BSTree bst,KeyType key){if(!bst)return bst;else if(bst->key==key)return bst;else if(bst->key>key)return SearchBST(bst->lchild,key);else return SearchBST(bst->rchild,key);}二叉排序樹的非遞迴演算法
BSTree SearchBST(BSTree bst,KeyType key){BSTree q;q=bst;while(q){if(q->key == key)return q;if(q->key > key)q=q->lChild;elseq=q->rChild;}return NULL;}穩定與不穩定
/*
如果兩個數無論怎麼放置,排序到最後都是一個順序,那麼這種演算法叫做穩定的。
如果排序到最後,兩個數發生變化了,那麼這種演算法叫做不穩定的。
*/
排序演算法直接插入排序
void InsertSort(RecordType r[],int length){for(int i=2;i<=length;i++){r[0]=r[i];//要插入的數字,r[0]是監視哨j=i-1;while(r[0].key<r[j].key){r[j+1]=r[j];j--;}}}折半插入排序
void BinSort(RecordType r[],int length){for(int i=2;i<=length;i++){x=r[i];low=1;high=i-1;while(low<=high){//確定插入位置mid=(low+high)/2;if(x.key<r[mid].key)high=mid-1;elselow=mid+1;}//移動位置for(j=i-1;j>=low;--j){r[j+1]=r[j];}r[low]=x;}}希爾排序,縮小增量排序法
/*
演算法思想
利用了直接插入排序的最佳性質:當有序的時候,時間複雜度可以提高到O(n);
1.將待排序的關鍵字序列分成若干個較小的子序列,對子序列進行直接插入排序,使真箇排序排好序
2.進行直接插入排序
*/
交換類排序之冒泡排序,相鄰兩個比較,然後,最大(小)的冒泡到最後
Void BubbleSort(RecordType r[],int length){n=length;change=true;for(int i=1;i<n-1&&change;++i){change=false;for(int j=1;j<n-i;++j){if(r[j].key>r[j+1].key){x=r[j];r[j]=r[j+1];r[j+1]=x;change=true;}}}}交換類排序之快速排序演算法
void QKSort(RecordType r[],int low,int high){if(low < high){position=QKPass(r,low,high);QKSort(r,low,position-1);QKSort(r,position+1,high);}}int QKPass(RecordType r[],int left,int right){x=r[left];low=left,high=right;while(low<high){while(low<high&&r[high].key>x.key)high--;if(low<high){r[low]=r[high];low++;}while(low<high&&r[low].key<x.key)low++;if(low<high){r[high]=r[low];high--;}}r[low]=x;//將基準記錄記錄到low==high的地方return low;//返回基準記錄位置}選擇類排序演算法(簡單選擇排序)
Void SimpleSort(RecordType r[],int length){n=length;for(int i=0;i<length;i++){for(j=i+1;j<length;j++){if(r[j]>r[i]){//交換類代碼都可以如下a=a+b;b=a-b;a=a-b;x=r[i];r[i]=r[j];r[j]=x;}}}}歸併排序
//2路歸併排序的遞迴演算法
void MSort(RecordType r1[],int low,int high,RecordType r3[]){/*r1排好序以後放到r3中,r2是個輔助空間*/RecordType r2[N];if(low == high){r3[low]=r1[low];}else{mid=(low+high)/2;MSort(r1,low,mid,r2);MSort(r1,mid,high,r2);Merge(r2,low,mid,high,r3);}}void Merge(RecordType r2[],int low,int mid,int high,RecordType r3[]){//合并兩個有序的數組,合并到r3中i=low; j=mid+1; k=low;while((i<=mid)&&(j<=high)){if(r2[i]<r2[j]){r3[k]=r2[i];i++;}else{r3[k]=r2[j];j++;}k++;}//配置數組剩餘的資料while(i<=mid){r3[k]=r2[i];k++;i++;}while(j<high){r3[k]=r2[j];j++;k++;}}
9.7 各種排序方法的綜合比較
首先,我們從演算法的平均時間複雜度、 最壞時間複雜度、以及演算法所需的輔助儲存空間三方面,對各種排序方法加以比較,如表9-1所示。其中簡單排序包括除希爾排序以外的其它插入排序、起泡排序、和簡單選擇排序。
表9-1 各種排序方法的效能比較
排序方法 |
平均時間複雜度 |
最壞時間複雜度 |
輔助儲存空間 |
簡單排序 |
O(n2) |
O(n2) |
O(1) |
快速排序 |
O(nlogn) |
O(n2) |
O(logn) |
堆排序 |
O(nlogn) |
O(nlogn) |
O(1) |
歸併排序 |
O(nlogn) |
O(nlogn) |
O(n) |
基數排序 |
O(d(n+rd)) |
O(d(n+rd)) |
O(rd) |
綜合分析和比較各種排序方法,可以得出以下結論:
l 簡單排序一般只用於n較小的情況。當序列中的記錄“基本有序”時,直接插入排序是最佳的排序方法,常與快速排序、歸併排序等其它排序方法結合使用。
l 快速排序、堆排序和歸併排序的平均時間複雜度均為O(nlogn),但實驗結果表明,就平均時間效能而言,快速排序是所有排序方法中最好的。遺憾的是,快速排序在最壞情況下的時間效能為O(n2)。堆排序和歸併排序的最壞時間複雜度仍為O(nlogn),當n較大時,歸併排序的時間效能優於堆排序,但它所需的輔助空間最多。
l 基數排序的時間複雜度可以寫成O(d*n)。因此,它最適用於n值很大而關鍵字的位元d較小的序列。
l 從排序的穩定性上來看,基數排序是穩定的,除了簡單選擇排序,其它各種簡單排序法也是穩定的。然而,快速排序、堆排序、希爾排序等時間效能較好的排序方法,以及簡單選擇排序都是不穩定的。多數情況下,排序是按記錄的主關鍵字進行的,此時不用考慮排序方法的穩定性。如果排序是按記錄的次關鍵字進行的,則應充分考慮排序方法的穩定性。
綜上所述,每一種排序方法各有特點,沒有哪一種方法是絕對最優的。我們應根據具體情況選擇合適的排序方法,也可以將多種方法結合起來使用。