排序(Sort)

排序(Sort)

一、概述

排序是計算機程序設計中的一種重要操做。若是數據可以根據某種規則排序,就能大大挺高數據處理的算法效率。html

1.基本概念

排序就是整理文件中的記錄,使之按關鍵字遞增(或遞減)的次序排列起來。前端

排序的對象是文件,它由一組記錄組成。每條記錄則由一個或若干個數據項(或域)組成。java

關鍵字項就是可用來標識一個記錄的一個或多個組合的數據項。該數據項的值稱爲關鍵字(key)。須要注意的是,在不易產生混淆時,可將關鍵字項簡稱爲關鍵字。算法

用來做爲排序運算的關鍵字,能夠是數字類型,也能夠是字符類型。關鍵字的選取應根據問題的要求而定。shell

2.穩定性

當待排序記錄的關鍵字均不相同時,排序結果是唯一的,不然排序結果不唯一。後端

在待排序的文件中,若存在多個關鍵字相同的記錄,通過排序後這些具備相同關鍵字的記錄之間的相對次序保持不變,該排序方法是穩定的;若具備相同關鍵字的記錄之間的相對次序發生變化,則稱這種排序方法是不穩定的。數組

3.分類

根據排序時待排序的數據元素數量的不一樣,使得排序過程當中涉及的存儲器不一樣,能夠將排序方法分爲兩類。 一類是整個排序過程在內存儲器中進行,稱爲內部排序,簡稱內排序。數據結構

另外一類是因爲待排序元素數量太大,以致於內存儲器沒法容納所有數據,排序須要藉助外部存儲設備才能完成,這類排序稱爲外部排序。app

通常狀況下,內排序適宜在記錄個數很少的小文件中使用,外排序則適用於記錄個數太多,不能一次將其所有記錄放入內存的大文件。ide

對於外排序,可進一步分爲兩種方法:

  • 合併排序法
  • 直接合並排序法。

對於內排序,按策略進行劃分,能夠分爲:

  • 插入排序
  • 交換排序
  • 選擇排序
  • 歸併排序
  • 分配排序

4.排序算法分析

分析排序算法時,應該考慮比較的次數和數據移動的次數。

具體須要考慮如下3中狀況的比較和移動次數:

  • 最好狀況(一般是數據已經排序)
  • 最壞狀況(一般是數據按反序存放)
  • 平均狀況(數據是隨機順序的)

不少排序方法在這3種狀況下的性能是迥然不一樣的,因此能夠根據實際條件選擇使用哪種算法。

二、插入排序

插入排序的思想:

每次將一個待排序的記錄按其關鍵字大小插入到前面已經排好序的子文件的適當位置,直到所有記錄插入完成爲止。

1.直接插入排序(Insertion Sort)

直接插入排序是一種最簡單的排序方法,它的基本操做是將一個記錄插入到已經排好序的有序表中,從而獲得一個新的有序表。

1>基本思想

假設待排序的記錄存放在數組R[1……n]中,排序過程當中,R被分爲兩個子區間R[1……i]和R[i+1……n],其中R[1……i]是已經排好序的有序區;R[i+1……n]是當前未排序的部分。將當前無序區的第一個記錄R[i+1]插入到有序區R[1……i]的適當位置,使R[1……i+1]變爲新的有序區,每次插入一個數據,知道全部的數據有序爲止。

2>算法步驟

通常來講,插入排序都採用in-place在數組上實現。具體算法描述以下:

  • 1.從第一個元素開始,該元素能夠認爲已經被排序;
  • 2.取出下一個元素,在已經排序的元素序列中從後向前掃描;
  • 3.若是該元素(已排序)大於新元素,將該元素移到下一位置;
  • 4.重複步驟3,直到找到已排序的元素小於或者等於新元素的位置;
  • 5.將新元素插入到該位置後;
  • 6.重複步驟2~5。

3>java代碼

// 插入排序
	public static int[] insertionSort(int[] arr) {
		int preIndex, temp;
		//比較的論數
		for (int i = 1; i < arr.length; i++) {
			//當前下標的前一位下標
			preIndex = i - 1;
			//當前位置的元素
			temp = arr[i];
			//前一位下標不越界而且前一位的元素值大於當前位置的元素值
			while (preIndex >= 0 && arr[preIndex] > temp) {
				//移動元素位置
				arr[preIndex + 1] = arr[preIndex];
				//下標前移繼續比較
				preIndex--;
			}
			//插入相應位置
			arr[preIndex + 1] = temp;
		}
		return arr;
}

