C++面試題(七)

在C++中,排序也是一個很重要的東西,下面就對常見的排序算法進行一個總結
1.交換函數

void swap(int *a, int i, int j) //交換兩個數    
{  
        if(i==j)  
           return;  
    int tmp = a[i];  
    a[i] = a[j];  
    a[j] = tmp;  
} 

(1)冒泡排序
依次比較相鄰的數據,將小數據放在前,大數據放在後;即第一趟先比較第1個和第2個數,大數在後,小數在前,再比較第2個數與第3個數,大數在後,小數在前,以此類推則將最大的數”滾動”到最後一個位置;第二趟則將次大的數滾動到倒數第二個位置……第n-1(n爲無序數據的個數)趟即能完成排序。
以下面5個無序的數據爲例:
40 8 15 18 12 (文中僅細化了第一趟的比較過程)
第1趟: 8 15 18 12 40
第2趟: 8 15 12 18 40
第3趟: 8 12 15 18 40
第4趟: 8 12 15 18 40

void bubblesort(int *arr,int nsize)  
{  //排序,從i開始排,總是在[i+1,nsize]去尋找比當前元素小的,並且交換,使得當前位置的值總是其後面最小的。  
    for (int i = 0; i < nsize; i++)  
        for (int j = i + 1; j < nsize; j++)  
            if (arr[i] > arr[j]) swap(arr, i,j);  
} 

(2)選擇排序
以升序爲例,比如在一個長度爲N的無序數組中,
在第一趟遍歷N個數據,找出其中最小的數值與第一個元素交換,
第二趟遍歷剩下的N-1個數據,找出其中最小的數值與第二個元素交換……
第N-1趟遍歷剩下的2個數據,找出其中最小的數值與第N-1個元素交換,
至此選擇排序完成。
以下面5個無序的數據爲例:
56 12 80 91 20(文中僅細化了第一趟的選擇過程)
第1趟:12 56 80 91 20
第2趟:12 20 80 91 56
第3趟:12 20 56 91 80
第4趟:12 20 56 80 91

void selectsort(int *arr, int nsize)  
{  
    for (int i = 0; i < nsize; i++)  
    {  
        //arr[i+1....nsize-1]中找到當前最小值及其位置(準備與當前a[i]調換)    
        int min = arr[i];  
        int minpos = i;  
        for (int j = i + 1; j < nsize; j++)  
        {  
            if (arr[j] < min)  
            {  
                min = arr[j]; //當前最小值    
                minpos = j;//記錄當前最小值的位置    
            }  
        }  
        swap(arr, i, minpos);//交換最小值位置,a[0....i]已經有序  
    }  
}  

(3)插入排序
像撲克摸牌一樣,插入即表示將一個新的數據插入到一個有序數組中,並繼續保持有序。例如有一個長度爲N的無序數組,進行N-1次的插入即能完成排序;第一次,數組第1個數認爲是有序的數組,將數組第二個元素插入僅有1個有序的數組中;第二次,數組前兩個元素組成有序的數組,將數組第三個元素插入由兩個元素構成的有序數組中……第N-1次,數組前N-1個元素組成有序的數組,將數組的第N個元素插入由N-1個元素構成的有序數組中,則完成了整個插入排序。
以下面5個無序的數據爲例:
65 27 59 64 58 (文中僅細化了第四次插入過程)
第1次插入: 27 65 59 64 58
第2次插入: 27 59 65 64 58
第3次插入: 27 59 64 65 58
第4次插入: 27 58 59 64 65

void insertsort(int *arr, int nsize)  
{  
    int i, j, key;  
    for (i = 1; i<nsize; i++)//控制需要插入的元素  
    {  
        key = arr[i]; //key爲當前要插入的元素,將其插入到有序段arr[0,i-1]  
        j = i - 1;  
        while (j >= 0 && arr[j] > key) //查找要插入的位置,循環結束時則找到插入位置j  
        {  
            arr[j+1] = arr[j]; //移動元素的位置.供要插入元素使用  
            j--;  
        }  
        arr[j+1] = key; //插入指定元素到指定位置  
    }  
}  

(4)快速排序
快速排序是C.R.A.Hoare於1962年提出的一種劃分交換排序。它採用了一種分治的策略,該方法的基本思想是:
1.先從數列末尾取出一個數作爲基準元。
2.分區過程,將比這個數大的數全放到它的右邊,小於或等於它的數全放到它的左邊。
3.再對左右區間重複第二步,直到各區間只有一個數。

//手動快速默寫快排:先劃界,再分治....    
int quickPartion(int *arr, int low, int high)  
{  
    int pos = rand() % (high - low + 1) + low;  
    swap(arr, pos, high);//將末尾的元素隨機化,防止極端情況    
    int key = arr[high];//總是將末尾元素選爲關鍵化界元  
    int i = low - 1;//總是記錄比key小的元素最前面的位置  
    for (int j = low; j <= high - 1; j++)  
    {  
        if (arr[j] <= key)  
            swap(arr, ++i, j);  
    }  
    swap(arr, ++i, high);  
    return i;//返回“中間位置”  
}  

void QuickSort(int *arr, int low, int high)  
{  
    if (low < high)  
    {  
        int mid = quickPartion(arr, low, high);  
        QuickSort(arr, low, mid - 1);  
        QuickSort(arr, mid + 1, high);  
    }  
}  
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章