拓展排序

歸并排序

歸并排序采用分治的思想:

  • Divide: 將n個元素平均劃分為各含n/2個元素的子序列。
  • Conquer:遞歸解決兩個規模為n/2的子問題。
  • Combine:合并倆個已排序的子序列。
    性能:時間復雜度為O(nlogn),空間復雜度為O(N),算法與初始序列無關,排序是穩定的。
void mergeSort(int arr[], int len) {
   int* a = arr;
   int* b = (int*) malloc(len * sizeof(int));

   for (int size = 1; size < len; size += size) {
       for (int start = 0; start < len; start += size + size) {
           int k = start;
           int left = start, right = min(left + size + size, len), mid = min(left + size, len);

           int start1 = left, end1 = mid;
           int start2 = mid, end2 = right;

           while (start1 < end1 && start2 < end2) {
               b[k++] = a[start1] > a[start2] ? a[start2++] : a[start1++];
           }

           while (start1 < end1) {
               b[k++] = a[start1++];
           }
           while (start2 < end2) {
               b[k++] = a[start2++];
           }
       }
       int* temp = a;
       a = b;
       b = temp;
   }

   if (a != arr) {
       for (int i = 0; i < len; ++i) {
           b[i] = a[i];
       }
       b = a;
   }

   free(b);
}

基數排序
對于有d個關鍵字時,可以分別按關鍵字進行排序。有兩種方法:

  • MSD:先從高位開始進行排序,在每個關鍵字上,可采用基數排序。
  • LSD:先人低位開始進行排序,在每個關鍵字上,可采用桶排序。
    即通過每個數的每位數字的大小來比較
//找出最大數字的位數
int maxNum(int arr[], int len) {
    int _max = 0;

    for (int i = 0; i < len; ++i) {
        int d = 0;
        int a = arr[i];

        while (a) {
            a /= 10;
            d++;
        }

        if (_max < d) {
            _max = d;
        }
    }
    return _max;
}


void radixSort(int *arr, int len) {
    int d = maxNum(arr, len);
    int *temp = new int[len];
    int count[10];
    int radix = 1;

    for (int i = 0; i < d; ++i) {
        for (int j = 0; j < 10; ++j) {
            count[j] = 0;
        }

        for (int k = 0; k < len; ++k) {
            count[(arr[k] / radix) % 10]++;
        }

        for (int l = 1; l < 10; ++l) {
            count[l] += count[l - 1];
        }

        for (int m = 0; m < len; ++m) {
            int index = (arr[m] / radix) % 10;
            temp[count[index] - 1] = arr[m];
            count[index]--;
        }

        for (int n = 0; n < len; ++n) {
            arr[n] = temp[n];
        }
        radix *= 10;

    }

    delete (temp);
}

拓撲排序

在有向圖中找拓撲序列的過程,就是排外排序。 ** 拓撲序列常常用于判定圖是否有環 **。

  • 從有向圖中選擇一個入度為0的結點,輸出它。
  • 將這個結點以及該結點出發的所有邊從圖中刪除。
  • 重復前兩步,直到沒有入度為0的點。

如果 所有的點都被輸出,即存在一個拓撲序列,則圖沒有環。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 背景 一年多以前我在知乎上答了有關LeetCode的問題, 分享了一些自己做題目的經驗。 張土汪:刷leetcod...
    土汪閱讀 12,766評論 0 33
  • 1. Java基礎部分 基礎部分的順序:基本語法,類相關的語法,內部類的語法,繼承相關的語法,異常的語法,線程的語...
    子非魚_t_閱讀 31,739評論 18 399
  • 回溯算法 回溯法:也稱為試探法,它并不考慮問題規模的大小,而是從問題的最明顯的最小規模開始逐步求解出可能的答案,并...
    fredal閱讀 13,712評論 0 89
  • 前言 八大排序,三大查找是《數據結構》當中非常基礎的知識點,在這里為了復習順帶總結了一下常見的八種排序算法。常見的...
    LeeLom閱讀 97,604評論 41 662
  • 都說“男不可不讀王小波,女不可不讀周國平”,可是,作為女生的我慶幸了解到了有思想,敢說真話,深情又有趣的小波。 ...
    Gloria文閱讀 320評論 0 1