排序算法

题目要求:初始无序数组{3, 8, 20, -5, 2, -9, 7, 1, -12, 18},按从小到大排序

一、堆排序

基本概念:

大根堆:一个二叉树,它的每个结点的值都大于或等于其左右孩子结点的值。

小根堆:一个二叉树,它的每个结点的值都小于或等于其左右孩子结点的值。

算法简介:

    首先将待排序序列构造成一个大根堆,此时,整个序列的最大值就是堆顶的根节点。将其与数组末尾元素进行交换,此时末尾就为最大值。然后将剩余n-1个元素重新构造成一个堆,这样会得到n个元素的次小值。如此反复执行,便能得到一个有序序列了。

代码实现:

// 调整堆,其子树必须已经是大根堆

// 参数 array[]:待排序数组,len:数组长度,pidx:待调整堆的根节点索引(数组中的索引)

// return -1:参数错误,0:调整成功

int adjust_heap(int array[], int len, int pidx)
{
    if(NULL == array || len < 1 || pidx < 0 || pidx >= len)
    {
        printf("params error!\n");
        return -1;
    }

    int tmp = 0;
    int max_idx = pidx;
    int lidx = 2*pidx + 1;//左孩子索引值
    int ridx = 2*pidx + 2;//右孩子索引值

    while(lidx < len)
    {
        if(array[lidx] > array[max_idx])
        {
            max_idx = lidx;
        }
        if(array[ridx] > array[max_idx] && ridx < len) // 取二叉树中最大值索引
        {
            max_idx = ridx;
        }

        if(max_idx != pidx) //最大值放到根节点
        {
            tmp = array[max_idx];
            array[max_idx] = array[pidx];
            array[pidx] = tmp;

            pidx = max_idx; //递归调整其子树,只需调整最大值对应的子树
            lidx = 2*pidx + 1;
            ridx = 2*pidx + 2;
        }
        else
        {
            break;
        }
    }
    return 0;
}

// 创建大根堆 O(logn)

// 参数 array[]:待排序数组,len:数组长度

// return -1:参数错误,0:创建成功

int create_heap(int array[], int len)
{
    if(NULL == array || len < 1)
    {
        printf("params error!\n");
        return -1;
    }

    int i = len/2 - 1;//最后一个非叶子节点的索引值
    for(; i >= 0; i--) //从最后一棵非叶子子树进行调整,向前逐一进行
    {
        adjust_heap(array, len, i);
    }
    return 0;
}


// 堆排序 O(nlogn)

// 参数 array[]:待排序数组,len:数组长度

// return -1:参数错误,0:排序成功

int heap_sort(int array[], int len)
{
    if(NULL == array || len < 1)
    {
        printf("params error!\n");
        return -1;
    }

    int result = create_heap(array, len);//首先创建大根堆
    if(result != 0)
    {
        return -1;
    }
    int i = len - 1;
    int tmp = 0;
    for(; i > 0; i--)
    {
        tmp = array[0]; // 最大值放到数组末尾
        array[0] = array[i];
        array[i] = tmp;


        adjust_heap(array, i, 0); //前len-1个数调整为大根堆,取次大值
    }

    for(i = 0; i < len; i++)
    {
        printf("%d ", array[i]);
    }
    printf("\n");
    return 0;
}

int main(int argc, char *argv[])
{
    int origin[] = {3, 8, 20, -5, 2, -9, 7, 1, -12, 18};
    int result = heap_sort(origin, 10);
    if(result != 0)
    {
        return -1;
    }
    return 0;
}

二、快速排序

算法简介:

(1)在数据集之中,选择一个元素作为"枢轴"(pivot)。

(2)所有小于"枢轴"的元素,都移到"枢轴"的左边;所有大于"枢轴"的元素,都移到"枢轴"的右边。

(3)对"枢轴"左边和右边的两个子集,不断重复第一步和第二步,直到所有子集只剩下一个元素为止。

代码实现:

int quick_sort(int array[], int left, int right)
{
    if(NULL == array || left < 0 || right < left)
    {
        printf("params error!\n");
        return -1;
    }

    int l = left, r = right;
    int pivot = array[l]; //选取数组中最左侧的数作为枢轴

    while(l < r)
    {
        while((l < r) && array[r] > pivot) //右侧比“枢轴”值大的数原地不动
        {
            r--;
        }
        if(l < r) //比“枢轴”值赋值到原“枢轴”所在位置
        {
            array[l++] = array[r];
        }

        while((l < r) && array[l] < pivot) //左侧比“枢轴”值小的数原地不动
        {
            l++;
        }
        if(l < r) // 比“枢轴”值大的数放到刚才右侧比“枢轴”大的数位置
        {
            array[r--] = array[l];
        }
    } // 第一遍循环结束,此时 l == r ,左侧全是比“枢轴”值小的数,右侧全是大的数

    array[l] = pivot;//“枢轴”放到索引 l 的位置
    //但此时并不能保证左右两侧的数已排好序
    if(l > left)// 如果“枢轴”左侧有多于一个数,则对左侧子数组递归上面的过程
    {
        quick_sort_core(array, left, l-1);
    }
    if(r < right) // 如果“枢轴”右侧有多于一个数,则对右侧子数组递归上面的过程
    {
        quick_sort_core(array, r+1, right);
    }

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值