4>算法分析

①時間複雜度

對於具備n個記錄的文件,要進行n-1趟排序。 各類狀態下的時間複雜度以下表:

②空間複雜度

算法所需的輔助空間是一個監視哨,輔助空間負責度S(n)=O(1),是一個就地排序。

③穩定性

直接插入排序是穩定的排序方法。

2.希爾排序(Shell Sort)

希爾排序是插入排序的一種,因D.L.Shell於1959年提出而得名。希爾排序也稱做縮減增量排序(diminishing increment sort)

1>基本思想

先取定一個小於n的整數d1做爲第一個增量,把文件的所有記錄分紅d1個組,全部距離爲d1的倍數的記錄放在同一個組中,在各組內進行插入排序;而後,取第二個增量d2<d1,重複上述的分組和排序,直至所取的增量dt=1(dt<……<d2<d1),即全部記錄放在同一組中進行直接插入排序爲止。

2>算法步驟

先將整個待排序的記錄序列分割成爲若干子序列分別進行直接插入排序,具體算法描述:

  • 1.選擇一個增量序列t1,t2,…,tk,其中ti>tj,tk=1;
  • 2.按增量序列個數k,對序列進行k 趟排序;
  • 3.每趟排序,根據對應的增量ti,將待排序列分割成若干長度爲m 的子序列,分別對各子表進行直接插入排序。僅增量因子爲1 時,整個序列做爲一個表來處理,表長度即爲整個序列的長度。

3>java代碼

// 希爾排序
	public static void shellSort2(int[] arr) {
		int j;
		// 初始值爲數組長度的一半,而後按照一半的一半遞減至1
		for (int gap = arr.length / 2; gap > 0; gap /= 2) {
			// 初始取值爲數組長度的一半,而後加一遞增,不能超過數組長度
			for (int i = gap; i < arr.length; i++) {
				int tmp = arr[i];// 取出數組的一半位置的元素。
				// 比較步長兩端的元素,若是後端小於前端
				for (j = i; j >= gap && tmp - arr[j - gap] < 0; j -= gap) {
					arr[j] = arr[j - gap];// 將前端的值賦予後端
				}
				// 此時j減去了gap則爲前端的位置,將後端的值賦予前端。完成不一樣位置的元素交換。
				arr[j] = tmp;
			}
		}
	}

4>算法分析

①增量序列的選擇則

Shell排序的執行時間依賴於增量序列。

好的在增量序列的共同特徵爲:

  • 最後一個增量必須爲1;應儘可能避免序列中的值(尤爲是相鄰的值)互爲倍數的狀況。
  • 當n較大時,比較和移動的次數約在n^1.25 到1.6n^1.25 之間。
②時間複雜度

希爾排序的時間性能優於直接插入排序,緣由以下:

  • 當文件初態基本有序時,直接插入排序所需的比較和移動次數均較少。
  • 當n值較小時,n和n^2的差異也較小,即插入排序的最好時間複雜度是O(n)和最歡的時間複雜度O(n^2)差異不大。
  • 在希爾排序開始時增量較大,分組較多,每組的記錄數目少,故各組內直接插入較快,後來增量di組件縮小,分組數組件減小,而各組的記錄數目逐漸增多,但因爲已經按di-1做爲距離排過序,使文件較接近於有序狀態,因此新的一趟排序過程也較快。所以,希爾排序在效率上較直接插入排序有較大的改進。
③穩定性

希爾排序是一種不穩定的排序方法。

三、交換排序

交換排序的基本思想:

兩兩比較待排序記錄的關鍵字,發現兩個記錄的次序相反時,即進行交換,直到沒有反序的記錄爲止。 應用交換排序基本思想的主要排序方法有冒泡和快速排序。

1.冒泡排序(Bubble Sort)

1>基本思想

設想被排序的記錄關鍵字保存在數組R[1……n]中,將每一個記錄R[i]看作是重量爲R[i].key的氣泡。根據輕氣泡不能在重氣泡之下的原則,從下往上掃描數組R;凡掃描到違反本原則的輕氣泡,就使其向上「漂浮」。如此反覆進行,直到最後任何兩個氣泡都輕者在上,重者在下爲止。

2>算法步驟

  • 1.比較相鄰的元素。若是第一個比第二個大,就交換它們兩個;
  • 2.對每一對相鄰元素做一樣的工做,從開始第一對到結尾的最後一對,這樣在最後的元素應該會是最大的數;
  • 3.針對全部的元素重複以上的步驟,除了最後一個;
  • 4.重複步驟1~3,直到排序完成。

