選擇排序

  選擇排序的基本方法是:每步從帶排序的元素中選出關鍵詞最小(或最大)的元素,順序放在已排序的元素的最後,直到全部排序完爲止。這裏介紹簡單選擇排序和堆排序。

簡單選擇排序

1.算法思想
  每次從無序區中挑選出一個最小的值,將其與無序區的第一個元素交換,初始有序區爲空,無序區包含所有待排序元素。

2.性能分析
  簡單選擇排序算法的效率與初始數據的順序無關。

這裏寫圖片描述

3.完整代碼

#include<iostream>
using namespace std;

void select_sort(int a[], int n) {
    int k,temp=0;
    //每次從無序區中選出最小的元素與無序區的第一個元素交換 
    for(int i=0;i<n;++i) {
        //k標記無序區最小元素 
        k=i;
        for(int j=i+1;j<n;++j)
            if(a[j]<a[k])
                k = j;

        if(k!=i) {
            temp = a[i];
            a[i] = a[k];
            a[k] = temp;
        }
    }
}

//輸出數組
void print_array(int a[],int n) {
    for(int i=0;i<n;++i){
        cout<<a[i]<<" ";
    }
    cout<<endl;
} 

int main() {
    //簡單選擇排序測試數據 
    int a[] = {7,3,1,12,5,9};
    int n = 6;
    cout<<"Before sort:";
    print_array(a,n);
    cout<<"After binary insertion:";
    select_sort(a,n);
    print_array(a,n); 

    return 0; 
} 

測試結果如下:

這裏寫圖片描述

堆排序

1.算法思想
  首先按照大根推的定義將數組調整爲堆(初始建堆),交換根結點a[0]和最後一個結點a[n-1](將最大元素a[0]歸位);然後將a[0]~a[n-2]重新調整爲堆,交換a[0]和a[n-2];如此反覆,直到交換了a[0]和a[1]。

2.算法過程
(1)維護堆的性質
  AMX-HEAPIFY是用於維護最大堆性質的重要過程。它的輸入爲一個數組a和一個下標i。在調用MAX-HEAPIFY的時候,我們假定根結點爲LEFT(i)和RIGHT(i)的二叉樹都是最大堆,但這時a[i]有可能小於其孩子,這樣就違背了最大堆的性質。MAX-HEAPIFY通過讓a[i]在最大堆中“逐級下降”,從而使得以下標i爲根結點的字數重新遵循最大堆的性質。

//假設以index爲結點的左右子樹Left(index)和Right(index)都爲最大堆
//這時a[index]可能小於其孩子
//maxHeapify通過讓a[index]在最大堆中“逐級下降”來維持最大堆的性質 
void maxHeapify(int a[], int index) {
    int l = Left(index);
    int r = Right(index);
    int largest = 0;
    if(l<heapSize && a[l]>a[index])     
        largest = l;
    else largest = index;
    if(r<heapSize && a[r]>a[largest])
        largest = r;
    if(largest != index) {
        swap(&a[largest],&a[index]);
        maxHeapify(a,largest);
    }   
}

(2)建堆
  我們可以用自底向上的方法利用過程MAX-HEAPIFY把一個大小爲n=A.length的數組a[0]~a[n-1]轉換爲最大堆。我們知道,每個葉子節點都可以堪稱只包含一個元素的堆,通過過程BUILD-MAX-HEAP對樹中非葉子結點從下標最大的開始都調用一次MAX-HEAPIFY來建堆。

void buildMaxHeap(int a[],int length) {
    heapSize = length;
    //含有n個結點的堆的下標最大的非葉子結點的標號爲(n-2)/2
    for(int i=(length-2)>>1;i>=0;--i)
        maxHeapify(a,i); 
} 

(3)堆排序算法
  調用過程BUILD-MAX-HEAP初始化堆,交換a[0]與堆中最後一個結點,調用MAX-HEAPIFY(a,0),重複這一過程直到堆的大小爲1。

void heap_sort(int a[], int length) {
    //初始化堆
    buildMaxHeap(a,length);
    //選擇堆的根結點與最後一個結點交換
    for(int i=length-1;i>=1;--i){
        swap(&a[i],&a[0]);
        --heapSize;
        maxHeapify(a,0);
    }
}

3.性能分析
  堆排序的時間效率與帶排序數據的順序無關。

這裏寫圖片描述

4.完整代碼

#include<iostream>
using namespace std;

int heapSize = 0;

int  Left(int index) {
    return (index<<1)+1;
}

int Right(int index) {
    return (index<<1)+2;
}

void swap(int *a, int *b) {
    int temp = *a;
    *a = *b;
    *b = temp;
}
//假設以index爲結點的左右子樹Left(index)和Right(index)都爲最大堆
//這時a[index]可能小於其孩子
//maxHeapify通過讓a[index]在最大堆中“逐級下降”來維持最大堆的性質 
void maxHeapify(int a[], int index) {
    int l = Left(index);
    int r = Right(index);
    int largest = 0;
    if(l<heapSize && a[l]>a[index])     
        largest = l;
    else largest = index;
    if(r<heapSize && a[r]>a[largest])
        largest = r;
    if(largest != index) {
        swap(&a[largest],&a[index]);
        maxHeapify(a,largest);
    }   
}

void buildMaxHeap(int a[],int length) {
    heapSize = length;
    for(int i=(length-2)>>1;i>=0;--i)
        maxHeapify(a,i); 
} 

void heap_sort(int a[], int length) {
    buildMaxHeap(a,length);
    for(int i=length-1;i>=1;--i){
        swap(&a[i],&a[0]);
        --heapSize;
        maxHeapify(a,0);
    }
}

//輸出數組
void print_array(int a[],int n) {
    for(int i=0;i<n;++i){
        cout<<a[i]<<" ";
    }
    cout<<endl;
} 

int main() {
    //直接插入測試數據 
    int a[] = {4,10,16,2,12,9,7};
    int n = 7;
    cout<<"Before sort:";
    print_array(a,n);
    cout<<"After heap-sort:";
    heap_sort(a,n);
    print_array(a,n);
    cout<<endl;

    return 0;   
}

測試結果如下:

這裏寫圖片描述

發佈了129 篇原創文章 · 獲贊 45 · 訪問量 24萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章