內部排序之選擇排序 簡單選擇排序和堆排序

2021-06-22 11:43:14 字數 3473 閱讀 2218

1.簡單選擇排序

基本思想:

給定待排陣列,共n個元素,依次比較n個元素,選擇出最大值(或最小值),與a[0]元素替換,然後比較剩下的n-1個元素,同樣得到最大值最大值(或最小值),與a[1]元素替換,以此類推,重複進行。  直到n=1 。此時 陣列順序已排好(降序或公升序)。

**實現:

/**

簡單選擇排序

---基本思想:在要排序的一組數中,選出最小的乙個數與第乙個位置的數交換;

然後在剩下的數當中再找最小的與第二個位置的數交換,如此迴圈到倒數第二個數和最後乙個數比較為止

簡單選擇排序法(****** selection sort)就是通過n-i次關鍵字間的比較,

從n-i+1個記錄中選出關鍵字最小的記錄,並和第i(1≤i≤n)個記錄交換之

**///對陣列a進行 插入排序 ------公升序

void ******slectsort(int *a,int n)

if(min!=i) // a[i] 與a[min] 互換 }}

時間複雜度:外層迴圈(移動次數),最好情況 移動0次,最壞情況(逆序)執行n-1次,記憶體迴圈(比較次數):  執行o(1+2+...+n-1)=o(n(n-1)/2)  所以總的時間複雜度為

移動次數+比較次數=o(n-1)+o(n(n-1)/2)=o(n^2)).

2.堆排序

基本思想:在要排序的一組數中,利用堆的性質 ,選出最小的乙個數與第乙個位置的數交換;

然後在剩下的數當中再找最小的與第二個位置的數交換,如此迴圈到倒數第二個數和最後乙個數比較為止。

堆排序是基於簡單選擇排序的演算法的一種改進演算法。區別:每次迴圈比較時,利用堆的性質,得到最大值或最小值。

<1>現在簡單介紹一下堆的性質:

若將此序列所儲存的向量r[1..n]看做是一棵完全二叉樹的儲存結構,則堆實質上是滿足如下性質的完全二叉樹:

樹中任一非葉子結點的關鍵字均不大於(或不小於)其左右孩子(若存在)結點的關鍵字。

即有:ki<=k(2i)且ki<=k(2i+1)(1≤i≤ n)   小頂堆 (圖二) 或

ki>=k(2i)且ki>=k(2i+1)(1≤i≤ n)  大頂堆(圖一)

//k(i)相當於二叉樹的非葉子結點,k(2i)則是左子節點,k(2i+1)是右子節點。

<2>.堆排序的步驟:

一、建立堆表。 將給定待排序陣列元素  轉換成二叉堆 。

二、 迴圈得到最大值(或是最小值),完成排序。

具體排序流程圖例:

建堆過程:給定陣列a  

從第乙個非葉子節點開始逐一比較  是否滿足大頂堆的性質。

堆排序過程:

建好堆後  取堆頂元素(最大值),然後剩下的元素執行建堆 得新堆。重複比較。直至排好。

**實現:

#include//對陣列a進行 插入排序 ------公升序  

// 堆結構

typedef struct heap_theap;

// 寫函式使得 陣列滿足堆性質。

//思想是:從乙個節點i,和他的孩子leftchild(i),rightchild(i)中找到最大的,

//然後其索引存放在largest中。如果i是最大的。那麼i為根的子樹已經是最大堆,程式結束。

//否則i的某個子節點有最大元素,那麼i的值和largest的值交換。

//下標為largest的節點在交換後作為父節點,那麼他可能又違反堆性質,因此遞迴呼叫該函式。

void maxheapify(heap *hp, unsigned int node)

else }

/*對於1個個數為n的堆,從上面堆的圖中可以分析得到,n/2-1之前的都是父節點。

之後的都是葉子節點,我們只需要對父節點進行maxheapify就可以了。

n/2可以用右移運算n>>1。

*/ /**

arrp待排序陣列 arrlength 表長 heap 堆表

**/

heap *createheap(int *arrp, int arrlength,heap *heap)

//堆排序

/**設堆的陣列為a[0..n-1],呼叫maxheapify函式就可以得到最大值,

然後將最大值和n-1互換,把堆的大小heapmaxindex減1,再次呼叫maxheapify,

又得到最大值,存放在a[0],再和a[n-2]互換,把堆的大小再減一,這樣迴圈下去,

知道堆的大小為0。那麼我們就得到了由小到大的排好序的陣列。

**/void heapsort(heap *hp) }

int main();

int i;

for(i=0;i<10;i++)

printf("\n");

printf("a sort by insert methods:\n");

phpa = createheap(a,10,&hpa);

heapsort(phpa);

for(i=0;i<10;i++)

return 0;

}

堆排序**參考 

堆排序的效能分析:

它的執行時間主要是消耗在初始構建堆和在重建堆時的反覆篩選上。

在構建堆的過程中,因為我們是完全二叉樹從最下層最右邊的非終端結點開始構建,將它與其孩子進行比較和若有必要的互換,對於每個非終端結點來說,其實最多進行兩次比較和互換操作,因此整個構建堆的時間複雜度為o(n)。

在正式排序時,第i次取堆頂記錄重建堆需要用o(logi)的時間(完全二叉樹的某個結點到根結點的距離為.log2i.+1),並且需要取n-1次堆頂記錄,因此,重建堆的時間複雜度為o(nlogn)。

所以總體來說,堆排序的時間複雜度為o(nlogn)。由於堆排序對原始記錄的排序狀態並不敏感,因此它無論是最好、最壞和平均時間複雜度均為o(nlogn)。這在效能上顯然要遠遠好過於冒泡、簡單選擇、直接插入的o(n2)的時間複雜度了。

空間複雜度上,它只有乙個用來交換的暫存單元,也非常的不錯。不過由於記錄的比較與交換是跳躍式進行,因此堆排序也是一種不穩定的排序方法。

另外,由於初始構建堆所需的比較次數較多,因此,它並不適合待排序序列個數較少的情況。

內部排序之簡單選擇排序

簡單選擇排序是最基本的一種選擇排序,這種選擇排序嚴格貼合選擇排序的基本思想。與直接插入排序類似,簡單選擇排序也可以將序列視為兩部分,只是直接插入排序初始的有序序列有乙個元素,簡單選擇排序初始的整個序列都視為待排序序列,有序序列為空。若要使用簡單選擇排序使陣列arr n 成為乙個降序序列,使用i來記錄...

內部排序 簡單選擇排序

n 個記錄進行簡單選擇排序的基本方法是 通過n i 1 i n 在次關鍵字之間比較,從n i 1個記錄中選出關鍵字最小的記錄,並和第i個記錄進行交換,當i等於n時偶有記錄有序排列。簡單選擇排序是一種不穩定的排序方法,時間複雜度為o n2 在排序過程中僅需要乙個元素作為輔助空間用於陣列元素值的交換,空...

選擇排序之簡單選擇排序

選擇排序是幾大排序演算法中的一種,選擇排序的思想如下 每趟從待排序的記錄序列中選擇關鍵字最小的記錄放置到已排序表的最前位置,直到全部排完。選擇排序大概有兩種,今天我們說其中一種 簡單選擇排序。1 基本思想 在要排序的一組數中,選出最小的乙個數與第乙個位置的數交換 然後在剩下的數當中再找最小的與第二個...