Visual C# 常用排序算法

. 插入排序

  1.1. 基本思想:

  每次將一個待排序的數據元素,插入到前面已經排好序的數列中的適當位置,使數列依然有序;直到待排序數據元素全部插入完爲止。

  1.2. 排序過程: 

  【示例】:

[初始關鍵字] [49] 38 65 97 76 13 27 49

(38) [38 49] 65 97 76 13 27 49

(65) [38 49 65] 97 76 13 27 49

(97) [38 49 65 97] 76 13 27 49

(76) [38 49 65 76 97] 13 27 49

(13) [13 38 49 65 76 97] 27 49

(27) [13 27 38 49 65 76 97] 49

(49) [13 27 38 49 49 65 76 97]

  1.3. 程序實現

<summary>

/// 插入排序算法
/// </summary>
/// <param name="dblArray"></param>

static void InsertSort(ref double[] dblArray)
{
 for(int i = 1 ; i < dblArray.Length ; i++)
 {
  int frontArrayIndex = i-1 ;
  int CurrentChangeIndex = i ;
  while(frontArrayIndex>=0)
  {
   if(dblArray[CurrentChangeIndex] < dblArray[frontArrayIndex])
   {
    ChangeValue(ref dblArray[CurrentChangeIndex],ref dblArray[frontArrayIndex]);
    CurrentChangeIndex = frontArrayIndex ;
   }
   frontArrayIndex--;
  }
 }
}

/// <summary>
/// 在內存中交換兩個數字的值
/// </summary>
/// <param name="A"></param>
/// <param name="B"></param>

static void ChangeValue (ref double A ,ref double B)
{
 double Temp = A ;
 A = B ;
 B = Temp ;
}

 

2. 選擇排序

  2.1. 基本思想:

  每一趟從待排序的數據元素中選出最小(或最大)的一個元素,順序放在已排好序的數列的最後,直到全部待排序的數據元素排完。

  2.2. 排序過程:

  【示例】:

初始關鍵字 [49 38 65 97 76 13 27 49]

第一趟排序後 13 [38 65 97 76 49 27 49]

第二趟排序後 13 27 [65 97 76 49 38 49]

第三趟排序後 13 27 38 [97 76 49 65 49]

第四趟排序後 13 27 38 49 [49 97 65 76]

第五趟排序後 13 27 38 49 49 [97 97 76]

第六趟排序後 13 27 38 49 49 76 [76 97]

第七趟排序後 13 27 38 49 49 76 76 [ 97]

最後排序結果 13 27 38 49 49 76 76 97

  2.3. 程序實現

/// <summary>
/// 選擇排序
/// </summary>
/// <param name="dblArray"></param>

private static void SelectSort(ref double[] dblArray)
{
 for(int i =0 ; i< dblArray.Length; i++)
 {
  double MinValue = dblArray[i] ;
  int MinValueIndex = i ;
  for(int j = i; j< dblArray.Length; j++)
  {
   if(MinValue > dblArray[j] )
   {
    MinValue = dblArray[j] ;
    MinValueIndex = j ;
   }
  }
  ExChangeValue(ref dblArray[i], ref dblArray[MinValueIndex]);
 }
}

/// <summary>
/// 交換數據
/// </summary>
/// <param name="A"></param>
/// <param name="B"></param>

private static void ExChangeValue(ref double A , ref double B)
{
 double Temp = A ;
 A = B ;
 B = Temp ;
}

 

3. 冒泡排序

  3.1. 基本思想:

  兩兩比較待排序數據元素的大小,發現兩個數據元素的次序相反時即進行交換,直到沒有反序的數據元素爲止。

  3.2. 排序過程:

  設想被排序的數組R[1..N]垂直豎立,將每個數據元素看作有重量的氣泡,根據輕氣泡不能在重氣泡之下的原則,從下往上掃描數組R,凡掃描到違反本原則的輕氣泡,就使其向上"漂浮",如此反覆進行,直至最後任何兩個氣泡都是輕者在上,重者在下爲止

  【示例】:

49 13 13 13 13 13 13 13

38 49 27 27 27 27 27 27

65 38 49 38 38 38 38 38

97 65 38 49 49 49 49 49

