程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 排序算法詳解(三)

排序算法詳解(三)

編輯:C++入門知識

前面說了插入排序和快速排序,下面我們來看一下選擇排序。

選擇排序的基本思想是:每一趟在n-i+1的記錄中選個去關鍵字最小的記錄作為有序序列的第i個記錄。我們先來看下選擇排序中最簡單的方法,簡單選擇排序,其使用與序列元素比較少的情況。

簡單選擇排序的基本思想是,在要排序的元素序列中找到一個最小的元素,將它與序列的第一個元素進行交換,然後在剩余的n-1個元素中在找到最小的,跟剩余序列中的第一個元素進行交換,重復此過程直到全部選擇完成。

其算法思想很簡單,下面我們來看一個簡單選擇排序的小例子,進一步加深對此算法的理解:

[cpp] 
#include<stdio.h> 
#include<stdlib.h> 
 
#define N 100 
 
void Selectsort(int *arr,int n) 

    int i,j,min,t; 
    for(i=0;i<n-1;i++) 
    { 
        min = i; 
        for(j=i+1;j<n;j++) 
        { 
            if(arr[j]<arr[min]) 
                min = j; 
        } 
        if(min-i) 
        { 
            t = arr[min]; 
            arr[min] = arr[i]; 
            arr[i] = t;  
        } 
    } 
    for(i=0;i<n;i++) 
        printf("L[%d]=%d\n",arr[i]); 

 
int main() 

    int i,n,L[N]; 
    scanf("%d",&n); 
    for(i=0;i<n;i++) 
        scanf("%d",&L[i]); 
    Selectsort(L,n); 
    return 0; 

由上面的分析可以看出,簡單選擇排序的時間復雜度為O(n2)。是不穩定的排序算法。
當數據量比較大的時候,簡單選擇排序就不太適用了,那麼我們下來看另外一種選擇排序,堆排序,其適用於大數據量的排序。

首先我們來看下什麼是堆。堆的定義是:具有n個元素的序列(h1,h2,...,hn),當且僅當滿足(hi>=h2i,hi>=2i+1)或(hi<=h2i,hi<=2i+1)(i=1,2,...,n/2)時稱之為堆。了解了堆以後,我們就來看下如何實現堆排序。(使用大跟堆)

1、先將初始初始序列L[0..n-1]建成一個大根堆,此堆為初始的無序區。

2、然後將最大的元素L[0](即堆頂)和無序區的最後一個記錄L[n-1]交換,由此得到新的無序區L[0..n-2]和有序區L[n-1],且滿足L[0..n-2]≤L[n-1]。

3、將當前無序區L[0..n-2]調整為堆,然後再次將L[0..n-2]中最大的元素L[0]和該區間的最後一個記錄L[n-2]進行交換,這樣有得到新的無序區L[0..n-3]和有序區L[n-2..n-1],且仍滿足關系L[0..n- 3]≤L[n-2..n-1]。

4、再將無序區調整為堆,重復以上步驟直到無序區只有一個元素為止。

前面每交換一次元素後都要重新將無序區調成為堆,那麼一個序列怎樣轉化為堆呢,下面我們來看下如何創建一個堆。

從一個無序序列建堆的過程就是一個反復篩選的過程。如將此序列看成是一個完全二叉樹,則最後一個非終端節點是第 n/2 個元素,由此篩選就從n/2開始即可。從n/2第一個非終端節點開始,比較其左右子樹的根節點,如果大於左右子樹根節點,那麼不做變動,如果小於左右子樹根節點的最大值,那麼就與這個最大值交換位置,然後繼續從n/2-1個非終端節點開始繼續比較,知道所有非終端節點比較完成,一個堆就初始化完成了。

堆排序聽起來比較復雜,那麼我們下來看一個堆排序的例子加深對堆排序的理解:

[cpp] 
#include<stdio.h> 
#include<stdlib.h> 
 
#define N 100 
 
void HeapAdjust(int *arr,int n)   //建堆函數 

    int t,i,j,start,max; 
    start = n/2;     
    for(i=start;i>0;i--) 
    { 
        max = 2*i-1; 
        if(2*i+1<=n) 
            if(arr[2*i-1]<arr[2*i]) 
                max++; 
        if(arr[i-1]<arr[max]) 
        { 
            t = arr[max]; 
            arr[max] = arr[i-1]; 
            arr[i-1] = t; 
        } 
    } 
    t = arr[n-1];          //後面三行是將堆的根節點與最後一個元素進行交換 
    arr[n-1] = arr[0]; 
    arr[0] = t; 

 
void Heapsort(int *arr,int n)     //堆排序函數 

    int i; 
    for(i=n;i>0;i--) 
        HeapAdjust(arr,i); 
    for(i=0;i<n;i++) 
        printf("L[%d]=%d\n",i,arr[i]); 

 
int main() 

    int i,n,L[N]; 
    scanf("%d",&n); 
    for(i=0;i<n;i++) 
        scanf("%d",&L[i]); 
    Heapsort(L,n); 
    return 0; www.2cto.com

堆排序的時間復雜度是O(nln n)。是不穩定的排序算法。
以上就是對幾種基本的排序算法進行了一個大概的說明,代碼都是自己編寫,有什麼問題歡迎指正。


作者:wanchres

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved