排序 選擇排序&&堆排序

選擇排序&&堆排序算法

1.選擇排序:   數組

  介紹:選擇排序(Selection sort)是一種簡單直觀的排序算法。它的工做原理以下。首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,而後,再從剩餘未排序元素中繼續尋找最小(大)元素,而後放到已排序序列的末尾。以此類推,直到全部元素均排序完畢。數據結構

  步驟:假設數組array長度爲N即有數組內有N個數據未排序數據
優化

  1.第一趟遍歷將這N個數據中最小的數據和array[0]交換。
spa

  2.第二趟則遍歷N-1個數據,將這N-1個數據中最小的和array[1]交換(第二趟中的數組是從原數組中的array[1]開始即排除第一趟中最小的數據再進行交換)。
設計

  ...
code

 

  程序實現:blog

方法1:每趟選擇最小數據進行交換排序

 1 void SelectSort(int* _array, size_t _arraySize)
 2 {
 3     assert(_array&&_arraySize);
 4     for (size_t i = 0;i < _arraySize;++i)
 5     {
 6         int MinIndex = i;//記錄首位置下標
 7         for (size_t j = i + 1;j < _arraySize;++j)
 8         {
 9             if (_array[MinIndex] > _array[j])//比較首位置以後的各個元素並將最小數據的下標賦給MinIndex
10                 MinIndex = j;
11         }
12         //if (MinIndex != i)//防止首元素即最小時進行交換,減小沒必要要開銷
13             swap(_array[MinIndex], _array[i]);
14     }
15     return;
16 }

方法2:與方法一相似,進行了優化,每趟將最小數據置首,將最大元素置尾索引

 

 1 void SelectSort_optimize(int* _array, int _arraySize)
 2 {
 3     assert(_array&&_arraySize);
 4 
 5     int left = 0;
 6     int right = _arraySize - 1;
 7     for (;left <= right;++left,--right)//每一趟找到最大值和最小值減小循環次數
 8     {
 9         int MinIndex = left;
10         int MaxIndex = right;
11         for (int index = left;index <= right;++index)//此時數組爲閉區間,與未優化時存在差別
12         {
13             if (_array[MinIndex] > _array[index])
14                 MinIndex = index;
15             if (_array[MaxIndex] < _array[index])
16                 MaxIndex = index;
17         }
18         if (left != MinIndex)
19         {
20             swap(_array[left], _array[MinIndex]);
21             if (left == MaxIndex)//避免若是最大值爲_array[left]時,將被上一步操做移到_array[MinIndex]後出錯
22                 MaxIndex = MinIndex;//將MaxIndex更新
23         }
24         if (right != MaxIndex)
25             swap(_array[right], _array[MaxIndex]);
26     }
27     return;
28 }

 

效率分析:

  算法穩定性:不穩定

  時間複雜度:O(n^2)

  空間複雜度:O(1)

2.堆排序
  介紹:堆排序(Heapsort)是指利用堆積樹(堆)這種數據結構所設計的一種排序算法,它是選擇排序的一種。能夠利用數組的特色快速定位指定索引的元素。堆分爲大堆和小堆,是徹底二叉樹升序排序時使用大堆,降序排序時使用小堆。

   步驟:對數組_array進行升序排序,假設數組array長度爲N即有數組內有N個數據未排序數據

    1:將_array中的N個數據構成大堆後,此時最大值即爲_array[0],而後將_array[0]與_array[N-1]交換。

   2:除_array[N-1]外,其他數據繼續創建大堆後,此時最大值仍爲_array[0],而後將_array[0]與_array[N-2]交換。

   ...

  根據下面網址演示能夠清楚理解堆排序的過程

http://www.tyut.edu.cn/kecheng1/site01/suanfayanshi/heap_sort.asp

 程序實現:

 

 1 void AdjustDown(int* _arr,size_t ParIndex,int _arrSize)//從父節點開始向下調整
 2 {
 3     size_t ChildIndex = ParIndex * 2 + 1;//找出父節點的左子樹下標
 4 
 5     while (ChildIndex < _arrSize)
 6     {
 7         if ((_arr[ChildIndex] < _arr[ChildIndex + 1]) && ((ChildIndex + 1) < _arrSize))//找出父節點的左右子樹中的較大值的下標
 8             ChildIndex++;
 9         if (_arr[ParIndex] < _arr[ChildIndex])
10         {
11             swap(_arr[ParIndex], _arr[ChildIndex]);//若是父節點數據小於子節點數據則交換
12             ParIndex = ChildIndex;    //繼續調整交換後的子樹,保證堆中任意子樹均爲大堆
13             ChildIndex = ParIndex * 2 + 1;
14         }
15         else//若是_arr[ParIndex] > _arr[ChildIndex]則說明其已經爲大堆且子樹也爲大堆,跳出循環
16             break;
17     }
18 }
19 void HeapSort(int* _array, int _arraySize)
20 {
21     assert(_array&&_arraySize > 0);
22     //建堆
23     for (int i = _arraySize / 2 - 1;i >= 0;--i)//從最後一個非葉子節點開始向下調整直到根節點調整完
24         AdjustDown(_array, i, _arraySize);
25 
26     for (int j = _arraySize - 1;j > 0;--j)
27     {
28         swap(_array[0], _array[j]);
29         AdjustDown(_array, 0,j);
30     }
31     return;
32 }

下面是當數組爲{3,12,24,2,6}時的排序過程

 

效率分析:

  算法穩定性:不穩定

  時間複雜度:O(n^lg n)

  空間複雜度:O(1)

相關文章
相關標籤/搜索