排序(2)

四. 二路归并排序(非递归形式):

时间复杂度: O(n*log(n))

空间复杂度: O(n)

稳定性: 稳定

static void Merge(int ar[], int len, int gap)  // gap 几几合并
{
    int* br = (int*)malloc(sizeof(int) * len);
    assert(br != NULL);
    int low1 = 0;
    int high1 = low1 + gap - 1;
    int low2 = high1 + 1;
    int high2 = (low2 + gap - 1) < len ? (low2 + gap - 1) : len-1;
    int index = 0;
    while (low2 < len)//两个有序段
    {
        while (low1 <= high1 && low2 <= high2)//两个都没走到尾
        {
            if (ar[low1] <= ar[low2])
            { 
                br[index++] = ar[low1++];
            }
            else
            {
                br[index++] = ar[low2++];
            }
        }
        while (low2 <= high2) //有一个走到尾,则将另一个剩余的数据拷贝到br中
        {
            br[index++] = ar[low2++];
        }
        while (low1 <= high1)
        {
            br[index++] = ar[low1++];
        }
        low1 = high2 + 1;//更改low1 ,low2指向下一对有序段
        high1 = low1 + gap - 1;
        low2 = high1 + 1;
        high2 = (low2 + gap - 1) < len ? (low2 + gap - 1) : len - 1;
    }
    while (low1 < len)//只有一个有序段
    {
        br[index++] = ar[low1++];
    }
    //拷贝到ar中
    for (int i = 0; i < len; i++)
    {
        ar[i] = br[i];
    }
    free(br);
    br = NULL;
    return;
}

void MergeSort(int ar[], int len)
{
    assert(ar != NULL && len > 1);
    for (int i = 1; i < len; i *= 2)
    {
        Merge(ar, len, i);
    }
}

五.(简单)选择排序 :

规则:每次从待排序的队列中找到最小的元素,与待排序的第一个元素交换

效率: 时间复杂度O(n^2)

空间复杂度O(1)

稳定性: 不稳定

void SelectSort(int ar[], int len)
{
    assert(ar != NULL && len > 1);
    for (int i = 0; i < len - 1; i++)
    {
        //int min = ar[i];
        int index = i;
        int j = i + 1;
        for (; j < len; j++)
        {
            if (ar[j] < ar[index])
            {
                //min = ar[j];
                index = j;
            }
        }
        if (index != i)
        {
            int tmp = ar[index];
            ar[index] = ar[i];
            ar[i] = tmp;
        }
    }
}

六 堆排序:

效率: 时间复杂度 O(n*log(2,n))

空间复杂度: O(1)

稳定性: 不稳定

//简单介绍下堆:
//什么是堆: 堆分为两种   大顶堆(一个二叉树,父节点的值大于子节点的值)  小顶堆
// 什么是树形结构
//二叉树  树根  深度(log 2(节点个数)+1)  叶子节点(没有子结点的结点)  左孩子  右孩子  完全二叉树()   满二叉树()  
//
// 大顶堆和小顶堆的关系和兄弟节点的值无关,只和父子节点的值有关
// 
// 调整2个要点 1.从最后一个非叶子结点开始从后向前调整
//             2.调整时从上向下
//             3.升序(大顶堆),降序(小顶堆)
//

//父子结点关系:
//父 x     找   子 y1,y2 :  左y1 = 2*x + 1, 右y2 = 2*x + 2;
//子 y1,y2 找   父 x     :  x = (y1/y2 - 1)/2;

void HeapAdjust(int ar[], int start, int end)//传入开始的结点和结束的结点下标
{
    int tmp = ar[start];
    for (int i = start * 2 + 1; i <= end; i = 2*i+1)
    {
        if (i < end && ar[i] < ar[i+1])//两个孩子都有且左孩子大于右孩子
        {
            i++;//让i指向较大的孩子
        }
        //只有一个孩子不进行比较
        if (ar[i] > tmp)
        {
            ar[start] = ar[i];
            start = i;
        }
        else
        {
            break;
        }
    }
    ar[start] = tmp;//1.触底2.找到合适位置
}

void HeapSort(int ar[], int len)
{
    assert(ar != NULL && len > 1);

    //1.调整成大顶堆
    for (int i = (len-1)/2; i >= 0; i--)
    {
        HeapAdjust(ar, i, len - 1);
    }

    int tmp = 0;
    for (int j = 0; j < len - 1; j++)//4. 循环1,2,3操作
    {
        //2.将根结点(最大值)和最后一个结点交换,并继续调整
        tmp = ar[0];
        ar[0] = ar[len - 1 - j];
        ar[len - 1 - j] = tmp;
        //3.将剩下的继续进行调整
        HeapAdjust(ar, 0, len - 1 - j - 1);
    }

}

未完待续...

posted @ 2021-04-15 12:02  Wz_qq_2***6  阅读(37)  评论(0)    收藏  举报