76 97 65 49 49 49 49 49

13 76 97 65 65 65 65 65

27 27 76 97 76 76 76 76

49 49 49 76 97 97 97 97

  3.3. 程序實現

  程序支持順序和倒序排列。

/// <summary>
/// 冒泡算法
/// </summary>
/// <param name="abarray"></param>
/// <param name="IsAscending">是否順序排序</param>
/// <returns></returns>

private static double[] BubbleArithmetic(double[] abarray ,bool IsAscending)
{
 if(abarray.Length > 0 )
 {
  for(int i = abarray.Length-1 ;i >=0 ;i--)
  {
   for(int j = i-1 ; j>=0 ; j--)
   {
    if(CheckAccordCondition(abarray[i],abarray[j],IsAscending))
    {
     ExChangeValue(ref abarray[i],ref abarray[j]);
    }
   }
  }
 }
 return abarray;
}

/// <summary>
/// 交換數據
/// </summary>
/// <param name="A"></param>
/// <param name="B"></param>

private static void ExChangeValue(ref double A , ref double B)
{
 double Temp = A ;
 A = B ;
 B = Temp ;
}

/// <summary>
/// 是否符合條件
/// </summary>
/// <returns></returns>

private static bool CheckAccordCondition(double data1 ,double data2, bool IsAscending)
{
 if(data1 > data2)
 {
  return IsAscending == true ? true :false;
 }
 else
 {
  return IsAscending == true ? false :true ;
 }
}
4. 快速排序

  4.1. 基本思想:

  在當前無序區R[1..H]中任取一個數據元素作爲比較的"基準"(不妨記爲X),用此基準將當前無序區劃分爲左右兩個較小的無序區:R[1..I-1]和R[I+1..H],且左邊的無序子區中數據元素均小於等於基準元素,右邊的無序子區中數據元素均大於等於基準元素,而基準X則位於最終排序的位置上,即R[1..I-1]≤X.Key≤R[I+1..H](1≤I≤H),當R[1..I-1]和R[I+1..H]均非空時,分別對它們進行上述的劃分過程,直至所有無序子區中的數據元素均已排序爲止。

  4.2. 排序過程:

  【示例】:

初始關鍵字 [49 38 65 97 76 13 27 49]

第一次交換後 [27 38 65 97 76 13 49 49]

第二次交換後 [27 38 49 97 76 13 65 49]

第三次交換後 [27 38 13 97 76 49 65 49]

第四次交換後 [27 38 13 49 76 97 65 49]

[27 38 13 49 76 97 65 49]

(一次劃分過程)

初始關鍵字 [49 38 65 97 76 13 27 49]

一趟排序之後 [27 38 13] 49 [76 97 65 49]

二趟排序之後 [13] 27 [38] 49 [49 65]76 [97]

三趟排序之後 13 27 38 49 49 [65]76 97

最後的排序結果 13 27 38 49 49 65 76 97

  各趟排序之後的狀態

  4.3. 程序實現

/// <summary>
/// 快速排序法
/// </summary>
/// <param name="dbArray"></param>
/// <param name="StartIndex"></param>
/// <param name="EndIndex"></param>

private static void QuickSort( ref double[] dbArray ,int StartIndex ,int EndIndex)
{
 //基數
 int CurrentIndex = StartIndex ;
 //順序查找
 bool IsOrderSearched = true ;
 //反序查找
 bool IsDisOrderSearched = true ;
 while(IsOrderSearched || IsDisOrderSearched)
 {
  IsDisOrderSearched = false ;
  IsOrderSearched = false ;
  for(int i =EndIndex ; i>CurrentIndex ;i--)
  {
   if(dbArray[i] < dbArray[CurrentIndex])
   {
    ExChangeValue(ref dbArray[i] ,ref dbArray[CurrentIndex]);
    CurrentIndex = i ;
    IsDisOrderSearched = true ;
    break ;
   }
  }
  for(int i = StartIndex ; i < CurrentIndex ; i++)
  {
   if(dbArray[i] > dbArray[CurrentIndex])
   {
    ExChangeValue(ref dbArray[i] ,ref dbArray[CurrentIndex]);
    CurrentIndex = i ;
    IsOrderSearched = true ;
    break ;
   }
  }
 }
 if( EndIndex - StartIndex > 0 )
 {
  if(CurrentIndex != StartIndex )
  {
   QuickSort(ref dbArray ,StartIndex,CurrentIndex -1);
  }
  if(CurrentIndex != EndIndex)
  {
   QuickSort(ref dbArray ,CurrentIndex+1,EndIndex);
  }
 }
}

