美文网首页
堆排序的不简洁代码

堆排序的不简洁代码

作者: Collie | 来源:发表于2019-10-04 14:41 被阅读0次
#include <iostream>
#include <vector>

namespace algorithm
{
    namespace sort
    {
        namespace heap_sort
        {
            //用于执行堆排序的类
            //由于使用顺序存储结构来表示一棵树
            //所以使用裸指针而不是STL中的元素
            template<typename E>
            class Tree
            {
            private:
                const size_t size__;
                E *const elements;
            public:
                Tree(const size_t &size, E *elements) :
                    size__(size),elements(
                        reinterpret_cast<E *>(
                            malloc((size + 1)*sizeof(E))
                            )
                    )
                {
                    if (elements == NULL) memset(this->elements, 0, sizeof(int));
                    else memcpy((this->elements + 1), elements, size * sizeof(E));
                }

                E *getElements() const
                {
                    return this->elements;
                }

                const size_t size() const
                {
                    return this->size__;
                }

                //从完全二叉树中序号为root的结点开始在序号为[1,range]范围内进行筛选
                inline void adjust(const size_t &root, const size_t &range) const
                {
                    //这个筛选过程怎么那么费脑筋呢
                    bool hasLeftChild = 2 * root < range;
                    bool hasRightChild = (2 * root + 1) < range;

                    if (hasLeftChild&&hasRightChild)
                    {
                        //妈的,这样写逻辑真是太他妈的蛋疼
                        if (this->getElements()[root] <= this->getElements()[2 * root] &&
                            this->getElements()[root] <= this->getElements()[2 * root + 1])
                        {
                            //不需要调整,返回
                            return;
                        }
                        else
                        {
                            //从两个叶子结点中找一个最小的替换到头
                            if (this->getElements()[2 * root] < this->getElements()[2 * root + 1])
                            {
                                E temp = this->getElements()[root];
                                this->getElements()[root] = this->getElements()[2 * root];
                                this->getElements()[2 * root] = temp;
                                //然后要对以这个为根的进行筛选
                                adjust(2 * root, range);
                            }
                            else
                            {
                                E temp = this->getElements()[root];
                                this->getElements()[root] = this->getElements()[2 * root + 1];
                                this->getElements()[2 * root + 1] = temp;
                                //然后要对以这个为根的进行筛选
                                adjust(2 * root + 1, range);
                            }
                        }
                    }

                    if ((!hasLeftChild) && (!hasRightChild))
                    {
                        //叶子节点,一样不需要调整
                    }

                    if (hasLeftChild == true && hasRightChild == false)
                    {
                        if (this->getElements()[root] < this->getElements()[2 * root])
                        {
                            return;
                        }
                        else
                        {
                            //交换,然后筛选左子树
                            E temp = this->getElements()[root];
                            this->getElements()[root] = this->getElements()[2 * root];
                            this->getElements()[2 * root] = temp;
                            //然后要对以这个为根的进行筛选
                            adjust(2 * root, range);
                        }
                    }

                    //其实不会有只有右子树没有左子树的情况的,但是还是要写上
                    if (hasLeftChild == false && hasRightChild == true)
                    {
                        if (this->getElements()[root] < this->getElements()[2 * root + 1])
                        {
                            return;
                        }
                        else
                        {
                            //交换,然后筛选左子树
                            E temp = this->getElements()[root];
                            this->getElements()[root] = this->getElements()[2 * root + 1];
                            this->getElements()[2 * root + 1] = temp;
                            //然后要对以这个为根的进行筛选
                            adjust(2 * root + 1, range);
                        }
                    }
                }

                //这个重载的无参构造函数用于在建堆时进行全局筛选
                inline void adjust() const
                {
                    //进行首次筛选
                    for (size_t i = this->size() / 2; i > 0; --i)
                    {
                        this->adjust(i, this->size());
                    }
                }

                //应该考虑如何进行筛选
                inline void sort() const
                {
                    //用于排序并存储在原来的位置
                    adjust();
                    for (size_t remaining = size(); remaining > 1; remaining--)
                    {
                        adjust(1, remaining);
                        //替换到最后一个
                        E temp = this->elements[1];
                        this->elements[1] = this->elements[remaining];
                        this->elements[remaining] = temp;
                    }
                }
            };

            
        }
    }
}

int main(int argc, char ** argv)
{
    using algorithm::sort::heap_sort::Tree;
    

    //为了统一下标,应该浪费第一位
    int data[10] = { 2,0,1,5,3,0,1,8,6,6 };
    Tree<int> tree = Tree<int>(10,data);
    for (size_t i = 1; i <= 10; i++)
    {
        std::cout << *(tree.getElements() + i) << " ";
    }
    std::cout << std::endl << std::flush;

    tree.sort();

    for (size_t i = 1; i <= 10; i++)
    {
        std::cout << *(tree.getElements() + i) << " ";
    }
    std::cout << std::endl << std::flush;

    tree.adjust();

    for (size_t i = 1; i <= 10; i++)
    {
        std::cout << *(tree.getElements() + i) << " ";
    }
    std::cout << std::endl << std::flush;

    tree.sort();

    for (size_t i = 1; i <= 10; i++)
    {
        std::cout << *(tree.getElements() + i) << " ";
    }
    std::cout << std::endl << std::flush;
}

相关文章

  • 堆排序的不简洁代码

  • 堆排序---基础篇

    本文主要介绍堆排序的一些基本过程和分析。 大纲 堆排序简介 堆排序代码实现 1. 堆排序简介 1.1 堆排序的存储...

  • 14.排序算法(5)

    1.堆排序介绍 2. 代码实现

  • 堆排序代码

    include //array是待调整的堆数组,i是待调整的数组元素的位置,nlength是数...

  • C#实现堆排序源码

    下面代码段是关于C#实现堆排序的代码。 private static void HeapSortFunct...

  • 堆排序

    概述 堆排序基于完全二叉树进行排序, 稳定性 堆排序不稳定 时间复杂度 堆排序的时间复杂度为 nlogn C代码

  • C#堆排序源码

    如下的代码内容是关于C#堆排序的代码。 private static void Adjust (int[] lis...

  • 简洁代码的思考

    偶然看到一篇博客 Code, Picasso, and Simplicity,说的是他开始为了实现一个特性,写了3...

  • 代码简洁之道

    第一章 有意义的命名(起名是门艺术) 示例代码为伪代码,懂就好 名副其实目的:只需要一个好名称就能知道发什么了什么...

  • 简洁代码-注释

    代码整洁之道笔记 [TOC] 注释 写出好的代码就不要注释啦。 逻辑实在复杂不得不加,那记得把注释将清楚。 别把注...

网友评论

      本文标题:堆排序的不简洁代码

      本文链接:https://www.haomeiwen.com/subject/jecspctx.html