堆--神奇的优先队列

---------当然这里讲的是完全二叉树的一个排序

  直接上代码

  int[] _test = { 99, 5, 36, 2, 19, 1, 46, 12, 7, 22, 25, 28, 17, 92 };//这个就是我们的完全二叉树
            n = _test.Length - 1;
            for (int i = n / 2; i >-1; i--)//在这里除以2是因为,所有的子叶节点都不用计算!!!
            {
                siftdown(i);//每次将i传递进来进行排序
            }
        public void siftdown(int i)
        {
            int flag = 0, t;
            while (i * 2 <=n  && flag == 0)
            {
                //首先判断左儿子
                if (_test[i] > _test[i * 2])
                {
                    t = i * 2;
                }
                else
                {
                    t = i;
                }
                //判断右儿子
                if (i * 2 + 1 <= n)
                {
                    if (_test[i * 2 + 1] < _test[t])//如果右儿子小的话
                    {
                        t = i * 2 + 1;
                    }
                }
                //交换这两个数
                if (t != i)
                {
                    _test[t] ^= _test[i];
                    _test[i] ^= _test[t];
                    _test[t] ^= _test[i];
                    i = t;//继续向下
                }
                else
                {
                    flag = 1;
                }
            }
        }

进行排序

        int deletemax()
        {
            int t;
            t = _test[0];
            _test[0] = _test[n];
            n--;
            siftdown(0);
            return t;
        }

当然进行排序的方法不止这一个,

        public void heapSort()
        {
            while (n>0)
            {
                _test[0] ^= _test[n];
                _test[n] ^= _test[0];
                _test[0] ^= _test[n];
                n--;
                siftdown1(0);
            }
        }

上面代码的意思也就是说,每次让第一个数和最后一个数交换位置,因为在这里我们的排序规则和上面的不一样了!!!

所以呢,每次取一个小的数,在堆里面就行排序,排完了顺序也就出来了

        public void siftdown1(int i)
        {
            int flag = 0, t;
            while (i * 2 <= n && flag == 0)
            {
                //首先判断左儿子
                if (_test[i] < _test[i * 2])
                {
                    t = i * 2;
                }
                else
                {
                    t = i;
                }
                //判断右儿子
                if (i * 2 + 1 <= n)
                {
                    if (_test[i * 2 + 1] > _test[t])//如果右儿子小的话
                    {
                        t = i * 2 + 1;
                    }
                }
                //交换这两个数
                if (t != i)
                {
                    _test[t] ^= _test[i];
                    _test[i] ^= _test[t];
                    _test[t] ^= _test[i];
                    i = t;//继续向下
                }
                else
                {
                    flag = 1;
                }
            }
        }

可以看到,我们只是简单的将判断的符号改了

        public void Create()
        {
            n = _test.Length - 1;
            for (int i = n / 2; i >-1; i--)//在这里除以2是因为,所有的子页节点都不用计算!!!
            {
                siftdown1(i);//每次将i传递进来进行排序
            }
            for (int i = 0; i < _test.Length; i++)
            {
                Console.WriteLine(_test[i]);
            }

          Console.WriteLine("---------->");

            heapSort();
            for (int i = 0; i < _test.Length; i++)
            {
                Console.WriteLine(_test[i]);
            }
        }

 

 

从图上我们可以知道我们是从大到小排序的

posted @ 2017-03-28 15:29  夏风微凉  阅读(146)  评论(0编辑  收藏  举报