八大排序演算法之歸併排序

2021-08-06 03:22:00 字數 3652 閱讀 3055

介紹到這裡只剩下歸併排序和基數排序沒有介紹過了。這兩種演算法各有各的特點,歸併排序是分治法的一種有效應用,

所謂歸併是指將若干個已排好序的部分合併成乙個有序的部分。而基數排序又稱為桶排序,是唯一一種不需要元素之間相互比較就可以排好序的排序演算法。

一、歸併排序

1.基本思想

這裡介紹的歸併排序是非遞迴版本的歸併排序。基本思想如下:首先我們知道單個元素都是有序,然後我們逐漸增加元素之間的距離,最開始的時候為1,即a[0]和a[1]比較,使兩者有序;然後a[2]和a[3]比較,使兩者有序,以此類推。然後進行第二趟排序時,距離以指數式增長為2^1=2,即將a[0]、a[1]看成乙個整體(因為這兩者已經有序),將a[2]、a[3]看成乙個整體,將這兩部分進行歸併合成乙個有序的部分。下一次距離增長為2^2=4,重複上述過程。
2.排序過程

3.**實現

#include

#include

void mergesort(int *parray, int ilen);

void printarray(int *parray, int ilen);

void merge(int *parray, int ilen, int igap);

int main(void)

; int ilen = sizeof(iarray_a) / sizeof(*iarray_a);

mergesort(iarray_a, ilen);

printarray(iarray_a, ilen);

return0;}

void merge(int *parray, int ilen, int igap)

else

if(parray[ilow2] <= parray[ilow2])

}while (ilow1 <= ihigh1)

while (ilow2 <= ihigh2)

ilow1 = ihigh2 + 1;

ihigh1 = ilow1 + igap - 1;

ilow2 = ihigh1 + 1; //第二個歸併段的起始下標,下標可取

ihigh2 = (ilow2 + igap < ilen ? (ilow2 + igap - 1) : (ilen - 1));

} //處理只有乙個歸併段的資料

while (ilow1 <= ilen - 1)

for (i = 0; i < ilen; ++i)

free(ptemp_a);

}void mergesort(int *parray, int ilen)

}void printarray(int *parray, int ilen)

printf("\n");

}

4.演算法分析

(1)時間複雜度

從上面**可知,對於n個元素組成的序列,共需要logn趟歸併過程,每次歸併的距離2^n(n=0,1,2,......),而每次歸併的過程中是把序列中所有元素都遍歷了一遍,所以一次遍歷過程的時間複雜度為o(logn)。所以整個排序過程時間複雜度為o(nlogn).
(2)空間複雜度
歸併排序的時間複雜度比較大,需要和原陣列一樣的大小,所以空間複雜度為o(n)。
(3)穩定性
穩定。
二、基數排序

1.基本思想

基數排序的過程很好理解,但是其**實現比較複雜,主要是因為需要做很多輔助性工作。基本思想是在排序過程中,對於乙個數而言,先排權值比較小的位數,如三位數字序列,先按個位排序,則為;再按十位排序,則為;最後按百位進行排序,則為。具體過程見排序過程。
2.排序過程
**實現過程中需要明確幾個地方,一是入桶和出桶本質上就是入隊和出隊的過程,所以需要我們在**實現時構建乙個佇列;二是入桶和出桶的次數由序列中值最大的元素的位數決定;三是桶的個數由單個數字的取值範圍決定,比如這裡是每個數字由0~9組成,所以需要十個桶。

3.**實現

#include 

#include

typedef

struct node

node, *list;

void initlist(list plist)

bool isempty(list plist)

static node* buynode(int ival)

//獲取序列中值最大的元素

int getmaxfigure(int *parray, int ilen)

}return imax;

}//獲取數字的位數

int getwidth(int inum) //獲取最大位數

return iwidth; //返回數字的位數

}//在尾部插入乙個節點

void inserttail(list plist, int ival)

p->pnext = buynode(ival);

}//刪除首節點

bool deletefirstnode(list plist, int *rtval)

node *p = plist->pnext;

*rtval = p->idata;

plist->pnext = p->pnext;

free(p);

p = null;

return

true;

}void radixsort(int *parray, int ilen)

int iremind;

int icount = getwidth(getmaxfigure(parray, ilen)); //獲取值最大元素的位數,決定了我們進行基數排序的次數

for (int i = 0; i < icount; ++i)

//將每個元素按其指定位置的數來入隊

inserttail(plist_a[iremind], parray[j]); //入隊

}//全部入隊後依次出隊

int iindex = 0;

for (int j = 0; j < 10; ++j)}}

}void printarray(int *parray, int ilen)

printf("\n");

}int main(void)

; int ilen = sizeof(iarray_a) / sizeof(*iarray_a);

radixsort(iarray_a, ilen);

printarray(iarray_a, ilen);

return

0;}

4.演算法分析
假設入桶的次數為r,且有d個桶,n個元素。
(1)時間複雜度
時間複雜度為o(r*d)。
(2)空間複雜度
空間複雜度為o(n)。
(3)穩定性
穩定。

八大排序演算法 之 歸併排序

排序思想 如圖所示 排序趟數 如果2 n 如此例,length 9 8,趟數是4.排序原理 1,第一趟將相鄰兩個數歸併成乙個有序的小組合 2,第二趟將相鄰兩個有序小組合歸併成乙個更大的的有序組合 3,依次類推,直到將所有數歸併成乙個最大的組合 具體 實現如下 歸併排序主方法 public stati...

八大排序演算法之歸併排序

歸併排序的核心是,每次將兩個有序陣列組合成為乙個新的有序陣列。對於倆個有序陣列 def merge a list,b list list l a,l b len a len b res 0 for i in range l a l b index 0 i,j 0,0 while i歸併排序中,兩個有...

八大排序演算法之歸併排序

說明 歸併排序是建立在歸併操作上的一種有效的排序演算法。該演算法是採用分治法 divide and conquer 的乙個非常典型的應用。將已有序的子串行合併,得到完全有序的序列 即先使每個子串行有序,再使子串行段間有序。若將兩個有序表合併成乙個有序表,稱為2 路歸併。思路 1.將序列中待排序數字分...