9-堆排序&二路归并排序

堆排序&二路归并排序

堆排序

建堆:
1.从最后一颗子树开始向上处理
2.每次处理过程都是从要处理的子树的根节点开始向下比较

堆排序
先把队列做成大堆,即父节点大于所有子节点
在这里插入图片描述再将做好的大堆排序。一次一次将最大的节点(根节点)往后方,然后再做大堆。
在这里插入图片描述

//大堆void FilterDown(int *ar, int start, int end){       int i = start, j = i * 2 + 1;       int item = ar[i];       while (j <= end)       {              if (j + 1 <= end && ar[j] < ar[j + 1])              {                     ++j;              }              if (item > ar[j])   //调整节点位置              {                     break;              }              else              {                     ar[i] = ar[j];              }              i = j;              j = 2 * i + 1;       }       ar[i] = item;}void HeapSort(int *br, int num){       if (num < 2) return;       //////做成大堆       int pos = (num - 2) / 2;       while (pos >= 0)       {              FilterDown(br, pos, num - 1);              --pos;       }       PrintArray(br, num);       //////排序       for (int i = num - 1; i > 0; i--)       {              Swap(br[i], br[0]);              FilterDown(br, 0, i - 1);              PrintArray(br, num);       }}



// 一次调整过程  O(logn)
void AdjustTree(int *arr, int root, int len)
{
    int tmp = arr[root];
    int i = root;
    int j = 2 * i + 1;


    while (j < len)
    {
        if (j + 1 < len && arr[j] < arr[j + 1])
        {
            j += 1;
        }
        
        if (arr[j] <= tmp)
        {
            break;
        }


        arr[i] = arr[j];
        i = j;
        j = 2 * i + 1;
    }


    arr[i] = tmp;
}


//建立一颗最大堆  O(nlogn)
void CreateHeap(int *arr, int len)
{
    int i = (len - 2) / 2;
    for (; i >= 0; i--)
    {
        AdjustTree(arr, i, len);
    }
}


//堆排序  O(nlogn)    O(1)    不稳定
//  无论待排序数据如何,时间复杂度不变
void HeapSort(int *arr, int len)
{
    CreateHeap(arr, len);


    for (int i = 1; i < len; i++)
    {
        Swap(&arr[0], &arr[len - i]);  
        AdjustTree(arr, 0, len - i);
    }
}

二路归并排序:

合并两个有序的数据序列


//O(n)
void Meger(int *arr, int  len, int width, int *brr)
{
    int low1 = 0;
    int high1 = low1 + width - 1;
    int low2 = high1 + 1;
    int high2 = low2 + width - 1 < len - 1 ? low2 + width - 1 : len - 1;


    int tag = 0;


    //  将有两个归并段的段归并到brr中
    while (low1 < len && low2 < len)
    {
        while (low1 <= high1  && low2 <= high2)
        {
            if (arr[low1] < arr[low2])
            {
                brr[tag++] = arr[low1++];
            }
            else
            {
                brr[tag++] = arr[low2++];
            }
        }


        while (low1 <= high1)
        {
            brr[tag++] = arr[low1++];
        }
        while (low2 <= high2)
        {
            brr[tag++] = arr[low2++];
        }


        low1 = high2 + 1;
        high1 = low1 + width - 1 < len - 1 ? low1 + width - 1 : len - 1;
        low2 = high1 + 1;
        high2 = low2 + width - 1 < len - 1 ? low2 + width - 1 : len - 1;
    }


    //  将最后剩余的一个归并段合并到brr中
    while (low1 < len)
    {
        brr[tag++] = arr[low1++];
    }


    //  将brr中的所有数据复制到arr中
    tag = 0;
    while (tag < len)
    {
        arr[tag] = brr[tag];
        tag++;
    }
}


//二路归并排序
// O(nlogn)     O(n)    稳定
void MegerSort(int *arr, int len)
{
    int *brr = (int *)malloc(sizeof(int)* len);
    assert(brr != NULL);


    for (int i = 1; i < len; i *= 2)
    {
        Meger(arr, len, i, brr);
    }


    free(brr);
}
发布了82 篇原创文章 · 获赞 7 · 访问量 4193

猜你喜欢

转载自blog.csdn.net/sunshine612/article/details/104701583