数据结构与算法之高级排序(希尔/堆)<十一>

基础排序
数据结构与算法之基础排序(冒泡/插入/选择)<十>

希尔排序

希尔排序又称为缩小增量排序。该算法是一个泛化的插入排序,插入排序在序列几乎有序的情况下非常有效。希尔排序利用此特性,分多路并使用不同的间距进行插入排序,当间距为1是则就是简单的插入排序,本质上希尔排序是插入排序的简单拓展 

优点
    对中等大小的序列非常有效 
    是所有已知O(n^2)排序算法中最快的 
    相对简单的排序算法 
缺点 
    较大序列不是个好的选择
    不及 归并 堆 快速排序有效 
    明显比 归并 堆 快速 排序慢 
算法
    选择合适的间距 将序列分成n路
    每路使用插入排序
    重复上述过程直至间距为1

堆排序

堆排序是一种基于比较的排序算法,该算法同时属于选择排序。虽然在大多数计算机上的运行效率低于快速排序。但是堆排序最大的优势是在最坏情况下O(nlogn) 

关于堆的基础知识参考数据结构与算法之优先队列<九>

以下算法实现仅供参考若有错误欢迎指正

希尔排序

public void sortByShell2(int[] a) {
        int d = SIZE;
        while (true) {
            // 将数组分成d路然后每列进行插入排序
            d = d / 2;
            // 遍历所有路   每路进行插入排序
            for (int j = d; j < arr.length; j++) {
                // 若第i个元素大于i-1元素,该位置元素位置正确。小于的话,后移空出位置
                if (a[j] < a[j - d]) {
                    //下个元素位置
                    int n = j - d;
                    // 复制为哨兵,即存储待排序元素
                    int x = a[j]; 
                    // 先后移 空出位置
                    a[j] = a[j - d]; 
                    // 循环查找插入位置 直至找到或者到头
                    while (n >= d && x < a[n - d]) { 
                        a[n] = a[n - d];
                        //下个元素位置
                        n = n - d; 

                    }
                    // 插入到正确位置
                    a[n] = x; 
                }
            }
            // 步长为1时便是插入排序了 排序也就完成了
            if (d == 1) {
                break;
            }
        }
    }

堆排序

    // 调整堆父节点小
    public void adjustHeap(int[] heap, int node, int length) {
        // 保存被调整的节点
        int temp = heap[node];
        // 利用完全二叉树的特殊性,父节点与子节点的关系child=father*2+1
        int child = node * 2 + 1;
        while (child < length) {
            // 如果存在右孩子且右孩子小于左孩子
            if ((child + 1) < length && heap[child] < heap[child + 1]) {
                // 选择小的孩子
                ++child;
            }
            // 如果父节点大于孩子中最小的
            if (heap[node] < heap[child]) {
                heap[node] = heap[child];
                // 向下继续调整
                node = child;
                child = node * 2 + 1;
            } else {
                break;
            }
            // 调整完毕 找到了正确位置
            heap[node] = temp;
        }

    }

    // 建立堆
    public void buildHeap(int[] arr, int length) {
        // 根据child=node*2+1可以算出数列中最后一个节点
        for (int node = (length - 1) / 2; node >= 0; --node) {
            // 从下自上将所有的节点调整一遍
            adjustHeap(arr, node, length);
        }
    }

    // 将创建好的堆进行堆排序
    public void sortByHeap(int[] array, int length) {
        buildHeap(array, length);
        int temp;
        // 将数组遍历从尾部到顶依次与根节点互换
        for (int i = length - 1; i > 0; --i) {
            temp = array[i];
            array[i] = array[0];
            array[0] = temp;
            // 将根节点替换后从上向下调整
            adjustHeap(array, 0, i);

        }
    }

到此希尔排序和堆排序介绍完毕

下一篇 数据结构与算法之高级排序(快速/归并)<十二>

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值