3>java代碼

// 冒泡排序
	public static void bubbleSort(int[] arr) {
		// 比較的輪數
		for (int i = 0; i < arr.length - 1; i++) {
			// 每輪比較的次數
			for (int j = 0; j < arr.length - 1 - i; j++) {
				// 從小到大排序
				if (arr[j] > arr[j + 1]) {
					int tmp = arr[j];
					arr[j] = arr[j + 1];
					arr[j + 1] = tmp;
				}
			}
		}
	}

4>算法分析

①時間複雜度

若文件的初始狀態是正序的,一趟掃描便可完成排序。所需的關鍵字比較次數C和記錄移動次數M均達到最小值:

Cmin=n-1;Mmin=0

冒泡最好的時間複雜度爲O(n)。

若成績是文件是反序的,須要進行n-1趟排序。每趟排序要進行n-i此關鍵字的比較(1≤i≤n-1),且每次比較都必須移動記錄三次來達到交換記錄位置。在這種狀況下,比較和移動次數均達到最大值:

Cmax=n(n-1)/2=O(n^2);Mmax=3n(n-1)/2=O(n^2)

冒泡的最壞時間複雜度爲O(n^2)。

冒泡算法的平均時間複雜度爲O(n^2)。

②穩定性

冒泡排序是就地排序,且它是穩定的。

2.快速排序(Quick Sort)

快速排序是C.R.A.Hoare於1962年提出的一種劃分交換排序。它採用了一種分治的策略,一般稱其爲分治法(Divide-and-ConquerMethod)。

1>基本思想

將原有問題分解爲若干個規模更小但結構與原問題類似的子問題,遞歸地解這些子問題。而後將這些子問題的解組合爲原問題的解。而後將這些子問題的解組合爲原問題的解。

2>算法步驟

快速排序使用分治法來把一個串(list)分爲兩個子串(sub-lists)。具體算法描述以下:

  • 1.從數列中挑出一個元素,稱爲 「基準」(pivot);
  • 2.從新排序數列,全部元素比基準值小的擺放在基準前面,全部元素比基準值大的擺在基準的後面(相同的數能夠到任一邊)。在這個分區退出以後,該基準就處於數列的中間位置。這個稱爲分區(partition)操做;
  • 3.遞歸地(recursive)把小於基準值元素的子數列和大於基準值元素的子數列排序。

3>java代碼

// 快速排序
	public static void fastSort(int[] arr, int left, int right) {
		// 最小位置
		int minIndex = left;
		// 最大位置
		int maxIndex = right;
		// 三方變量
		int temp = 0;
		// 最大和最小位置不相等時
		if (minIndex < maxIndex) {
			// 三方變量從最小位置開始取值比較
			temp = arr[minIndex];
			// 當最大和最小位置不重疊時
			while (minIndex != maxIndex) {
				// 小位置沒有越過大位置,而且大位置的值大於等於temp的取值
				while (maxIndex > minIndex && arr[maxIndex] >= temp) {
					// 大位置向左移
					maxIndex--;
				}
				// 不然,小位置的元素取大位置的元素
				arr[minIndex] = arr[maxIndex];
				// 小位置沒有越過大位置,而且小位置的元素值小於等於三方變量
				while (minIndex < maxIndex && arr[minIndex] <= temp) {
					// 小位置右移
					minIndex++;
				}
				// 不然,大位置的元素取小位置的元素
				arr[maxIndex] = arr[minIndex];
			}
			// 中止處的小位置去三方變量的值。
			arr[maxIndex] = temp;
			// 左半數組重複上面的操做
			fastSort(arr, left, minIndex - 1);
			// 右半數組重複上面的操做
			fastSort(arr, maxIndex + 1, right);
		}
	}

4>算法分析

快速排序的時間主要耗費在劃分操做上,對長度爲k的區間進行劃分,共需k-1次關鍵字的比較。

①時間複雜度

最壞狀況是每次劃分宣州區的基準都是當前無序區中關鍵字最小(或最大)的記錄,劃分的結果是基準左邊的子區間爲空(或右邊的子區間爲空),而劃分所得的另外一個非空的子區間中記錄數目僅僅比劃分前的無序區中記錄個數減小一個。

所以,快速排序必須作n-1此劃分,第i此劃分開始區間長度爲n-i+1,所需的比較次數爲n-i(1≤i≤n-1),故總的比較次數達到最大值:

