排序算法Part2

46 阅读2分钟

6. 堆排序 Heap Sort

  • 利用完全二叉树的性质,构建大顶堆

  • 把堆顶元素与最后一个元素交换,然后调整堆

  • 不稳定

  • 时间复杂度

    最好最坏平均
    O(nlogn)O(nlogn)O(nlogn)O(nlogn)O(nlogn)O(nlogn)
  • 实现

    void HeapAdjust(int *arr, int s, int e)
    {
        for (int j = 2 * s + 1; j <= e; j = 2 * j + 1)
        {
            int tmp = arr[s];
            if (j < e && arr[j] < arr[j + 1])
            {
                ++j;
            }
            if (tmp > arr[j])
            {
                break;
            }
            Swap(arr[j], arr[s]);
            s = j;
        }
    }
    void HeapSort(int *arr, int n)
    {
        for (int i = n / 2 - 1; i >= 0; i--)
        {
            HeapAdjust(arr, i, n - 1);
        }
    
        for (int i = n - 1; i >= 0; i--)
        {
            Swap(arr[i], arr[0]);
            HeapAdjust(arr, 0, i - 1);
        }
    }
    

7. 归并排序 Merge Sort

  • 源于分治思想,

  • 时间复杂度

    最好最坏平均
    O(nlogn)O(nlogn)O(nlogn)O(nlogn)O(nlogn)O(nlogn)
  • 递归实现

        void Merge(int *arr, int *tmp, int s, int m, int e)
        {
            int i = s, j = m + 1, k = s;
            while (i <= m && j <= e)
            {
                if (arr[i] < arr[j])
                {
                    tmp[k++] = arr[i++];
                }
                else
                {
                    tmp[k++] = arr[j++];
                }
            }
            while (i <= m) tmp[k++] = arr[i++];
            while (j <= e) tmp[k++] = arr[j++];
    
            for (i = s; i <= e; i++)
            {
                arr[i] = tmp[i];
            }
        }
    
        void MergeSort(int *arr, int *tmp, int s, int e)
        {
            if (s < e)
            {
                int m = s + (e - s) / 2;
                MergeSort(arr, tmp, s, m);
                MergeSort(arr, tmp, m + 1, e);
                Merge(arr, tmp, s, m, e);
            }
        }
    
        void MergeSort(int *arr, int n)
        {
            int *tmp = new int[n];
            MergeSort(arr, tmp, 0, n - 1);
            delete[] tmp;    
        }
    
  • 迭代实现

        void MergePart(int *arr, int *tmp, int n, int k)
        {
            for (int s = 0; s < n;)
            {
                int m = s + k - 1;
                if (m >= n) m = n - 1;
    
                int e = s + 2 * k - 1;
                if (e >= n) e = n - 1;
    
                Merge(arr, tmp, s, m, e);
                s = e + 1;
            }
        }
    
        void MergeSort(int *arr, int n)
            int *tmp = new int[n];
            int k = 1;
            while (k < n)
            {
                MergePart(arr, tmp, n, k);
                k <<= 1;
            }
            delete[] tmp;
        }
    

8. 快速排序 Quick Sort

  • 选定一个基准,大于基准的元素统统放右边,小于基准的元素放左边

  • 分别对左右两边递归进行上述操作

  • 不稳定

  • 时间复杂度

    最好最坏平均
    O(nlogn)O(nlogn)O(n2)O(n^2)O(nlogn)O(nlogn)
  • 实现

    int Partion(int *arr, int low, int high)
    {
        int pivot = arr[low];
        while (low < high)
        {
            while (low < high && arr[high] >= pivot)
            {
                high--;
            }
            arr[low] = arr[high];
            while (low < high && arr[low] <= pivot)
            {
                low++;
            }
            arr[high] = arr[low];
        }
        arr[low] = pivot;
        return low;
    }

    void QSort(int *arr, int low, int high)
    {
        if (low < high)
        {
            int pivot = Partion(arr, low, high);
            QSort(arr, low, pivot - 1);
            QSort(arr, pivot + 1, high);
        }
    }

    void QuickSort(int *arr, int n)
    {
        QSort(arr, 0, n - 1);
    }