C 将新分支添加到树中,然后以高效的方式将新叶添加到链接列表中的正确位置

C 将新分支添加到树中,然后以高效的方式将新叶添加到链接列表中的正确位置,c,algorithm,tree,binary-tree,C,Algorithm,Tree,Binary Tree,假设我们有一个二叉树和一个链表,其中包含所有叶子中出现的数据 例如,以下树的列表将是:9,2,3(订单事项,从左到右) 现在我们在某处添加一个新节点,从而创建一个新分支,如下所示: 有没有一种有效的方法将这个新叶添加到列表中,这样列表将保持叶从左到右的顺序?i、 e新列表应为9,1,2,3 在最坏的情况下,我想到的任何东西都与创建一个全新的列表相同,即遍历整个树 就像在LDR中遍历树并查找新叶,同时保留最后一个叶的信息,但在最坏的情况下,它可能遍历树的全部或大部分 顺便说一句,列表和树是任意

假设我们有一个二叉树和一个链表,其中包含所有叶子中出现的数据

例如,以下树的列表将是:
9,2,3
(订单事项,从左到右)

现在我们在某处添加一个新节点,从而创建一个新分支,如下所示:

有没有一种有效的方法将这个新叶添加到列表中,这样列表将保持叶从左到右的顺序?i、 e新列表应为
9,1,2,3

在最坏的情况下,我想到的任何东西都与创建一个全新的列表相同,即遍历整个树

就像在LDR中遍历树并查找新叶,同时保留最后一个叶的信息,但在最坏的情况下,它可能遍历树的全部或大部分

顺便说一句,列表和树是任意定义的,如下所示:

typedef struct listNode  {
    int data;
    struct listNode* next;
} ListNode;

typedef struct  treeNode {
    int data;
    struct treeNode* parent; //prev node
    struct treeNode* left;
    struct treeNode* right;
} TreeNode;

是的,有,但还需要向
treeNode
添加更多数据,即指向列表节点的指针(如果存在)

现在的想法是,一旦您找到了添加新节点的位置(
v
),假设它是某个节点
u
的子节点。
你需要找到上一页。它可以在
O(h)
中执行,方法是在树上向上移动,直到找到一个节点
x
,该节点有一个左子节点。按以下顺序转到左侧子对象,并在其上继续遍历:

if the current node has right son:
     go to right son, repeat
else if the current node has left son:
     go to left son, repeat
else:
     found previous leaf, let it be l
现在,您有了新的节点
v
,还有上一个叶
l

你现在要做的就是把v的节点放在l的节点之后:

v.node = createNode();
v.node.next = l.node.next; 
l.node.next = v.node;
该算法的复杂度为
O(h)
,其中
h
是树的高度


注意:注意简单的边缘情况,其中
v
是链表中的第一个节点。

您还必须考虑节点删除,例如,如果9获得子节点。直观地看,似乎每个内部节点都应该保留叶列表中与其子树对应的第一个和最后一个节点的控制柄,以便在向下遍历到插入新节点的位置时缩小搜索范围。@MattOlson是的,这实际上是一个简单的例子,如果我们知道我们在一个叶子中添加了一个叶子,那么我们只需要覆盖列表中相应位置的数据。@MattOlson关于另一部分,你的意思是,例如,在原始树中,
2
应该包含
9
3
?否;例如,8将持有指向9和3(其子树的边界)的指针;5人分别持有9票和2票;7将保留
null
和2(其左子树上没有叶子),依此类推。然后,当您达到7时,在正确的位置添加1(可能您需要一个双链接列表),并在展开堆栈时将更改传播回树。我只是头脑风暴;如果我提出了一个具体的算法,我会把它作为一个答案发布。或者你可以使用@amit的解决方案,这比我想象的要简单得多。:)爬上树,很好!如果树没有父级定义,那么最好的解决方案就是创建一个新的列表?两个AMIT回答相同问题的几率有多大lol.@kuhaku否,如果没有父级定义,您仍然可以“找到”它,因为您从根递归地插入了元素(我假定),因此,您可以爬回堆栈并获取所需的
父级。