Cmax=n(n-1)/2=O(n^2)

最好狀況下,每次劃分所取的基準都是當前無序區的「中值」記錄,劃分的結果是基準的左、右兩個無序子區間的長度大體相等。總的關鍵字比較次數爲:O(nlgn)。 平均時間複雜度爲:O(nlgn)。

②空間複雜度

快速排序在系統內部須要一個棧來實現遞歸。若每次劃分較爲均勻,則其遞歸樹的高度爲O(lgn),故遞歸後須要棧空間爲O(lgn)。最壞狀況下,遞歸樹的高度爲O(n),所需的棧空間爲O(n)。

③穩定性

快速排序是非穩定的。

四、選擇排序

選擇排序的基本思想:

每一趟從待排序的記錄中選出關鍵字最小的記錄,順序放在已排好序的子文件的最後,直到所有記錄排序完畢。

選擇排序方法主要有一下兩種:直接選擇排序(或稱簡單選擇排序)和堆排序。

1.直接選擇排序(Selection Sort)

1>基本思想

第i趟排序開始時,當前有序區和無序區分別爲R[1……i-1]和R[i……n](1≤i≤n-1),該趟排序則是從當前無序區中選出關鍵字最小的記錄R[k],將它與無序區的第一個記錄R[i]交換,是R[1……i]和R[i+1……n]分別變爲新的有序區和新的無序區。由於每趟排序均使有序區中增長了一個記錄,且有序區中的記錄關鍵字均不大於無序區無序區轟炸過記錄的關鍵字,即第i趟排序以後R[1……i].keys≤R[i+1……n].keys,因此進行n-1趟排序以後有R[1……n-1].keys≤R[n].key,即通過n-1趟排序以後,整個文件R[1……n]遞增有序。

2>算法步驟

n個記錄的直接選擇排序可通過n-1趟直接選擇排序獲得有序結果。具體算法描述以下:

  • 1.初始狀態:無序區爲R[1..n],有序區爲空;
  • 2.第i趟排序(i=1,2,3…n-1)開始時,當前有序區和無序區分別爲R[1..i-1]和R(i..n)。該趟排序從當前無序區中-選出關鍵字最小的記錄 R[k],將它與無序區的第1個記錄R交換,使R[1..i]和R[i+1..n)分別變爲記錄個數增長1個的新有序區和記錄個數減小1個的新無序區;
  • 3.n-1趟結束,數組有序化了。

3>java代碼

//直接選擇排序
	public static void SelectionSort(int[] arr) {
		int minIndex,temp;
		for(int i = 0;i<arr.length;i++) {
			minIndex=i;
			for(int j=i+1;j<arr.length;j++) {
				if(arr[j]<arr[minIndex]) {
					minIndex = j;
				}
			}
			temp = arr[i];
			arr[i] =arr[minIndex];
			arr[minIndex]=temp;
		}
	}

4>算法分析

①時間複雜度

直接選擇排序的平均時間複雜度爲O(n^2)。

②穩定性

直接選擇排序是一個就地排序,而且是不穩定的。

2.堆排序(Heap Sort)

堆排序是利用徹底二叉樹進行排序的方法。

堆有大根堆(根結點的關鍵字值最大的堆)和小根堆(根結點關鍵字值最小)之分。

堆排序利用了大根堆(或小根堆)堆頂記錄的關鍵字最大(或最小)這一特徵,使得在當前無序區中選取最大(或最小)關鍵字的記錄變得簡單。

1>基本思想

大根堆排序思想:

首先將初始文件R[1……n]建成一個大根堆,此堆的初始的無序區;將關鍵字最大的記錄R[1](即堆頂)堆頂和無序區的最後一個記錄R[n]交換,由此獲得新的無序區R[1……n-1]和有序區R[n],且知足R[1……n-1].keys≤R[n].keys,因爲交換後新的根R[1]可能違反堆性質,故應將當前無序區R[1……n-1]調整爲堆;而後再次將R[1……n-1]中關鍵字最大的記錄R[1]和該區間的最後一個記錄R[n-1]交換,由此獲得新的無序區R[1……n-2]和有序區R[n-1……n],且仍知足關係R[1……n-2].keys≤R[n-1……n].keys。一樣要將R[1……n-2]調整爲堆。重複以上步驟,直至按關鍵字有序。

