这可能听起来像是一个家庭作业问题,但老实说,事实并非如此。
我有一个键/值对列表,我正在读取二叉树。我实现了一个AVL树,非常简单 - 密钥,值作为有效负载,左子,右子,平衡因子和树本身的父节点。这里没问题。
现在,我想按照不同的标准对树进行重新排序 - 假设一个不同的比较函数,或者我想使用该值(某些部分)来对树进行排序。当然,我可以在几乎任何顺序中遍历我的原始树并将每个节点添加到新的AVL树 - 毕竟,构建的代码就在那里。或者我可以将树转储到数组qsort()
数组中,并使用众多算法中的一种从排序数组中高效生成树。
但是,由于原因太复杂而无法解释,我宁愿不分配第二个结构,相反,我想对树本身进行排序。标准排序算法似乎没有多大意义,因为它们通常依赖于诸如“选择第n个元素”,“前进一个元素”,“备份一个元素”等操作,这些操作在阵列中很便宜,而是在二叉树中代价高昂。
谷歌搜索没有多大帮助 - 有数以万计的网页可以解释二叉树,B树,AVL树,红黑树以及如何使用它们对数据进行排序。我不需要这些页面,我知道基础知识。但是,如果有一篇文章在某处解释了“如何对未排序的树进行排序,从而对结果进行排序和平衡”,那些数以万计的页面可以很好地隐藏它。
因此,如果有任何好的算法重新排序未排序的树,同时保持平衡,我想听听它 - 如果这个算法需要的时间少于“只是构建一个新的”尝试,一切都好。
(不,我没有代码可以展示,因为我正在寻找一个算法; AVL树构建代码我不会对这个问题做出贡献,一旦我找到合适的算法,我就非常肯定我将能够实现它 - 我只需要一个起点。)
答案 0 :(得分:1)
一种方法是将树的节点逐个移动到已排序的新树中。是的,我知道技术上是另一棵树,但是你永远不会增加分配的节点数量,也不会复制任何内存,只需切换指针即可。因此,除了一个额外的根节点,你不是“分配第二个结构”。
我疯狂地猜测你在这里做了什么,但也许你正在改变你的排序键。如果是这样,可以为具有相同节点集的两个(或更多)树提供树指针,因此节点可以同时在2个(或更多)树中,对两个时间进行排序,并进行不同的排序。这可能也很有用。
答案 1 :(得分:0)
时间复杂度不能比O(n*log n)
更好,因为您要构建的二叉搜索树(BST)基于键的比较,而原始树根本不是有序 (以另一个不相关的标准订购)。该方法有三个步骤,并从二叉树(BT)建立一个BST (这就是你想要的)。
O(n)
中完成,并使用AVL树的左/右子指针作为DLL的上一个/下一个指针。O(n*log n)
时间内的DLL排序。请参阅sort an linked list。O(n)
中的二叉搜索树(例如AVL)。请参阅convert sorted list into BST。