这些天我一直在努力实现我的教授要求我们做的一项功能,作为一项挑战,但我无法想到任何可行的方法,所以我在这里看看是否任何人都可以对此有所了解。
这只是关于算法,但我实际上是在C ++中编程,使用根据基本规范编程的BSTree(插入,删除,成员操作)。
问题如下:
假设树的每个节点都包含绝对数字的数字,并且我们有两个不同的BST:一个用于存储负数,另一个用于存储正数。我们可以称他们为negBST和posBST。例如,如果我们输入数字-2 2 5 8 -4 -5 -3 -6
,这些将是我们的两棵树:
2 2
\ \
4 5
/ \ \
3 5 8
\
6
Negative BST Positive BST
目标是打印它们都是有序的,因此,在这种情况下,它会打印:
2 -2 -3 -4 5 -5 -6 8
现在,面临挑战:实际上是否可以在不使用任何其他辅助动态数据结构(如队列,堆栈,列表等)的情况下执行此操作...?
编辑: 提供的示例可能有点令人困惑,因为树的深度可能会有所不同。
答案 0 :(得分:3)
一个简单但效率低下的解决方案是将变量n
从零迭代到MAX_NUMBER
并检查每个迭代和树,如果数字n
保存在树中。如果是,请打印(当然否定负面树)。
您还可以并行执行两次深度优先搜索。在每次迭代中,您比较下一个搜索步骤将产生较低数字的树。打印相应树中的数字并进行相应的搜索。
更详细一点:您初始化两个DFS。这为每个树中的一条路径分别指向第一个元素。现在比较元素,选择具有较低元素的树。打印元素(如果需要,使用减号)并在您选择的树中推进DFS。这将为您提供此树中的下一个元素。再次,您比较两个树中的下一个元素,选择较小的元素,等等。
这里有一些类似Javascript / C的伪代码:
// let's assume a DFS and its status is represented by an object
// dfs.next() returns the next number and advances the search
// dfs.peekNext() only returns the next number
var dfsPos = initDFS(posBST);
var dfsNeg = initDFS(negBST);
while (!dfsPos.hasFinished() || !dfsNeg.hasFinished()) {
if (dfsPos.hasFinished())
print('-' +dfsNeg.next());
else if (dfsNeg.hasFinisehd())
print(dfsPos.next());
else if (dfsPos.peekNext() < dfsNeg.peekNext())
print(dfsPos.next());
else
print('-' +dfsNeg.next());
}
答案 1 :(得分:1)
我将假设negBST和posBST各自包含唯一键。
您可以创建单个BST,例如 commonBST ,而不是尝试同时处理两个单独的BST:s,它们允许非唯一条目。一般来说,这很棘手并且会破坏基本的BST属性,但在这种特殊情况下,它会起作用,如:
对于我们的数字数组(例如:-2 2 5 8 -4 -5 -3 -6
),要构建单个 BST commonBST,请仅查看每个数字的绝对值;说KEY = abs(number)
,并将号码符号与KEY
的其他属性相关联,比如说KEY.sign
。每个可能的KEY
只能存在以下状态:
KEY
,KEY.keySign=-1
for - )KEY
,KEY.keySign=+1
for +)KEY
,两个标志,KEY.keySign=0
)如果我们已经有两棵树(而不是创建两棵树的初始数组),我们只需将negBST添加到posBST即可实现上述的commonBST。
由于negBST和posBST只包含唯一键,因此commonBST键中唯一的退化可能是特定KEY的+和 - 出现。
使用此模式,我们可以创建commonBST(使用您的数字数组作为示例):
For key C:
C*: C contains both +C and -C (keySign = 0)
C : C contains only one of +C and -C (get sign from keySign)
Example binary tree for numbers [-2, 2, 5, 8, -4, -5, -3, -6]:
2*
\
5*
/ \
4 8
/ /
3 6
以下swift代码构造了这样一个树
// adapted from "regular" BST in Swift from:
// http://waynewbishop.com/swift/binary-search-trees/
//generic binary search tree
public class AVLTree {
var key: Int?
var keySign: Int? // -1 or 1 for unique entries, 0 if both
var left: AVLTree?
var right: AVLTree?
init() { }
//add item based on its value
func addNode(key: Int) {
//check for the head node
if (self.key == nil) {
self.key = abs(key)
self.keySign = abs(key)/key
return
}
// check for duplicate key
if (abs(key) == self.key) {
self.keySign = 0
}
//check the left side of the tree
else if (abs(key) < self.key) {
if (self.left != nil) {
left!.addNode(key)
}
else {
//create a new left node
let leftChild : AVLTree = AVLTree()
leftChild.key = abs(key)
leftChild.keySign = abs(key)/key
self.left = leftChild
}
}
//check the right side of the tree
else if (abs(key) > self.key) {
if (self.right != nil) {
right!.addNode(key)
}
else {
//create a new right node
let rightChild : AVLTree = AVLTree()
rightChild.key = abs(key)
rightChild.keySign = abs(key)/key
self.right = rightChild
}
}
}
}
let numberList : Array<Int> = [-2, 2, 5, 8, -4, -5, -3, -6]
//create a new BST instance
var root = AVLTree()
//sort each item in the list
for number in numberList {
root.addNode(number)
}
这使用纯粹的命令式方法,因此您应该能够将其用作您所选语言的详细伪代码。
commonBST只能扩展为常规BST,但只需在展开每个密钥时检查属性keySign
。
keySign=1
,print(key)
。keySign=-1
,print(-key)
。keySign=0
,print(-key)
&amp; print(key)
(或您选择的订单)。这应该具有任何常规BST的复杂度,O(log n)平均用于插入和查找。