欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

【精华】排序算法汇总——希尔排序与堆排序

程序员文章站 2024-03-14 14:43:28
...

日常说明:有错误欢迎大家指正,希望对你们有用。
更多算法请关注我的算法专栏https://blog.csdn.net/column/details/20417.html

三、希尔排序(shell sort)
算法思想:希尔排序又称为缩小增量排序,也属于插入类排序方法。具体的操作是:先将整个待排记录序列分割成若干子序列,然后对子序列分别进行插入排序,最后再进行一次直接插入排序。复杂度为O(n^(3/2))。
如:49 38 65 97 76 13 27 47 55 04,假定第一趟增量为5,第二趟增量为3,第三趟增量为1
第一趟排序:13 27 47 55 04 49 38 65 97 76
第二趟:13 04 47 38 27 49 65 97 76
第三趟:04 13 27 38 47 49 65 76 97
核心代码:

shell_insert(List&list,int increm)  //increm为增量,增量放在数组中
{
    for (int i = increm+1; i <=list.length; ++i)
    {
        if (list.elem[i] < list.elem[i - increm])
        {
            list.elem[0] = list.elem[i];//将要插入的值list.elem[i]暂存在第一个位置。
            int j;
            for (j = i - increm; j >0&&(list.elem[0]<list.elem[j]); j-=increm)
            {
                list.elem[j + increm] = list.elem[j];
            }//比较增量后子序列的大小,将大于list.elem[0]的数往后移动,list.elem[0]插入。
            list.elem[j + increm] = list.elem[0];
        }   
    }
}

shell_sort(List&list)
{
    int arr[3] = { 5,3,1 };//增量数组
    for (int i = 0; i < 3; i++)
    {
        list.shell_insert(list, arr[i]);
    }
};

堆排序
算法思想:堆排序可以建大顶堆或者小顶堆,就是最大的数在顶端或者最小的数在顶端。我们把数据序列逻辑化为完全二叉树,对一棵子树比较根节点和左右孩子的大小,将最大的数放在根节点。依次对每棵子树都进行此操作,这是建堆后不断调整为大顶堆的过程。建好堆后需要进一步调整即排序,使得根节点>左孩子>右孩子。简单说,通过筛选将完全二叉树中最大的数放在根节点,变成大顶堆。然后将根节点的数和最后一个数交换位置,除了最后一个数其他的数再调整为大顶堆,再交换到最后,几趟下来就排好序了。复杂度为O(nlogn)
核心代码:

HeapAdjust(int arr[], int root, int length)
{
    int lchild = root * 2 + 1;
    if (lchild!=NULL&&lchild < length)  
    {
        int temp = lchild;
        int rchild = lchild + 1;  
        if (rchild < length) 
        {
            if (arr[rchild] > arr[temp])//找出左右子结点中的最大值  
            {
                temp = rchild;
            }
        }
        if (arr[root] < arr[temp])
        {
            Swap(arr[root], arr[temp]);
            HeapAdjust(arr, temp, length);//从此次最大子节点的那个位置开始递归建堆  
        }
    }
}

Heap_sort(int arr[], int len)
{
    for (int i = len / 2; i >= 0; --i)//从最后一个非叶子节点的父结点开始建堆  
    {
        HeapAdjust(arr, i, len);
    }

    for (int j = len - 1; j > 0; --j) 
    {
        Swap(arr[0], arr[j]);//交换首尾元素,将最大值交换到数组的最后位置保存  
        HeapAdjust(arr, 0, j);//去除最后位置的元素重新建堆,此处j表示数组的长度,最后一个位置下标变为len-2  
    }

}