幾種常用的排序演算法

2021-09-02 06:12:49 字數 4318 閱讀 8875

[size=large]按照排序過程中所使用的內外存情況不同,可把排序分為內排序和外排序兩大類;若排序過程全部在記憶體資料表(如陣列)中進行,則成為內排序,若排序過程需要不斷地進行記憶體陣列和外村檔案之間的資料交換,則成為外排序。對於大的資料檔案,由於記憶體限制不能一次裝入記憶體進行排序,只能進行外排序來完成。

常用的排序有:插入排序,選擇排序,堆排序,快速排序,歸併排序,二路歸併的外排序等。

1、插入排序

將陣列a中待排序的n個元素看成乙個有序表和乙個無序表,開始的時候有序表總只含有乙個元素,無序表總含有n-1個元素,排序過程中每次從無序表中取出第乙個元素,把他插入到有序表中的適當位置,使之成為新的有序表,經過n-1次插入後,無序表就成為有序表了。

直接插入排序的平均時間複雜的為o(n^2),但當待排序記錄接近有序時,時間按複雜度接近o(n),所以直接插入法排序適合於袁術資料基本有序的情況。排序過程中只使用乙個臨時工作單元x,其空間複雜度為o(1)。[color=red]另外直接插入排序是穩定的,因為具有同一排序碼的後一元素必然插在具有同一排序碼的前一元素的後面,即相對次序保持不變。[/color][/size]

//直接插入排序

public static void insertsort(objecta,int n)

for(int i=0;i=0;j--)

else break;//查詢到插入的位置時離開內迴圈,前面的值肯定都比x小

}a[j+1]=x;//將原a[i]的值寫入到下標為j+1的位置

}}

[size=large]2、選擇排序(直接選擇排序和堆排序兩種)

(1)直接選擇排序:每次從當前待排序的區間中選出最小排序碼的元素,把該元素與該區間的第乙個元素交換位置。

直接選擇排序的時間複雜的為o(n^2)。[color=red]由於選擇排序存在著前後元素之間的互換,可能會改變相同排序碼元素的前後相對位置,所以此方法是不穩定的。[/color][/size]

//	直接選擇排序

public static void selectsort(objecta,int n)

for(int i=1;i<=n-1;i++)

}if(k!=i-1)

}}

[size=large](2)堆排序(heap sort)是利用堆的特性進行排序的過程。堆排序包括初始化堆和利用堆排序兩個階段。對堆中下標為i的元素進行篩選運算的過程是:首先把ri元素的排序碼si與兩個孩子中排序碼較大者sj(j=2i+1或j=2i+2)進行比較,若si>sj,則以si為根的子樹已經調整為堆,篩選運算完畢;否則ri與rj互換位置,互換後可能破壞以rj(此時的rj的值為原來的ri的值)為根的堆,接著再把rj與他的兩個孩子中排序碼較大者進行比較,以此類推,直到父節點的排序碼大於等於還子結點中較大的排序碼或者孩子結點為空時為止。這樣,以ri為根的子樹就被調整為乙個堆。在對ri進行篩選運算中,若他的排序碼較小則會被逐層下移,就像過篩子一項,小的漏下去,大的被選上來,所以把構成堆的過程形象地成為篩運算。

[/size]

篩選運算:**如下,結果是將當前區間最大的值放到最前

public static void sift(objecta,int n,int i)

for(int i=n/2-1;i>=0;i--)

for(int i=1;i<=n-1;i++)

}

object c=;

heapsort(c,c.length);

for(int i=0;ia.length)

for(int i=0;ii;j--)

}if(flag==false) return;

}}

[color=red]

[size=large]氣泡排序演算法的時間複雜的為o(n^2),由於氣泡排序通常比直接插入排序和直接選擇排序需要移動比較多的次數,所以他是3種簡單排序中速度最慢的乙個,另外氣泡排序樹穩定的。[/color][/size]

[size=large](2)快速排序(quick sort)又稱為劃分排序。是對氣泡排序的一種改進方法,在快速排序中,記錄的比較和交換是從兩端向中間進行的,排序碼較大的記錄一次就能夠交換到後面的單元,排序碼較小的記錄一次就能夠交換到前面的單元,記錄每次移動的距離較遠,因而總的比較和移動次數較少。

快排的過程:首先從待排序區間中選取第乙個元素作為比較的基準元素,通過從區間兩端向中間順序進行比較和交換,把在前面向後掃瞄到的大於基準元素排序碼同在後面向前掃瞄到的小於基準元素排序碼的元素交換位置,當所有元素都比較一遍後,把基準元素交換到前後兩部分單元的交界處。結果是前面單元的元素均小於基準元素,後面的元素均大於基準元素,而且基準元素的位置就是最終的排序位置,然後對劃分好的區間再次劃分排序,直到乙個區間為空或只含乙個元素時,即結束該區間上的快速排序過程。[/size]

