1. 程式人生 > >資料結構與演算法之三 深入學習排序

資料結構與演算法之三 深入學習排序

視訊課堂https://edu.csdn.net/course/play/7621
在本章中,你將學習: 通過使用快速排序來排序資料 通過使用歸併排序來排序資料 快速排序演算法 快速排序是最有效率的排序演算法之一,此演算法基於 分治法 連續 將問題 細分為更小的問題 直到 問題 成為可以直接解決的小問題 在快速排序演算法中,你: 從名為
樞軸 的列表處選擇元素 將列表劃分為兩部分 列表左端的所有元素 小於等於 樞軸 列表右端的所有元素 大於 樞軸 在此列表兩部分的 正確位置 儲存 樞軸 劃分之後為建立的 兩個子列表重複 此過程 ( 找樞軸的過程 ) 直到 每個子列表中只剩一個元素 思想:就是不斷找出符合條件的樞軸位置

編寫一個演算法以實現快速排序: QuickSort(low,high) 1. 如果 (low > high):   a.  返回 2. 設定 pivot = arr[low] 3. 設定 i = low + 1 4. 設定 j = high 5. 重複第
6 步直到 i > high arr[i] > pivot // 搜尋大於樞軸的元素 6. 1 遞增 i 7. 重複第 8 步直到 j < low arr[j] < pivot // 搜尋小於樞軸的元素       8. 1 遞減 j 9. 如果 i < j: // 如果較大的元素位於較小元素的左側   a.  交換 arr[i] arr[j]
10. 如果 i <= j:   a.  轉到第 5 // 繼續搜尋 11. 如果 low < j:   a.  交換 arr[low] arr[j] // 交換樞軸與列表第一部分的最後一個元素 12. QuickSort(low,J 1) // 對樞軸左側的列表應用快速排序 13. QuickSort(J + 1, high) // 對樞軸右側的列表應用快速排序

此排序演算法的總時間取決於樞軸值的位置。 最糟的情形出現在列表已經排序時。 通常,選擇第一個元素作為樞軸,但是其會導致 O(n2) 的最糟用例效率。 如果您選擇所有值的中間值作為樞軸 ,則效率將是 O(n log n)

什麼是快速排序演算法的平均用例的比較總次數。

答案: O(n log n)

歸併排序演算法: 其使用分治法來排序列表 要排序的列表將分為兩個幾乎相等的兩個子列表 這兩個子列表將通過使用歸併排序單獨排序 這兩個排序的子列表歸併為單個排序的列表

編寫一個演算法以實現歸併排序: MergeSort(low,high) 1. 如果 (low >= high):   a.  返回 呼叫本函式的地方 . 2. 設定 mid = (low + high)/2 3. 將列表劃分為幾乎完全相等的兩個子列表,並通過使用歸併排序來排序每個子列表。 執行的步驟如下: :     a. MergeSort low, mid   b. MergeSort mid + 1, high 4. 歸併兩個排序的子列表:通過一 merge() 方法實現 .   a. 設定 i = low      b. 設定 j = mid + 1   c. 設定 k = low   d. 重複直到 i > mid j > high: //  此迴圈將終止,前提是達到兩個子列表的其中一個結束處。  

    i. 如果 (arr[I] <= arr[J])      arr[I] 儲存到陣列 B 中的索引 k         1 遞增 i    Else arr[j] 儲存到陣列 B 中的索引 k 1 遞增 j      ii. 1 遞增 k   e. 重複直到 j > high: // 如果第二個中仍然有某些元素                                                                       // 追加到新列表的子列表   i. arr[j] 儲存到陣列 B 中的索引 k   ii. 1 遞增 j   iii. 1 遞增 k   f. 重複直到 i > mid:  // 如果在第一個子列表中仍然有一些元素                                             // 將它們追加到新類別中   i. arr[i] 儲存到陣列 B 中的索引 k   ii. 1 遞增 i   iii. 1 遞增 k 5. 將排序的陣列 B 中的所有元素複製到原始陣列 arr

若要排序此列表,您需要按遞迴方式將列表劃分為兩個幾乎完全相等的子列表,直 到每個子列表僅包含一個元素。   將列表劃分為大小為 1 的子列表需要 log n 次通行。 在每個通行中 ,最多執行 n 次比較。   因此,比較總數將是最多 n × log n 次。 歸併排序的效率等於 O(n log n) 歸併列表的最佳、平均和最糟用例效率之間沒有差異 ,因為所有這些效率均需要相 同的時間量。

