排序

冒泡排序(Bubble Sort)??種交換排序,它的基本思想就是:?兩兩?較相鄰的記錄的關(guān)鍵字,如果反序則交換,直到?jīng)]有反序的記錄為?

兩兩比較,往上移動 -> 第二層遍歷是從 尾部開始的

遍歷中, 沒有任何數(shù)據(jù)的交換動作 -> 數(shù)據(jù)是有序的

void BubbleSort(SqList *L){

? ? int?i,j;

? ? //flag用作標(biāo)記

? ? Status flag =TRUE;

? ? //I 從[1,L->length) 遍歷;

? ? //如果flag為False退出循環(huán). 表示已經(jīng)出現(xiàn)過一次j從L->Length-1 到 i的過程,都沒有交換的狀態(tài);

? ? for(i =1; i < L->length&& flag; i++) {

? ? ? ? //flag 每次都初始化為FALSE

? ? ? ? flag =FALSE;

? ? ? ? for(j = L->length-1; j>=i; j--) {

? ? ? ? ? ? if(L->r[j] > L->r[j+1]){

? ? ? ? ? ? //交換L->r[j]和L->r[j+1]值;

? ? ? ? ? ? swap(L, j, j+1);

? ? ? ? ? ? //如果有任何數(shù)據(jù)的交換動作,則將flag改為true;

? ? ? ? ? ? flag =?TRUE;

? ? ? ? ? ? }

? ? ? ? }

? ? ? ? if?(!flag)?break;

? ? }

}

直接插?排序算法(Stight Inserton Sort)的基本操作是將?個記錄插?到已經(jīng)排好序的有序表中,從?得到?個新的,記錄數(shù)增1的有序表

從第二個元素開始,往已經(jīng)排好序的數(shù)據(jù)中插入

void InsertSort(SqList *L){

? ? int?i,j;

? ? int?temp=0;

? ? //假設(shè)排序的序列集是{0,5,4,3,6,2};

? ? //i從2開始的意思是我們假設(shè)5已經(jīng)放好了. 后面的牌(4,3,6,2)是插入到它的左側(cè)或者右側(cè)

? ? for(i=2;i<=L->length;i++)

? ? {

? ? ? ? //需將L->r[i]插入有序子表

? ? ? ? if(L->r[i]r[i-1])

? ? ? ? {

? ? ? ? ? ? //設(shè)置哨兵 可以把temp改為L->r[0]

? ? ? ? ? ? temp = L->r[i];

? ? ? ? ? ? for(j=i-1;L->r[j]>temp;j--)

? ? ? ? ? ? ? ? ? ? //記錄后移

? ? ? ? ? ? ? ? ? ? L->r[j+1]=L->r[j];

? ? ? ? ? ? //插入到正確位置 可以把temp改為L->r[0]

? ? ? ? ? ? L->r[j+1]=temp;

? ? ? ? }

? ? }

}

簡單排序算法(Simple Selecton Sort)?就是通過n-i次關(guān)鍵詞?較,從n-i+1個記錄中找出關(guān)鍵

字最?的記錄,并和第i(1<=i<=n)?個記錄進(jìn)?交換

找出最小值,放在第一位,依此類推...

void SelectSort(SqList *L){

? ? int?i,j,min;

? ? for(i =1; i < L->length; i++) {

? ? ? ? //① 將當(dāng)前下標(biāo)假設(shè)為最小值的下標(biāo)

? ? ? ? min = i;

? ? ? ? //② 循環(huán)比較i之后的所有數(shù)據(jù)

? ? ? ? for(j = i+1; j <= L->length; j++) {

? ? ? ? ? ? //③ 如果有小于當(dāng)前最小值的關(guān)鍵字,將此關(guān)鍵字的下標(biāo)賦值給min

? ? ? ? ? ? if(L->r[min] > L->r[j]) {

? ? ? ? ? ? ? ? min = j;

? ? ? ? ? ? }

? ? ? ? }

? ? ? ? //④ 如果min不等于i,說明找到了最小值,則交換2個位置下的關(guān)鍵字

? ? ? ? if(i!=min)

? ? ? ? ? ? swap(L, i, min);

? ? }

}

堆排序

堆結(jié)構(gòu):堆是一個的完全?叉樹。具備完全?叉樹的特點(diǎn),左結(jié)點(diǎn),右結(jié)點(diǎn),父節(jié)點(diǎn),樹結(jié)點(diǎn)個數(shù)的 特點(diǎn)

?每個結(jié)點(diǎn)的值都?于或等于其左右孩?結(jié)點(diǎn)的值,稱為?頂堆

每個結(jié)點(diǎn)的值都小于或等于其左右孩?結(jié)點(diǎn)的值,稱為小頂堆

堆排序思路:

1. 將數(shù)據(jù)按照層序遍歷形成一個完全二叉樹, 按照?頂堆或?頂堆需求,對完全二叉樹進(jìn)行調(diào)整,調(diào)整的是非葉子結(jié)點(diǎn)

2. 將堆頂元素與末尾元素交換,將最?元素”沉"到數(shù)組末端;?