劃分過程:

public static int partition(object a,int s,int t)

while(j>=i&&((comparable)x).compareto(a[j])<0)

if(ia.length)

quickrecursion(a, 0, n-1);//呼叫上面的方法,從第0個開始,最後乙個結束,遍歷排序

}

[color=red][size=large]快速排序是不穩定的,平均情況下快速排序演算法的時間複雜度是o(nlog2n)。實踐證明:當n較大時,快速排序是目前為止在平均情況下最快的一種排序方法。空間複雜的為o(log2n),比之前討論的方法多占用一些輔助儲存空間。

最好的情況:時間複雜的o(nlog2n)

最差的情況:時間複雜的o(n^2),空間複雜度o(n),此時快速排序就變成了「慢排序」[/size][/color]

[size=large]4、歸併排序

歸併( merge)就是將兩個或多個有序表合成乙個有序表的過程。

將兩個有序的表歸位乙個有序表叫二路歸併,思路:比較兩個表的第乙個元素的大小,將二者較小的值複製到排序表中,將序號後移,比較下一對待比較元素,直到其中乙個表元素複製完,將另乙個表中剩餘元素複製到排序表中[/size]

[size=large]歸併排序(merge sort)就是利用歸併操作把乙個無序表排列成乙個有序表的過程。利用二路歸併操作排序的過程:首先將待排序區間中的每乙個元素都看作乙個有序表,則n個元素構成n個有序表,接著兩兩歸併,即第乙個與第二個,第三個與第四個。。。若最後剩下乙個表則直接進入下一趟歸併;然後再兩兩歸併,如此下去直到歸併第log2n向上取整趟後得到乙個長度為n的有序表為止。[/size]

兩兩歸併過程:

public static void twomerge(objecta,objectr,int s,int m,int t)else

}while(i<=m)

while(j<=t)

}

每一趟歸併過程:

//進行一趟二路歸併過程演算法

public static void mergepass(object a,object r,int n,int len)

//歸併最後兩個長度不等的有序表

if(p+len-1<=n-1)else

}

歸併排序過程:

public static void mergesort(objecta,int n)

}

[color=red][size=large]二路歸併時間複雜度等於歸併趟數與每一趟時間複雜度的乘積,o(nlog2n),空間複雜度o(n),二路歸併排序是穩定的,因為在每兩個有序表歸併時,若分別在兩個有序表中有相同排序碼的元素,twomerge演算法可以使前乙個有序表中同一排序碼的元素先被複製

[/size][/color]

[size=large]5、外排序

外排序就是對外存檔案中的記錄進行排序的過程,排序結果任然被放到外存檔案中。

外存檔案的排序中最適合採用歸併排序的方法。

減少歸併趟數和訪問外存的次數,提高外村排序速度需要提高初始歸併段的長度,要求在對磁碟檔案歸併排序之前首先利用一種排序方法,按照初始歸併段確定的長度在原檔案上依次建立好每個有序表,然後再呼叫對檔案的歸併排序演算法完成排序。

進行外排序需要4個檔案,對原待排序檔案f1按照初始歸併段進行內排序,把內排序好的資料段交替寫入兩個資料檔案f2,f3中,進行歸併排序並把歸併好的檔案內容交替寫入f4,f5,同樣再對f4,f5檔案中的資料進行歸併排序並將資料交替寫入f2,f3,這樣每歸併一趟,其歸併長度就增加一倍,直到f2中含有乙個歸併段,且包含全部記錄,f3的內容為空為止,此時f2中就得到了對f1中的全部記錄的有序檔案。[/size]

幾種常用的排序演算法

介紹 快速排序是由東尼 霍爾所發展的一種排序演算法。在平均狀況下,排序 n 個專案要 n log n 次比較。在最壞狀況下則需要 n 2 次比較,但這種狀況並不常見。事實上,快速排序通常明顯比其他 n log n 演算法更快,因為它的內部迴圈 inner loop 可以在大部分的架構上很有效率地被實...

幾種常用的排序演算法

介紹 快速排序是由東尼 霍爾所發展的一種排序演算法。在平均狀況下,排序 n 個專案要 n log n 次比較。在最壞狀況下則需要 n 2 次比較,但這種狀況並不常見。事實上,快速排序通常明顯比其他 n log n 演算法更快,因為它的內部迴圈 inner loop 可以在大部分的架構上很有效率地被實...

幾種常用的排序演算法

氣泡排序 氣泡排序是一種穩定的排序演算法。演算法的穩定性是指兩個相同的資料在經歷過排序後資料的位置沒有發生變化。int n array.length 這裡設個標誌位,當沒有位置交換時,代表已經排好序,可以退出迴圈 boolean flag false for int i 0 i n i if fla...