2>算法步驟

  • 1.將初始待排序關鍵字序列(R1,R2….Rn)構建成大頂堆,此堆爲初始的無序區;
  • 2.將堆頂元素R[1]與最後一個元素R[n]交換,此時獲得新的無序區(R1,R2,……Rn-1)和新的有序區(Rn),且知足R[1,2…n-1]<=R[n];
  • 3.因爲交換後新的堆頂R[1]可能違反堆的性質,所以須要對當前無序區(R1,R2,……Rn-1)調整爲新堆,而後再次將R[1]與無序區最後一個元素交換,獲得新的無序區(R1,R2….Rn-2)和新的有序區(Rn-1,Rn)。不斷重複此過程直到有序區的元素個數爲n-1,則整個排序過程完成。

3>java代碼

//交換值
	private static void swap(int[] arr,int biggerIndex,int rootIndex) {
		int temp=arr[rootIndex];
		arr[rootIndex]=arr[biggerIndex];
		arr[biggerIndex]=temp;
	}
	//調整大根堆
	private static void adjustHeap(int[] arr,int rootIndex,int lastIndex) {
		//從根結點開始往下調整
		int biggerIndex = rootIndex;
		int leftChildIndex=rootIndex * 2+1;
		int rightChildIndex=rootIndex*2+2;
		if(rightChildIndex<=lastIndex) {//若是右結點存在,則左結點必定存在
			if(arr[rightChildIndex]> arr[rootIndex]||arr[leftChildIndex]>arr[rootIndex]) {
				//將子節點更大的元素下標賦值給biggerIndex
				biggerIndex = arr[rightChildIndex]>arr[leftChildIndex]?rightChildIndex:leftChildIndex;
			}
		}else if(leftChildIndex<=lastIndex) {//保證左結點存在,且不越界
			if(arr[leftChildIndex]>arr[rootIndex]) {
				biggerIndex = leftChildIndex;
			}
		}
		if(biggerIndex!=rootIndex) {
			swap(arr, biggerIndex, rootIndex);
			adjustHeap(arr, biggerIndex, lastIndex);
		}

	}
	//構建大根堆
	private static void buildMaxHeap(int[] arr,int lastIndex) {
		//從最後一個元素的父結點開始進行調整,一直調整到根結點結束
		int j=(lastIndex-1)/2;
		while(j>=0) {
			int rootIndex = j;
			adjustHeap(arr, rootIndex, lastIndex);
			j--;
		}
	}

	//堆排序
	public static void heapSort(int[] arr,int len) {
		int lastIndex = len -1;
		//構建最大堆
		buildMaxHeap(arr, lastIndex);
		while(lastIndex>0) {
			swap(arr, 0, lastIndex);
			if(--lastIndex==0) {//剩餘元素個數爲1,排序結束,跳出循環
				break;
			}
			adjustHeap(arr, 0, lastIndex);
		}
	}

4>算法分析

堆排序的時間主要由創建初始堆和反覆重建堆這兩部分的時間開銷構成,他們均是經過調用heapSort實現的,

①時間複雜度

堆排序的最壞時間複雜度爲O(nlgn)。堆排序的平均性能較接近於最壞性能。

因爲建初始堆歲序的比較次數較多,所欲堆排序不適宜與記錄數較少的文件。

②空間複雜度

堆排序是就地排序,輔助空間爲O(1)

③穩定性

堆排序是一種不穩定的排序方法。

五、歸併排序(Merge Sort)

歸併排序是將兩個或兩個以上的有序表組合成一個新的有序表。

1>基本思想

先將N個數據當作N個長度爲1的表,將相鄰的表成對合並,獲得長度爲2的N/2個有序表,進一步將相鄰的合併,獲得長度爲4的N/4個有序表,一次類推,知道全部數據均合併成一個長度爲N的有序表爲止。

2>算法步驟

  • 1.把長度爲n的輸入序列分紅兩個長度爲n/2的子序列;
  • 2.對這兩個子序列分別採用歸併排序;
  • 3.將兩個排序好的子序列合併成一個最終的排序序列。

3>java代碼

