这属于https://stackoverflow.com/help/on-topic的"软件算法"
这是来自以下采访问题:http://www.glassdoor.com/Interview/Yelp-Software-Engineering-Intern-Interview-Questions-EI_IE43314.0,4_KO5,32_IP2.htm,
特别是"通过数组或链表实现的二叉树性能"
您将如何通过数组或链表实现二叉树?
教我做这件事的方法是通过具有两个左右两个指针的链接节点类型的结构,即(来自https://courses.cs.washington.edu/courses/cse143/12wi/lectures/ 02-22 / programs / IntTreeNode.java)
public class IntTreeNode {
public int data;
public IntTreeNode left;
public IntTreeNode right;
public IntTreeNode(int data) {
this(data, null, null);
}
public IntTreeNode(int data, IntTreeNode left, IntTreeNode right) {
this.data = data;
this.left = left;
this.right = right;
}
}
然后在实际的二叉树中
public class IntTree {
IntTreeNode overallRoot;
public IntTree() {
overallRoot = null;
}
....
}
如果仅使用数组或链接列表(一个指针),您将如何处理?
但是无论如何,这应该是一个快速的问题。即使您没有实现您不应该执行的树,您将如何分析树的性能?性能不取决于树的状态,就像它是BST吗?就像BST一样,find会是O(log n),因为您每次都要砍掉一半的树。
您如何立即基于这两个实现来分析性能?
在分析这样的算法时,您要查看它是什么类型的二叉树(平衡与不平衡),以及关于空间/时间复杂度的三个因素:
插入
删除中
搜索
比较二叉树的链表和数组实现,我们看到以下内容:
链表的插入和删除比在数组中完成时要便宜得多(想想要完成这两个操作必须对数组元素进行移位。
链表提供灵活的大小,而数组则没有。当数据不适合初始数组大小时,您将不得不处理数组扩展。
数组提供随机访问,而链接列表不提供;例如在处理完整或完整的二叉树的数组实现时,我们可以轻松地计算树中任何节点的索引。
话虽如此,对于二进制搜索树的特定实现,链表是更好的实现,仅因为在二进制搜索树中,访问遵循二进制搜索树的规则(根的值大于左子项,小于右子项)。因此,对于插入/删除和搜索,如果树是平衡的,则平均复杂度应为O(log n)。如果二进制搜索树不平衡,则所有操作的复杂度都变为O(n)-这是最坏的情况。
对于二叉搜索树,使用jadhachem提出的数组实现,搜索是否也具有O(log n)的平均复杂度?如果查看他的示例,它将带您到左节点或右节点,这意味着每次都消除一半的树
是的,绝对可以,搜索平均产生O(log n)。但是我也在考虑插入和删除-在数组实现中,这些操作很昂贵,因为您将不得不扩展或移动数据。
我不确定我是否理解正确,但这就是我的想法。
基本上,您可以将树中的节点存储为数组/列表的元素。
对于数组,请考虑以下内容:
public class Node {
public int data;
public int left;
public int right;
...
}
您的树将是Node s(Node[] tree)的数组,因此根将是第一个元素tree[0]。
每个元素都将其左右子元素引用为数组中的索引。
例如,tree[ tree[0].left ]将是根的左子级。
left值-1可能表明该节点没有左子节点;对于right同样。
例如,考虑以下树:
5
/ \
2 8
\ / \
3 6 9
假设您最初在数组中分配了10个元素。
由于树中的节点少于10个,因此其中一些节点为null。
看起来像这样:
(我将每个Node表示为(data,left,right)元组)
{ (5,1,2) , (2,-1,4) , (8,5,3) , (9,-1,-1) , (3,-1,-1) , (6,-1,-1) , null , null , null , null }
因此,对于节点(8,5,3),您可以知道其左子节点是第六个元素(节点(6,-1,-1)),而其右子节点是第四个元素(节点(9,-1,-1))。
插入/删除功能的性能可能会因您的精确实现而异。
类似的想法也适用于链表(但请记住,它们没有随机访问权限:找到第i个元素需要逐元素遍历该列表)。
希望这可以帮助。
元组的意思是python吗?不错的实现。我喜欢这个主意。那么,是否可以立即回答,因为链表没有随机访问权限,因此基于数组的实现的性能更快?
对困惑感到抱歉。我的意思是数学上的:我只是说Im将节点表示为三个整数。
是的,我认为在这种情况下,数组实现会更好。例如,插入可以对数完成。需要注意的是,一旦阵列中的空间用完了,就必须创建一个更大的新数组,并将所有元素复制到其中。
如果您使用的是链表,我假设该链表是包含左右指针的节点的列表,那么插入也不会是对数吗?我的意思是,您将尝试插入的数据与节点数据进行比较,如果较小则向左移动,如果较大则向右移动。这样,您每次也消除一半的树。
的确,如果您包括指向左右两个孩子的指针,那么您的运行时间会更好,但是它将不会是一个链表:)您将回到树的"常规"实现。
那么,如何使用链接列表来实现它?用一个指针作为实例变量?会不会是一样的事情,但是如果说的像2一样,您实际上必须物理遍历两个节点吗?
让我们继续聊天中的讨论。