演算法 排序 選擇排序(直接選擇和堆排序)

2021-07-07 01:23:37 字數 2663 閱讀 9866

這裡介紹兩種選擇排序演算法:直接選擇排序和堆排序

選擇排序基本思想:每一趟從待排序的序列中選出關鍵字最小(最大)的元素,順序放在已排好序的子串行的最後,直到全部元素排序完畢。

1、直接選擇排序

基本原理:每一次從待排序序列中選取最小的元素順序放在以排好的序列後面,例如序列r,先從r中選擇最小的元素,將之與r[0]交換,使這個最小值在序列最前端,然後再在剩餘的n-1個元素中選取最小的元素與r[1]交換,使之在序列的第二個位置,依此迴圈,直到最後排序完畢,n個元素的序列共需要進行n-1次比較選擇就可以得到排序後的序列。直接選擇排序屬於就地排序,但是是不穩定的例如(2,2,1)。

動畫:2、堆排序

若將此序列所儲存的向量r[1..n]看做是一棵完全二叉樹的儲存結構,則堆實質上是滿足如下性質的完全二叉樹:樹中任一非葉結點的關鍵字均不大於(或不小於)其左右孩子(若存在)結點的關鍵字。

【例】關鍵字序列(10,15,56,25,30,70)和(70,56,30,25,15,10)分別滿足堆性質(1)和(2),故它們均是堆,其對應的完全二叉樹分別如小根堆示例和大根堆示例所示。

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

大根堆排序基本原理和過程:利用堆的結構特徵,將堆頂最大元素和堆尾元素交換,使之處於堆尾,然後對堆進行調整,使剩餘的元素中最大的又在堆頂,從而與堆尾倒數第爾個數交換,迴圈,就能將堆重的元素從大到小依次從堆尾排到堆頂;前提是要初始化堆,使資料按堆的結構排列;

動畫:下面簡單說明一下大根堆排序實現**:這裡新建了3個函式:

void heapinit(vector &vec);

void heapsock(vector &vec);

void heapadjust(vector &vec,int n,int m);

分別用來進行堆初始化,堆排序,堆調整;

初始資料要通過堆初始化,使資料結構符合大根堆的結構模式。然後對堆進行排序,每選擇一次堆元素(堆頂元素排序)後,需要重新對剩餘資料進行調整,使之依然符合堆結構。

下面為兩種排序方法的**實現:

#include 

#include

using

namespace

std;

const

int n = 20; //定義常量 也可以這樣 #define n 20

void disp(vector

vec); //輸出函式,

void selectsort(vector

&vec); //直接選擇演算法

void selectsort2(vector

&vec); //直接選擇演算法2(改進)

void heapinit(vector

&vec); //堆初始

void heapsock(vector

&vec); //排序

void heapadjust(vector

&vec,int n,int m); //堆調整

int main()

; for(int i = 0; i < n; i++)

vec1[i] = a[i];

vec2 = vec1;

vec2[0] = 0; //這裡為了方便,堆排序從vec2[1]開始

disp(vec1);

disp(vec2);

selectsort2(vec1); //直接選擇排序

heapsock(vec2); //堆排序

disp(vec1);

disp(vec2);

return0;}

void disp(vector

vec) //輸出函式

void selectsort(vector

&vec)}}

}//另一種實現方法,不用每次都對值進行交換,只需記錄位置資訊即可

void selectsort2(vector

&vec)

if(pos != i)

}}void heapinit(vector

&vec)//注意這裡樹的頂端節點為1,不是0,為了方便,這裡對vec1的1-19個數排序,忽略vec[0]

}else

if(2*i <= n-1 && 2*i + 1 > n-1) //只有左子節點的情況}}

heapadjust(vec,2,n-1); //從堆的第二個節點開始進行調整

/* for(int j = 2; j<=(n-1)/2; j++) //從第二個節點開始,向下調整堆

}else if(2*j <= n-1 && 2*j + 1 > n-1) //注意邊界,只有左子節點的情況}}

*/}void heapsock(vector

&vec)

}void heapadjust(vector

&vec, int n, int m)

}else

if(2*j <= m && 2*j + 1 > m) //注意邊界,只有左子節點的情況}}

}

選擇類排序 直接選擇與堆排

思想 一開始整個陣列預設是無序區,有序區元素為空,每趟從無序區裡面選出乙個最小的元素,與無序區的第乙個元素進行交換,整個時候有序區的元素的元素 1,無序區的元素會 1,下一趟排序再從無序區選擇乙個最小的與無序區的元素進行交換,無序區元素 1.有序區 1,以後執行同樣的操作 如下 void selec...

排序演算法(直接選擇排序)

為什麼我們要叫直接選擇排序呢?在最開始的時候,待排序區間是整個陣列,從區間選乙個最小的與區間第乙個交換位置,然後將待排序區間從第二個開始,繼續以上操作,直至待排序區間長度為0 我們還是以為例 初始 3 5 7 9 8 6 2 1 4 0 第一趟 05 7 9 8 6 2 1 4 3 第二趟 0 17...

排序演算法 直接選擇排序

選擇排序的基本思想是 每一趟從待排序的記錄中選出關鍵字最小的記錄,順序放入已排序數列的最後,直到全部記錄排序完畢。直接選擇排序是一種簡單直觀的排序演算法。它的工作原理 首先在未排序序列中找到最小 大 元素,存放到排序序列的起始位置,然後,再從剩餘未排序元素中繼續尋找最小 大 元素,然後放到已排序序列...