2017.01.09:排序與搜索

排序和搜索

1.所謂的內排序是指所有的數據已經讀入內存。在內存中進行排序的算法;同時,內排序也一般假定所有用到的輔助空間可以直接存在於內存中。與之對應,另一類排序稱爲外排序,即內存中無法保存全部數據,需要進行磁盤訪問,每次讀入部分數據到內存進行排序。

 

合併排序:利用分而治之的思想,對兩部分非別進行排序,排序完成後,在將各自排序好的兩個部分合並還原成一個有序結構;算法的時間複雜度爲O(nlog n)。

 //合併函數
void Merge(int *_Array, int p, int q, int r) {// p:第0個;r:第n-1個數,q:第(r + p) / 2個數 
    int len1 = q - p + 1;
    int len2 = r - q;
    int *L = new int[len1 + 1];//用動態數組儲存左邊的數 
    int *R = new int[len2 + 1];//用動態數組儲存右邊的數 

    for (int i = 0; i < len1; i++) {// 把Array數組左邊的數放入L數組 
        L[i] = _Array[p + i];
    }

    for (int j = 0; j < len2; j++) {// 把Array數組右邊的數放入R數組 
        R[j] = _Array[q + 1 + j];
    }
    L[len1]=R[len2]=INT_MAX;    //定義無窮大 
    int i = 0, j = 0;
    for (int k = p; k <= r; k++) {
        if (L[i] < R[j]) {//小的放左邊,大的放右邊 
            _Array[k] = L[i];
            i++;
        }
        else {
            _Array[k] = R[j];
            j++;
        }
    }
}
//  歸併排序
void MergeSort(int _Array[], int p, int r) {
    if (p < r) {//p:第0個;r:第n-1個數。數組至少要有兩個數據 
        int q;
        q = (r + p) / 2;//拆分兩組 
        MergeSort(_Array , p , q);//拆分第0個到第 (r + p) / 2個 ,即拆分左半部分 
        MergeSort(_Array , q+1 , r);//拆分第(r + p) / 2個到第r個 ,即拆分右半部分 
        Merge(_Array , p , q , r);//調用合併函數,從第0個到第n-1個排好 
    }
}

快速排序:隨機選定一個元素作爲軸值,利用該軸值將數據分爲左右兩個部分,左邊元素都比軸值小,右邊元素都比軸值大,但他們不是完全排序的,在此基礎上,分別對左右兩堆遞歸調用快速排序。算法的時間複雜度爲O(nlog n),在最壞的情況下爲O(n^2),額外空間複雜度O(log n)。


//快速排序
void quick_sort(int s[], int l, int r)
{
    if (l < r)
    {
		//Swap(s[l], s[(l + r) / 2]); //將中間的這個數和第一個數交換 參見注1
        int i = l, j = r, x = s[l];
        while (i < j)
        {
            while(i < j && s[j] >= x) // 從右向左找第一個小於x的數
				j--;  
            if(i < j) 
				s[i++] = s[j];
			
            while(i < j && s[i] < x) // 從左向右找第一個大於等於x的數
				i++;  
            if(i < j) 
				s[j--] = s[i];
        }
        s[i] = x;
        quick_sort(s, l, i - 1); // 遞歸調用 
        quick_sort(s, i + 1, r);
    }
}

堆排序:每次將剩餘的最大元素移動到數組的最右邊。算法的時間複雜度爲O(nlog n),空間複雜度O(1)。

//堆排序函數
void HeapSort(int a[],int length)
{
    int temp;
    BuildMaxHeap(a,length);
    for (int i = length - 1; i >= 1; i--)
    {
        //交換根節點和數組的最後一個節點
        temp = a[i];
        a[i] = a[0];
        a[0] = temp;
        MaxHeapify(a, 0, 0, i-1);//維護從下標爲i-1到0的子數組
    }
}

桶排序和基數排序:不需要進行數據之間的兩輛比較,但是需要事先知道數組的一些具體情況。桶排序適用於知道待排序數組大小範圍的情況,其特性在於將數據根據其大小,放入合適的桶中,再依次從桶中取出,形成有序序列。基數排序,進行了K次桶排序。

void radixsort(int data[], int n) //基數排序  
{  
    int d = maxbit(data, n);  
    int tmp[n];  
    int count[10]; //計數器  
    int i, j, k;  
    int radix = 1;  
    for(i = 1; i <= d; i++) //進行d次排序  
    {  
        for(j = 0; j < 10; j++)  
            count[j] = 0; //每次分配前清空計數器  
        for(j = 0; j < n; j++)  
        {  
            k = (data[j] / radix) % 10; //統計每個桶中的記錄數  
            count[k]++;  
        }  
        for(j = 1; j < 10; j++)  
            count[j] = count[j - 1] + count[j]; //將tmp中的位置依次分配給每個桶  
        for(j = n - 1; j >= 0; j--) //將所有桶中記錄依次收集到tmp中  
        {  
            k = (data[j] / radix) % 10;  
            tmp[count[k] - 1] = data[j];  
            count[k]--;  
        }  
        for(j = 0; j < n; j++) //將臨時數組的內容複製到data中  
            data[j] = tmp[j];  
        radix = radix * 10;  
    }  
}  


快速選擇算法:利用快速排序的思想,時間複雜度是O(n)。

二分查找:算法複雜度爲O(logn)。

 int binarySearch(int *array, int left, int right, int value){
	 if(left>right){
		 return -1;
	 }
	 
	 int mid = right - (right - left)/2;
	 if(array[mid] == value){
		 return mid;
	 } else if(array[mid] < value){
		 return binarySearch(array,mid+1,right, value);
	 } else {
		 return binarySearch(array, left, mid-1, value);
	 }
 }




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