哪個演算法使用以下步驟來排序給出的元素列表?        1.      選擇名為樞軸的列表中的元素。       2. 將列表分為兩個部分,以便一部分包含小於樞軸的元素,另一部分包含大於樞 軸的元素。       3. 然後將樞軸放到兩個列表之間的正確位置。       4. 使用相同的演算法排序列表的兩個部分。

答案: 快速排序
小結
在本章中,你已經學到: 快速排序和歸併排序演算法基於分治技巧。 若要通過使用快速排序演算法來排序專案列表,您需要: 選擇樞軸值。 將列表分為兩個子列表,以便一個子列表包含了所有小於樞軸的項,另一個子列表 包含了大於樞軸的所有項。 然後將樞軸放到兩個子列表之間的正確位置。 通過使用快速排序來排序兩個子列表。 快速排序演算法採用的總時間取決於樞軸值的位置和最初的元素分階。 快速排序演算法的最差效率是 O(n2) 階的。 快速排序演算法的最佳效率是 O(n log n) 階的。 若要通過使用歸併排序來排序專案列表,您需要: 將列表分為兩個子列表。 通過使用歸併排序來排序每個子列表。 歸併兩個排序的子列表。 歸併排序演算法具有 O(n log n) 的效率。
/*
問題描述:編寫在陣列中儲存10個數字的程式,並通過使用快速排序演算法來排序。
*/
using System;
using System.Text;

class Merge_Sort
{
	private int[]arr=new int[20];	//定義陣列,你輸入數字,接受儲存的陣列
	private int[]dest=new int[20];	//在歸併排序中用來儲存已經排序的陣列,就是咱說的新陣列.
	private int cmp_count;	//比較總次數
	private int mov_count;	//移動總次數
	//陣列元素個數
	public int n;
	//****************構造方法
	public Merge_Sort()
	{
		cmp_count=0;
		mov_count=0;	
	}	
	//使用者輸入資料方法
	void read()
	{
		while(true)
		{
			Console.WriteLine("請輸入陣列的元素個數:");
			string s=Console.ReadLine();
			n=Int32.Parse(s);
			if(n<=20)
				break;
			else
				Console.WriteLine("\n陣列的最大元素個數為20.\n");	
		}
		Console.WriteLine("\n---------------------------------");
		Console.WriteLine("-----------請輸入陣列元素---------");
		Console.WriteLine("---------------------------------");
		//獲得陣列元素
		for(int i=0;i<n;i++)
		{
			Console.Write("<"+(i+1)+">");
			string s=Console.ReadLine();
			arr[i]=Int32.Parse(s);	
		}
	}
	//交換兩個陣列索引的方法
	void swap(int x,int y)
	{
		int temp;
		
		temp=arr[x];
		arr[x]=arr[y];
		arr[y]=temp;	
	}
	/**************歸併排序演算法****************/
	public void m_sort(int low,int high)
	{
		if(low>=high)
			return;
		else
		{
			int mid=(low+high)/2;
			m_sort(low,mid);
			m_sort(mid+1,high);
			merge(low,mid,high);
		}
	}
	public void merge(int low,int mid,int high)
	{
			int i=low;
			int j=mid+1;
			int k=low;
			while((i<=mid)&&(j<=high))
			{
				if(arr[i]<=arr[j])
					{
						dest[k]=arr[i];
						k++;
						i++;
					}	
				else
				{
					dest[k]=arr[j];
					k++;
					j++;	
				}
			}
			while(j<=high)
			{
					dest[k]=arr[j];
					k++;
					j++;		
			}
			while(i<=mid)
			{
				dest[k]=arr[i];
				k++;
				i++;
					
			}
			//Array.Copy(dest,arr,arr.Length);
			for(i=low;i<=high;i++)
			{
				arr[i]=dest[i];	
			}
	}
	//顯示方法
	void display()
	{
		Console.WriteLine("\n------------------------------------");	
		Console.WriteLine("---------已經排序後的陣列元素為------");	
		Console.WriteLine("------------------------------------");	
		
		for(int j=0;j<=n;j++)
		{
			Console.Write(arr[j]+" ");	
			//Console.Write(dest[j]+" ");
		}
		//Console.WriteLine("\n比較的總次數為:"+cmp_count);
		//Console.WriteLine("\n移動的總次數為:"+mov_count);
	}
	int getSize()
	{
		return (n);	
	}
	public static void Main(string[]args)
	{
		Merge_Sort mySort=new Merge_Sort();
		mySort.read();
		mySort.m_sort(0,mySort.n-1);
		mySort.display();
		
		Console.WriteLine("\n\n按任意鍵退出.");
		Console.Read();
	}
}