二叉树寻找前驱的普通方法和线索二叉树对比
【摘要】
目录标题
普通方法缺点
线索二叉树注意这里我们只给出了中序的线索二叉树实现,但是再实现先序线索二叉树的时候要避免死循环的情况要对最后一个节点的tagClueLChild修改为true
...
普通方法
//结构体
typedef struct TreeNode {
int data;
struct TreeNode* lchild;
struct TreeNode* rchild;
}*BT,TN;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
//寻找二叉树中序遍历的前驱
BT pre;
void findPreInorder(BT root,int p) {
if (!root)return;
findPreInorder(root->lchild,p);
if (root->data == p) {
printf("%d\n", pre->data);
return;
}
else {
pre = root;
}
findPreInorder(root->rchild,p);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
//寻找二叉树中序遍历的后继
TN pre1 = {-1};
BT pre2 = &pre1;
void findSubInorder(BT root, int p) {
if (!root)return;
findSubInorder(root->lchild, p);
if (pre2->data == p) {//当前驱等于要找的节点的时候该节点就是要寻找的后继
printf("%d\n", root->data);
pre2->data = -1;//防止下次再进入if
return;
}
else {
pre2 = root;
}
findSubInorder(root->rchild, p);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
//中序遍历该树用作对比,看看一会我们求得前驱和后继对不对
void inorder(BT temphead) {
if (!temphead)return;
inorder(temphead->lchild);
printf("%d ", temphead->data);
inorder(temphead->rchild);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
//广度优先初始化二叉树,图像和上面图片一样
void order(BT head) {
queue<BT> q;
BT node = (BT)malloc(sizeof(BT));
q.push(head);
int i = 2;
while (i < 16) {
BT lnode = (BT)malloc(sizeof(BT));
lnode->data = i;
lnode->lchild = NULL;
lnode->rchild = NULL;
i++;
BT rnode = (BT)malloc(sizeof(BT));
rnode->data = i;
rnode->lchild = NULL;
rnode->rchild = NULL;
i++;
q.front()->lchild = lnode;
q.front()->rchild = rnode;
q.pop();
q.push(lnode);
q.push(rnode);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
int main() {
BT head = (BT)malloc(sizeof(BT));
head->data = 1;
order(head);
BT temphead = head;//避免一会树得根节点地址丢失
printf("中序遍历:\n");
inorder(temphead);
printf("\n寻找节点5的前驱:");
temphead = head;
findPreInorder(temphead, 5);
printf("\n寻找节点5的后继:");
temphead = head;
findSubInorder(temphead, 5);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
缺点
每次寻找某节点前驱还要再遍历一次二叉树不能直接得到某节点的前驱
线索二叉树
之前我们提到了,二叉树的是存在n+1个空链域的,反正这些内存空着也是空着大佬们就想到了利用这些空的链域搞点事情,弄出了一个线索二叉树。
//建立
typedef struct TreeNode {
int data;
bool tagClueLChild=false;
bool tagClueRChild=false;
struct TreeNode* lChild=NULL;
struct TreeNode* rChild=NULL;
}*BT;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
//中序遍历线索二叉树
void cluePreInorder(BT root) {
if (!root)return;
cluePreInorder(root->lChild);
visit(root);
cluePreInorder(root->rChild);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
//建立一个全局前驱节点
static BT pre;
void visit(BT root) {
if (root->lChild == NULL) {
root->lChild = pre;
root->tagClueLChild = true;
}
if (pre != NULL && pre->rChild == NULL) {
pre->rChild = root;
pre->tagClueRChild = true;
}
pre = root;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
然后我们就可以愉快的直接从某个节点直接找到它的前驱和后继了不用再去遍历一遍二叉树了。
注意
这里我们只给出了中序的线索二叉树实现,但是再实现先序线索二叉树的时候要避免死循环的情况
//先序遍历线索二叉树
void cluePrePreorder(BT root) {
if (!root)return;
visit(root);
cluePrePreorder(root->lChild);
cluePrePreorder(root->rChild);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
也就是当root的节点为8的时候,二叉树的前驱pre为4,再visit的时候会把8的lChild指向4节点在进行下一句cluePrePreorder(root->lChild);
又会回到8节点此时8节点以经访问过了。所以代码要改进为
//先序遍历线索二叉树
void cluePrePreorder(BT root) {
if (!root)return;
visit(root);
if(root->tagClueLChild)//当不是线索二叉树的时候
cluePrePreorder(root->lChild);
cluePrePreorder(root->rChild);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
要对最后一个节点的tagClueLChild修改为true
文章来源: blog.csdn.net,作者:肥学,版权归原作者所有,如需转载,请联系作者。
原文链接:blog.csdn.net/jiahuiandxuehui/article/details/124601644
【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)