/// 交換數據
/// </summary>
/// <param name="A"></param>
/// <param name="B"></param>

private static void ExChangeValue(ref double A , ref double B)
{
 double Temp = A ;
 A = B ;
 B = Temp ;
}

5. 堆排序

  5.1. 基本思想:

  堆排序是一樹形選擇排序,在排序過程中,將R[1..N]看成是一顆完全二叉樹的順序存儲結構,利用完全二叉樹中雙親結點和孩子結點之間的內在關係來選擇最小的元素。

  5.2. 堆的定義:

  N個元素的序列K1,K2,K3,...,Kn.稱爲堆,當且僅當該序列滿足特性:Ki≤K2i Ki ≤K2i+1(1≤ I≤ [N/2])。

點擊放大此圖片

  堆實質上是滿足如下性質的完全二叉樹:樹中任一非葉子結點的關鍵字均大於等於其孩子結點的關鍵字。例如序列10,15,56,25,30,70就是一個堆,它對應的完全二叉樹如上圖所示。這種堆中根結點(稱爲堆頂)的關鍵字最小,我們把它稱爲小根堆。反之,若完全二叉樹中任一非葉子結點的關鍵字均大於等於其孩子的關鍵字,則稱之爲大根堆。

  5.3. 排序過程:

  堆排序正是利用小根堆(或大根堆)來選取當前無序區中關鍵字小(或最大)的記錄實現排序的。我們不妨利用大根堆來排序。每一趟排序的基本操作是:將當前無序區調整爲一個大根堆,選取關鍵字最大的堆頂記錄,將它和無序區中的最後一個記錄交換。這樣,正好和直接選擇排序相反,有序區是在原記錄區的尾部形成並逐步向前擴大到整個記錄區。

  【示例】:對關鍵字序列42,13,91,23,24,16,05,88建堆。

 
 


  5.4. 程序實現

/// <summary>
/// 小根堆排序
/// </summary>
/// <param name="dblArray"></param>
/// <param name="StartIndex"></param>
/// <returns></returns>

private static void HeapSort(ref double[] dblArray )
{
 for(int i = dblArray.Length -1 ; i >= 0; i--)
 {
  if(2*i+1<dblArray.Length)
  {
   int MinChildrenIndex = 2*i+1 ;
   //比較左子樹和右子樹,記錄最小值的Index
   if(2*i+2 < dblArray.Length )
   {
    if(dblArray[2*i+1]>dblArray[2*i+2])
     MinChildrenIndex = 2*i+2;
   }
   if(dblArray[i] > dblArray[MinChildrenIndex])
   {
    ExchageValue(ref dblArray[i],ref dblArray[MinChildrenIndex]);
    NodeSort(ref dblArray ,MinChildrenIndex);
   }
  }
 }
}

/// <summary>
/// 節點排序
/// </summary>
/// <param name="dblArray"></param>
/// <param name="StartIndex"></param>

private static void NodeSort(ref double[] dblArray,int StartIndex)
{
 while(2*StartIndex+1 < dblArray.Length)
 {
  int MinChildrenIndex = 2*StartIndex+1 ;
  if(2*StartIndex+2 < dblArray.Length )
  {
   if(dblArray[2*StartIndex+1]>dblArray[2*StartIndex+2])
   {
    MinChildrenIndex = 2*StartIndex+2;
   }
  }
  if(dblArray[StartIndex] > dblArray[MinChildrenIndex])
  {
   ExchageValue(ref dblArray[StartIndex],ref dblArray[MinChildrenIndex]);
   StartIndex = MinChildrenIndex ;
  }
 }
}

/// <summary>
/// 交換值
/// </summary>
/// <param name="A"></param>
/// <param name="B"></param>

private static void ExchageValue(ref double A , ref double B)
{
 double Temp = A ;
 A = B ;
 B = Temp ;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章