八種基本的排序(2)——直接選擇排序(C語言實現)

-

八種基本的排序(1)——冒泡排序(C語言實現)

八種基本的排序(2)——直接選擇排序(C語言實現)

八種基本的排序(3)——插入排序(C語言實現)

八種基本的排序(4)——歸併排序(C語言實現)

八種基本的排序(5)——快速排序(C語言實現)


目錄


選擇排序(Selection sort)

是一種簡單直觀的排序算法。1它的工作原理是每一次從待排序的數據元素中選出最小(或最大)的一個元素,存放在序列的起始位置,直到全部待排序的數據元素排完。 選擇排序是不穩定的排序方法(比如序列[5, 5, 3]第一次就將第一個[5]與[3]交換,導致第一個5挪動到第二個5後面)。
排序算法即解決以下問題的算法:

輸入

n個數的序列a1,a2,a3,...,an

輸出

原序列的一個重排a1,a2,a3,...,an ,使得a1<=a2<=a3<=...<=an
排序算法有很多,包括插入排序,冒泡排序,堆排序,歸併排序,選擇排序,計數排序,基數排序,桶排序,快速排序等。插入排序,堆排序,選擇排序,歸併排序和快速排序,冒泡排序都是比較排序,它們通過對數組中的元素進行比較來實現排序,其他排序算法則是利用非比較的其他方法來獲得有關輸入數組的排序信息。

思想

n 個記錄的文件的直接選擇排序可經過n1 趟直接選擇排序得到有序結果:
①初始狀態:無序區爲R[1..n] ,有序區爲空。
②第1趟排序
在無序區R[1..n] 中選出關鍵字最小的記錄R[k] ,將它與無序區的第1個記錄R[1] 交換,使R[1..1] 和R[2..n] 分別變爲記錄個數增加1個的新有序區和記錄個數減少1個的新無序區。
……
③第i 趟排序
i 趟排序開始時,當前有序區和無序區分別爲R[1..i1]R(i..n 。該趟排序從當前無序區中選出關鍵字最小的記錄 R[k],將它與無序區的第1個記錄R 交換,使R[1..i]R 分別變爲記錄個數增加1個的新有序區和記錄個數減少1個的新無序區。

通俗的解釋

對比數組中前一個元素跟後一個元素的大小,如果後面的元素比前面的元素小則用一個變量k來記住他的位置,接着第二次比較,前面“後一個元素”現變成了“前一個元素”,繼續跟他的“後一個元素”進行比較如果後面的元素比他要小則用變量k 記住它在數組中的位置(下標),等到循環結束的時候,我們應該找到了最小的那個數的下標了,然後進行判斷,如果這個元素的下標不是第一個元素的下標,就讓第一個元素跟他交換一下值,這樣就找到整個數組中最小的數了。然後找到數組中第二小的數,讓他跟數組中第二個元素交換一下值,以此類推。


時間複雜度

排序算法複雜度對比lgn=log2n
排序算法複雜度對比lgn=log2n
選擇排序的交換操作介於 0 和(n1 次之間。選擇排序的比較操作爲n(n12 次之間。選擇排序的賦值操作介於 0 和3(n1 次之間。
比較次數O(n2 ,比較次數與關鍵字的初始狀態無關,總的比較次數N=(n1+(n2+...+1=n(n12 。交換次數O(n ,最好情況是,已經有序,交換0次;最壞情況交換n1 次,逆序交換n2 次。交換次數比冒泡排序少多了,由於交換所需CPU時間比比較所需的CPU時間多,n 值較小時,選擇排序比冒泡排序快。


穩定性

選擇排序是給每個位置選擇當前元素最小的,比如給第一個位置選擇最小的,在剩餘元素裏面給第二個元素選擇第二小的,依次類推,直到第n1 個元素,第n 個元素不用選擇了,因爲只剩下它一個最大的元素了。那麼,在一趟選擇,如果一個元素比當前元素小,而該小的元素又出現在一個和當前元素相等的元素後面,那麼交換後穩定性就被破壞了。比較拗口,舉個例子,序列58529 ,我們知道第一遍選擇第1個元素5會和2交換,那麼原序列中兩個5的相對前後順序就被破壞了,所以選擇排序是一個不穩定的排序算法。


下面就是源代碼了

源代碼+註釋

函數版
//選擇排序(從小到大排)
#include<stdio.h>
int number[100000000];    //在主函數外定義數組可以更長多了 
void select_sort(int R[],int n)    //定義選擇排序函數"select_sort" 
{
    int i,j,k,index;    //定義變量 
    for(i=0;i<n-1;i++)   //遍歷 
    {
        k=i;
        for(j=i+1;j<n;j++)    //j初始不爲0,冒泡初始爲0,所以選排比冒泡快,但不穩定 
        {
            if(R[j]<R[k])   //順序從這裏改順序 小到大"<",大到小">" !!!
                k=j;      //這裏是區分冒泡排序與選擇排序的地方,冒泡沒這句 
        }
        if(k!=j)    //爲了嚴謹,去掉也行 
        {
            index=R[i];   //交換R[i]與R[k]中的數 
            R[i]=R[k];    //簡單的交換c=a,a=b,b=c 
            R[k]=index;
        }
    }
} 

int main()     //主程序 
{
    int i,n;
    printf("輸入數字個數:\n");    
    scanf("%d",&n);     //輸入要排序的數字的個數 
    printf("輸入%d個數:\n",n);
    for(int j=0;j<n;j++)     //將所有數全放入number數組中 
        scanf("%d",&number[j]) ;
    select_sort(number,n);   //引用選擇排序select_sort的函數 
    for (i=0;i<n-1;i++)    //用for循環輸出排完排完序的數組 
        printf("%d ",number[i]);   //這樣寫是爲了格式(最後一個數後面不能有空格)                                  
    printf("%d\n",number[i]);
    return 0;   //好習慣 
}
//ENDING

普通版
//選擇排序(從小到大排)
#include<stdio.h>
int number[100000000];    
int main()     
{
    int i,n,k,index,j;
    printf("輸入數字個數:\n");    
    scanf("%d",&n);     
    printf("輸入%d個數:\n",n);
    for(int ii=0;ii<n;ii++)    
        scanf("%d",&number[ii]) ;
    for(i=0;i<n-1;i++)   
    {
        k=i;
        for(j=i+1;j<n;j++)   
        {
            if(number[j]<number[k])   //順序從這裏改 !!!
                k=j;     
        }
        if(k!=j)    
        {
            index=number[i];  
            number[i]=number[k];   
            number[k]=index;
        }
    }
    for (i=0;i<n-1;i++)   
        printf("%d ",number[i]);                                  
    printf("%d\n",number[i]);
    return 0;   
}
//ENDING

希望大家喜歡這篇文章!!!
如有問題請留言,謝謝!!!

>>>我的博客<<<

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