iT邦幫忙

2023 iThome 鐵人賽

DAY 22
0

分而治之

分而治之(Divide and Conquer)是一個古老且廣泛使用的演算法策略。其核心概念是將大問題分解為若干較小的子問題,獨立解決這些子問題,然後組合它們的解以得到原問題的解。

想像你要為一本非常多頁的書寫內容摘要,但因為太大本了,你一個人很難完成。使用分而治之的思路,你可以將書一分為二,給你朋友兩個人各自讀一半的頁數,然後將兩人各自寫的摘要加再一起。你和你朋友也可以繼續再找其他朋友將剩餘部分再次分成更小的部分,直到讀起來變得非常簡單。

而合併排序 (Merge Sort) 是分而治之策略的典型應用

Merge Sort

合併排序 (Merge Sort) 是一種基於分而治之策略的比較排序算法。它的主要概念是將一個大陣列分割成兩個子陣列,分別對它們進行排序,然後合併這兩個已排序的子陣列以產生單一已排序的新陣列。

合併排序可以描述為以下步驟:

  • 分解: 將列表均勻分割成兩半。
  • 解決: 遞迴對兩半進行合併排序。
  • 合併: 將兩半合併為單一已排序的新列表。
// Merges two subarrays of array[].
// First subarray is arr[begin..mid]
// Second subarray is arr[mid+1..end]
void merge(int array[], int const left, int const mid,
           int const right)
{
    int const subArrayOne = mid - left + 1;
    int const subArrayTwo = right - mid;
 
    // Create temp arrays
    auto *leftArray = new int[subArrayOne],
         *rightArray = new int[subArrayTwo];
 
    // Copy data to temp arrays leftArray[] and rightArray[]
    for (auto i = 0; i < subArrayOne; i++)
        leftArray[i] = array[left + i];
    for (auto j = 0; j < subArrayTwo; j++)
        rightArray[j] = array[mid + 1 + j];
 
    auto indexOfSubArrayOne = 0, indexOfSubArrayTwo = 0;
    int indexOfMergedArray = left;
 
    // Merge the temp arrays back into array[left..right]
    while (indexOfSubArrayOne < subArrayOne
           && indexOfSubArrayTwo < subArrayTwo) {
        if (leftArray[indexOfSubArrayOne]
            <= rightArray[indexOfSubArrayTwo]) {
            array[indexOfMergedArray]
                = leftArray[indexOfSubArrayOne];
            indexOfSubArrayOne++;
        }
        else {
            array[indexOfMergedArray]
                = rightArray[indexOfSubArrayTwo];
            indexOfSubArrayTwo++;
        }
        indexOfMergedArray++;
    }
 
    // Copy the remaining elements of
    // left[], if there are any
    while (indexOfSubArrayOne < subArrayOne) {
        array[indexOfMergedArray]
            = leftArray[indexOfSubArrayOne];
        indexOfSubArrayOne++;
        indexOfMergedArray++;
    }
 
    // Copy the remaining elements of
    // right[], if there are any
    while (indexOfSubArrayTwo < subArrayTwo) {
        array[indexOfMergedArray]
            = rightArray[indexOfSubArrayTwo];
        indexOfSubArrayTwo++;
        indexOfMergedArray++;
    }
    delete[] leftArray;
    delete[] rightArray;
}
 
// begin is for left index and end is right index
// of the sub-array of arr to be sorted
void mergeSort(int array[], int const begin, int const end)
{
    if (begin >= end)
        return;
 
    int mid = begin + (end - begin) / 2;
    mergeSort(array, begin, mid);
    mergeSort(array, mid + 1, end);
    merge(array, begin, mid, end);
}
 
// UTILITY FUNCTIONS
// Function to print an array
void printArray(int A[], int size)
{
    for (int i = 0; i < size; i++)
        cout << A[i] << " ";
    cout << endl;
}

上一篇
Day 21 來!威利在哪裡? 其二
下一篇
Day 23 n 等分的新娘 其二
系列文
CS補完計畫—演算法與資料結構的第三次衝擊30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言