介紹到這裡只剩下歸併排序和基數排序沒有介紹過了。這兩種演算法各有各的特點,歸併排序是分治法的一種有效應用,
所謂歸併是指將若干個已排好序的部分合併成乙個有序的部分。而基數排序又稱為桶排序,是唯一一種不需要元素之間相互比較就可以排好序的排序演算法。
一、歸併排序
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.將序列中待排序數字分...