// 合併數據
	private static void merge(int[] arr,int left,int center,int right) {
		int[] newArr = new int[arr.length];
		int mid = center+1;
		int third = left;
		int tmp = left;
		while(left <=center&& mid<=right) {
			if(arr[left]<=arr[mid]) {
				newArr[third++]=arr[left++];
			}else {
				newArr[third++]=arr[mid++];
			}
		}
		while(mid<=right) {
			newArr[third++]=arr[mid++];
		}
		while(left<=center) {
			newArr[third++]=arr[left++];
		}
		while(tmp<=right) {
			arr[tmp]=newArr[tmp++];
		}
	}
	//排序
	private static void sort(int[] arr,int left,int right) {
		if(left>=right) {
			return;
		}
		int center = (left+right)/2;
		sort(arr, left, center);
		sort(arr, center+1, right);
		merge(arr, left, center, right);
	}
	//歸併排序
	public static void mergeSort(int[] arr) {
		sort(arr, 0, arr.length-1);
	}

4>算法分析

①時間複雜度

歸併排序的時間複雜度不管是在最好狀況下,仍是在最壞狀況下均是O(nlgn)。

②空間複雜度

須要一個輔助向量來暫存兩個有序子文件歸併的結果,故其輔助空間複雜度爲O(n)。

③穩定性

歸併排序是一種穩定的排序。

六、外部排序

算法和數據結構的實現能夠基於住存儲器,也能夠基於輔助存儲器,但這會影響算法和數據結構的設計。

主存儲器和輔助存儲器的差異主要與存儲介質中的訪問速度、數據的存儲量和數據的永久性有關。

訪問輔助存儲器比訪問主存儲器要慢不少,而外部排序的過程須要進行屢次的主存儲器和輔助存儲器之間的交換。

調整內部排序算法使之應用於外部排序,這種思路的更廣泛的問題是這樣作不可能比設計一個新的儘可能減小磁盤存取的算法更有效。

1.二路歸併排序

進行外部排序的一個更好的方法源於歸併排序。

1>基本思想

首先,按可用內存大小,將外存上喊n個記錄的文件分紅若干長度爲l的子文件或段(segment),依次讀入內存並利用有效的內部排序方法對它們進行排序,並將排序後獲得的有序子文件從新寫入外存。一般稱這些有序子文件爲歸併段或順串;而後對這些歸併段進行逐趟歸併,使歸併段組件由小到大,直至整個有序文件爲止。

2>算法步驟

  • 1.把原來的文件分紅兩個大小相等的順串文件。
  • 2.從每一個順串文件中取出一個塊,讀入輸入緩衝區中。
  • 3.從每一個輸入緩衝區中取出第一條記錄,把它們按照排好的順序寫入一個順串輸出緩衝區中。
  • 4.從每一個輸入緩衝區中取出第二條記錄,把它們按照排好的順序寫入另外一個順串輸出緩衝區中。
  • 5.在兩個順串輸出緩衝區之間交替輸出,重複這些步驟直到結束。當一個輸入塊用完時,從相應的輸入文件獨處第二個塊。當一個順串輸出緩衝區已滿時,把它寫回相應的輸出文件。
  • 6.使用原來的輸出文件做爲輸入文件,重複2至5步。在第二趟掃描中,每一個輸入順串文件的前兩條記錄已經排好了次序。這樣一來,就能夠把這兩個順串歸併成一個長度爲4個元素的順串輸出。
  • 7.對順串文件的每一堂掃描產生的順串愈來愈大,知道最後只剩下一個順串。

2.置換選擇排序

置換選擇其實是堆排序算法的一個微小變種。

1>算法步驟

  1. 從磁盤中獨處數據到數組中,設置LAST=M-1.
  2. 創建一個最小值堆。
  3. 重複如下步驟,直到數組爲空。 (1) 把具備最小關鍵碼值的記錄(根結點)送到輸出緩衝區。 (2) 設R是輸入緩衝區中的下一條記錄。若是R的關鍵碼值大於剛剛輸出的關鍵碼值,則把R放到根結點,不然使用數組中LAST位置的記錄代替根結點,而後把R放到LAST位置,並設置LAST=LAST-1。 (3) 篩出根結點,從新排列堆。

3.多路歸併排序

多路歸併與二路歸併相似。若是有B個順串須要歸併,從每一個順串中取出一個塊放在主存中使用,那麼B路歸併算法僅僅查看B個值,而且選擇最小的一個輸出。把這個值從它的順串中移出,而後重複這個過程。當任何順串的當前塊用完時,就從磁盤中獨處這個順串的下一個塊。

通常來講,簡歷大的初始順串能夠把運行時間減小到標準歸併排序的四分之一,使用多路歸併能夠進一步把時間減半。

七、排序算法性能表

本博文,部分參考十大經典排序算法(動圖演示),所涉及的動圖,均出自此博文!

上一篇:圖(graph)

下一篇:

相關文章
相關標籤/搜索