zoukankan      html  css  js  c++  java
  • 堆排序

     堆排序

    static void Main(string[] args)
    {
        //产生随机序列
        var rand = new Random();
        List<int> sequence = new List<int>();
        int length = 50; int count = 0;
    
        //以堆的形状输出数值
        int level = (int)(Math.Log(length) / Math.Log(2)) + 1;
        for (int i = 0; i < level; i++)
        {
            string pre = new string(' ', (int)Math.Pow(2, level - i - 1) - 1);
            string inter = new string(' ', (int)Math.Pow(2, level - i) - 1);
            Console.Write(pre);
            for (int k = 0; k < Math.Pow(2, i) && count < length; k++, count++)
            {
                sequence.Add(rand.Next() % 10);
                Console.Write("{0}" + inter, sequence[count]);
            }
            Console.WriteLine();
        }
        //使用堆排序
        HeapSort(sequence);
    
        //以堆的形状输出数值
        Console.WriteLine();
        length = sequence.Count;
        count = 0;
        for (int i = 0; i < level; i++)
        {
            string pre = new string(' ', (int)Math.Pow(2, level - i - 1) - 1);
            string inter = new string(' ', (int)Math.Pow(2, level - i) - 1);
            Console.Write(pre);
            for (int k = 0; k < Math.Pow(2, i) && count < length; k++, count++)
            {
                Console.Write("{0}" + inter, sequence[count]);
            }
            Console.WriteLine();
        }
        Console.Read();
    }
    //堆排序,时间复杂度O(nlg(n))
    static void HeapSort(List<int> sq)
    {
        //创建最大堆(节点上的值大于叶子节点的值)
        //时间复杂度O(n)
        BuildMaxHeap(sq);
        //最大堆的根节点为最大值,将最大值放在数组最后,同时将未维护的堆大小-1
        //然后重新维护最大堆
        for (int i = sq.Count - 1; i > 0; i--)
        {
            var temp = sq[i];
            sq[i] = sq[0];
            sq[0] = temp;
            heapSize--;
            MaxHeapify(sq, 0);
        }
    }
    //当前堆需要维护的大小
    static int heapSize = 0;
    //构建最大堆
    static void BuildMaxHeap(List<int> sq)
    {
        heapSize = sq.Count;
        //对每一个非叶子节点进行维护,从最后一个非叶子节点开始
        for (int i = heapSize / 2; i >= 0; i--)
        {
            MaxHeapify(sq, i);
        }
    }
    //在假定叶子节点为最大堆的情况下,维护最大堆,时间复杂度O(lg(n))
    static void MaxHeapify(List<int> sq, int i)
    {
        int l = (i + 1) << 1 - 1;
        int r = (i + 1) << 1;
        int large = 0;
        if (l < heapSize && sq[l] > sq[i])
            large = l;
        else
            large = i;
        if (r < heapSize && sq[r] > sq[large])
            large = r;
        if (large != i)
        {
            var temp = sq[i];
            sq[i] = sq[large];
            sq[large] = temp;
    MaxHeapify(sq, large); } }

     优先队列与堆排序

    优先队列用于维护一维元素构成的结合。其中,最大优先队列支持一下操作:

    1. Insert(S, x),将元素x插入S集合中
    2. Maximum(S),返回S集合中最大关键字
    3. ExtractMax(S),去掉S集合中最大关键字的项
    4. IncreaseKey(S, x, k),将x的值增加为到k,一般假设k>x

    明显使用堆可以维护一个优先队列。在一个维护好的最大堆中(非排序后,而是在BuildMaxHeap后),各种操作可以有如下实现。

    操作1:在最后插入一个极小值,然后使用操作4,则驾到x

    //sq为最大堆
    static void MaxHeapInsert(List<int> sq, int key)
    {
        heapSize++;
        sq.Add(int.MinValue);
        HeapIncreaseKey(sq, heapSize - 1, key);
    }

    操作2:直接返回S[0];

    //sq为最大堆
    static int HeapMaximum(List<int> sq)
    {
        return sq[0];
    }

    操作3:使用堆排序中的HeadSort变体,将第一个最大值取出

    //sq为最大堆
    static int HeapExtractMax(List<int> sq)
    {
        if (heapSize < 1)
            throw new Exception("heap underflow");
        int max = sq[0];
        sq[0] = sq[heapSize];
        heapSize--;
        //移除最后一个元素
        sq.RemoveAt(heapSize);
        //重新维护最大堆
        MaxHeapify(sq, 0);
        return max;
    }

    操作4:替换后,与父节点递归比较

    //sq为最大堆
    static void HeapIncreaseKey(List<int> sq, int i, int key)
    {
        if (key < sq[i])
            throw new Exception("new key must greater than current");
        sq[i] = key;
        // 父节点为(i+1)>>1-1
        //逐一与父节点比较
        while (i > 1 && sq[(i + 1) >> 1 - 1] < sq[i])
        {
            var temp = sq[i];
            sq[i] = sq[(i + 1) >> 1 - 1];
            sq[(i + 1) >> 1 - 1] = temp;
        }
    }

     

  • 相关阅读:
    leetcode@ [68] Text Justification (String Manipulation)
    leetcode@ [205] Isomorphic Strings
    leetcode@ [274/275] H-Index & H-Index II (Binary Search & Array)
    leetcode@ [174] Dungeon Game (Dynamic Programming)
    Java 开发@ JDBC链接SQLServer2012
    leetcode@ [97] Interleaving Strings
    leetcode@ [131/132] Palindrome Partitioning & Palindrome Partitioning II
    leetcode@ [263/264] Ugly Numbers & Ugly Number II
    py-day1-1 python的基本运算符和语句
    py-day1 pycharm 的安装 以及部分设置
  • 原文地址:https://www.cnblogs.com/qiusuo/p/5211101.html
Copyright © 2011-2022 走看看