3. 重新調(diào)整結(jié)構(gòu),使其滿?堆定義,然后繼續(xù)交換堆頂元素與當(dāng)前末尾元素,反復(fù)執(zhí)?調(diào)整+交換步驟,直到整個序列有序

大頂堆調(diào)整函數(shù)

?條件: 在L.r[s...m] 記錄中除了下標(biāo)s對應(yīng)的關(guān)鍵字L.r[s]不符合大頂堆定義,其他均滿足;

?結(jié)果: 調(diào)整L.r[s]的關(guān)鍵字,使得L->r[s...m]這個范圍內(nèi)符合大頂堆定義.

void?HeapAjust(SqList *L,int?s,int?m){

? ? int?temp,j;

? ? //① 將L->r[s] 存儲到temp ,方便后面的交換過程;

? ? temp = L->r[s];

? ? //② j 為什么從2*s 開始進(jìn)行循環(huán),以及它的遞增條件為什么是j*2

? ? //因?yàn)檫@是顆完全二叉樹,而s也是非葉子根結(jié)點(diǎn). 所以它的左孩子一定是2*s,而右孩子則是2s+1;(二叉樹性質(zhì)5)

? ? for(j =2* s; j <=m; j*=2) {

? ? ? ? //③ 判斷j是否是最后一個結(jié)點(diǎn), 并且找到左右孩子中最大的結(jié)點(diǎn);

? ? ? ? //如果左孩子小于右孩子,那么j++; 否則不自增1. 因?yàn)樗旧砭捅扔液⒆哟?

? ? ? ? if(j < m && L->r[j] < L->r[j+1])

? ? ? ? ? ? ++j;

? ? ? ? //④ 比較當(dāng)前的temp 是不是比較左右孩子大; 如果大則表示我們已經(jīng)構(gòu)建成大頂堆了;

? ? ? ? if(temp >= L->r[j])

? ? ? ? ? ? break;

? ? ? ? //⑤ 將L->[j] 的值賦值給非葉子根結(jié)點(diǎn)

? ? ? ? L->r[s] = L->r[j];

? ? ? ? //⑥ 將s指向j; 因?yàn)榇藭rL.r[4] = 60, L.r[8]=60. 那我們需要記錄這8的索引信息.等退出循環(huán)時,能夠把temp值30 覆蓋到L.r[8] = 30. 這樣才實(shí)現(xiàn)了30與60的交換;

? ? ? ? s = j;

? ? }

? ? //⑦ 將L->r[s] = temp. 其實(shí)就是把L.r[8] = L.r[4] 進(jìn)行交換;

? ? L->r[s] = temp;

}

堆排序--對順序表進(jìn)行堆排序

void HeapSort(SqList *L){

? ? int?i;

? ? //1.將現(xiàn)在待排序的序列構(gòu)建成一個大頂堆;

? ? //將L構(gòu)建成一個大頂堆;

? ? //i為什么是從length/2.因?yàn)樵趯Υ箜敹训恼{(diào)整其實(shí)是對非葉子的根結(jié)點(diǎn)調(diào)整.

? ? for(i=L->length/2; i>0;i--){

? ? ? ? HeapAjust(L, i, L->length);

? ? }

? ? //2.逐步將每個最大的值根結(jié)點(diǎn)與末尾元素進(jìn)行交換,并且再調(diào)整成大頂堆

? ? for(i = L->length; i >1; i--){

? ? ? ? //① 將堆頂記錄與當(dāng)前未經(jīng)排序子序列的最后一個記錄進(jìn)行交換;

? ? ? ? swap(L,1, i);

? ? ? ? //② 將L->r[1...i-1]重新調(diào)整成大頂堆;

? ? ? ? HeapAjust(L,1, i-1);

? ? }

}

堆排序的時間復(fù)雜度為:O(nlogn)

堆排序是就地排序,空間復(fù)雜度為常數(shù):O(1)

歸并排序

合并

//③ 將有序的SR[i..mid]和SR[mid+1..n]歸并為有序的TR[i..n]

void?Merge(intSR[],intTR[],inti,intm,intn)

{

? ? int?j,k,l;

? ? //1.將SR中記錄由小到大地并入TR

? ? for(j=m+1,k=i;i<=m && j<=n;k++)

? ? {

? ? ? ? if?(SR[i]<SR[j])

? ? ? ? ? ? TR[k]=SR[i++];

? ? ? ? else

? ? ? ? ? ? TR[k]=SR[j++];

? ? }


? ? //2.將剩余的SR[i..mid]復(fù)制到TR

? ? if(i<=m)

? ? {

? ? ? ? for(l=0;l<=m-i;l++)

? ? ? ? ? ? TR[k+l]=SR[i+l];

? ? }

? ? //3.將剩余的SR[j..mid]復(fù)制到TR

? ? if(j<=n)

? ? {

? ? ? ? for(l=0;l<=n-j;l++)

? ? ? ? ? ? TR[k+l]=SR[j+l];

? ? }

}

1.遞歸實(shí)現(xiàn): 將數(shù)據(jù) 拆成長度1的子序列, 再將子序列兩兩進(jìn)行合并且排序

先拆分,后合并

//② 將SR[s...t] 歸并排序?yàn)?TR1[s...t];

void?MSort(int?SR[],int?TR1[],int?low,int?hight){

? ? int?mid;

? ? int?TR2[MAXSIZE+1];

? ? if(low == hight)

? ? ? ? TR1[low] = SR[low];

? ? else{

? ? ? ? //1.將SR[low...hight] 平分成 SR[low...mid] 和 SR[mid+1,hight];

? ? ? ? mid = (low + hight)/2;

? ? ? ? //2. 遞歸將SR[low,mid]歸并為有序的TR2[low,mid];

? ? ? ? MSort(SR, TR2, low, mid);

? ? ? ? //3. 遞歸將SR[mid+1,hight]歸并為有序的TR2[mid+1,hight];

? ? ? ? MSort(SR, TR2, mid+1, hight);

? ? ? ? //4. 將TR2[low,mid] 與 TR2[mid+1,hight], 歸并到TR1[low,hight]中

? ? ? ? Merge(TR2, TR1, low, mid, hight);

? ? }

}

//① 對順序表L進(jìn)行歸并排序

void MergeSort(SqList *L){

? ? MSort(L->r,L->r,1,L->length);

}

2.非遞歸實(shí)現(xiàn):

邊拆分,邊合并

邊拆分邊合并

//對SR數(shù)組中相鄰長度為s的子序列進(jìn)行兩兩歸并到TR[]數(shù)組中;

void?MergePass(int?SR[],int?TR[],int?s,int?length){

? ? int?i =1;

? ? int?j;

? ? //①合并數(shù)組

? ? //s=1 循環(huán)結(jié)束位置:8 (9-2*1+1=8)

? ? //s=2 循環(huán)結(jié)束位置:6 (9-2*2+1=6)

? ? //s=4 循環(huán)結(jié)束位置:2 (9-2*4+1=2)

? ? //s=8 循環(huán)結(jié)束位置:-6(9-2*8+1=-6) s = 8時,不會進(jìn)入到循環(huán);

? ? while(i<= length-2*s+1) {

? ? ? ? //兩兩歸并(合并相鄰的2段數(shù)據(jù))

? ? ? ? Merge(SR, TR, i, i+s-1, i+2*s-1);

? ? ? ? i = i+2*s;

? ? ? ? /*

?? ? ? ? s = 1,i = 1,Merge(SR,TR,1,1,2);

?? ? ? ? s = 1,i = 3,Merge(SR,TR,3,3,4);

?? ? ? ? s = 1,i = 5,Merge(SR,TR,5,5,6);

?? ? ? ? s = 1,i = 7,Merge(SR,TR,7,7,8);

?? ? ? ? s = 1,i = 9,退出循環(huán);

?? ? ? ? */

? ? ? ? /*

?? ? ? ? s = 2,i = 1,Merge(SR,TR,1,2,4);

?? ? ? ? s = 2,i = 5,Merge(SR,TR,5,6,8);

?? ? ? ? s = 2,i = 9,退出循環(huán);

?? ? ? ? */

? ? ? ? /*

?? ? ? ? s = 4,i = 1,Merge(SR,TR,1,4,8);

?? ? ? ? s = 4,i = 9,退出循環(huán);

?? ? ? ? */

? ? }

? ? //②如果i

? ? // 1 < (9-8+1)(2)

? ? //s = 8時, 1 < (9-8+1)

? ? if(i < length-s+1){

? ? ? ? //Merge(SR,TR,1,8,9)

? ? ? ? Merge(SR, TR, i, i+s-1, length);

? ? }else{

? ? ? ? //③只剩下一個子序列;

? ? ? ? for(j = i; j <=length; j++) {

? ? ? ? ? ? TR[j] = SR[j];

? ? ? ? }

? ? }

}

void MergeSort2(SqList *L){

? ? int?*TR = (int?*)malloc(sizeof(int) * L->length);

? ? int?k =1;

? ? //k的拆分變換是 1,2,4,8;

? ? while(k < L->length) {

? ? ? ? //將SR數(shù)組按照s=2的長度進(jìn)行拆分合并,結(jié)果存儲到TR數(shù)組中;

? ? ? ? //注意:此時經(jīng)過第一輪的歸并排序的結(jié)果是存儲到TR數(shù)組了;

? ? ? ? MergePass(L->r, TR, k, L->length);

? ? ? ? k =2*k;

? ? ? ? //將剛剛歸并排序后的TR數(shù)組,按照s = 2k的長度進(jìn)行拆分合并. 結(jié)果存儲到L->r數(shù)組中;

? ? ? ? //注意:因?yàn)樯弦惠喌呐判虻慕Y(jié)果是存儲到TR數(shù)組,所以這次排序的數(shù)據(jù)應(yīng)該是再次對TR數(shù)組排序;

? ? ? ? MergePass(TR, L->r, k, L->length);

? ? ? ? k =2*k;

? ? }

}

排序總結(jié)

排序總結(jié)

穩(wěn)定性解釋:排序后的元素相同元素的順序依然是排序之前的順序

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容