周二就写完了,找bug找了很长时间,今天有空了,发出来。题目如下:
构建二叉排序树,找后继线索链表,插入都还可以,基本操作,就是这个删除比较麻烦,好多种情况,而且他居然每次都是对原二叉树进行插入删除,输出之后还得删除和插入回去,真的是闲的。
找后继采用栈的方法就可以了,插入就和查找差不多,只不过插入是找到上一节点,查找是找到查找节点,我把这两个功能集合成一个函数了,而且我觉得只有后继很麻烦,所以把前驱和根都找出来了。
删除需要按照节点的左右支来分情况讨论:
以下是我的实现:
#include <stdio.h> #include <stdlib.h> struct binaryTreeNode { int num; struct binaryTreeNode *left; struct binaryTreeNode *right; struct binaryTreeNode *next; struct binaryTreeNode *before; struct binaryTreeNode *root; }; struct binaryTree { struct binaryTreeNode *root; struct binaryTreeNode *head; struct binaryTreeNode *end; }; struct binaryTreeStack { struct binaryTreeNode *L[100]; int flag[100]; int top ; }; void run(); struct binaryTreeNode *createNewTree(struct binaryTreeNode *root); struct binaryTreeNode *createNewNode(); void pushStack(struct binaryTreeNode *node); void popStack(); void getTrackList(); int stackEmptyJudge(); struct binaryTreeNode *getNode(int num); void putOutSection(); void cutInNode(int num); void deletNode(int num); void print(); struct binaryTree T; struct binaryTreeStack S; int main() { run(); return 0; } void run() { int in, out; T.root = createNewTree(NULL); getTrackList(); putOutSection(); scanf("%d", &in); cutInNode(in); print(); deletNode(in); scanf("%d", &out); deletNode(out); print(); } struct binaryTreeNode *createNewTree(struct binaryTreeNode *root) { int num; struct binaryTreeNode *cur; scanf("%d", &num); if (num == -1) return NULL; cur = createNewNode(); cur->num = num; cur->left = createNewTree(cur); cur->right = createNewTree(cur); cur->root = root; return cur; } struct binaryTreeNode *createNewNode() { struct binaryTreeNode *p; p = (struct binaryTreeNode *)malloc(sizeof(struct binaryTreeNode)); p->num = 0; p->left = NULL; p->right = NULL; p->next = NULL; p->before = NULL; return p; } void pushStack(struct binaryTreeNode *node) { ++(S.top); S.L[S.top] = node; S.flag[S.top] = 0; } void popStack() { --(S.top); } void getTrackList() { int i; struct binaryTreeNode *next; S.top = -1; pushStack(T.root); while(stackEmptyJudge()) { next = NULL; switch(S.flag[S.top]) { case 0 : { ++(S.flag[S.top]); if(S.L[S.top]->left) pushStack(S.L[S.top]->left); break; } case 1 : { ++(S.flag[S.top]); if(S.L[S.top]->right) pushStack(S.L[S.top]->right); break; } case 2 : { if(S.L[S.top]->right) { next = S.L[S.top]->right; while(next->left) next = next->left; } else { i = S.top - 1; while(i >= 0 && S.flag[i] == 2) i--; if(i >= 0) next = S.L[i]; } S.L[S.top]->next = next; if(next) next->before = S.L[S.top]; popStack(); } } } next = T.root; while(next->left) next = next->left; T.head = next; next->before = NULL; next = T.root; while(next->right) next = next->right; T.end = next; next->next = NULL; } int stackEmptyJudge() { if(S.top == -1) return 0; return 1; } struct binaryTreeNode *getNode(int num) { struct binaryTreeNode *p = T.root; while(1) { if(p->num == num) return p; if(p->num < num) { if(p->right) p = p->right; else return p; } else { if(p->left) p = p->left; else return p; } } } void putOutSection() { int a, b; struct binaryTreeNode *p = T.head; scanf("%d%d", &a, &b); p = getNode(a); if(p->num <= a) p = p->next; while(p && p->num < b) { printf("%d ", p->num); p = p->next; } printf("\n"); } void cutInNode(int num) { struct binaryTreeNode *p = getNode(num), *newNode = createNewNode(); newNode->num = num; newNode->root = p; if(num < p->num) p->left = newNode; else p->right = newNode; getTrackList(); } void deletNode(int num) { struct binaryTreeNode *p, *before, *next, *root; p = getNode(num); root = p->root; next = p->next; before = p->before; if(p->right == NULL && p->left == NULL) { if(root) { if(root->left == p) root->left = NULL; else root->right = NULL; } else T.root = NULL; } else { if(p->left && p->right) { if(p->right == next) { p->num = next->num; p->right = next->right; } else { p->num = next->num; next->root->left = next->right; } } else { if(p->right) { if(p->right == next) { if(root) { if(root->right == p) root->right = next; else root->left = next; } else T.root = next; } else { p->num = next->num; next->root->left = next->right; } } else { if(p->left == before) { if(root) { if(root->right == p) root->right = before; else root->left = before; } else T.root = before; } else { p->num = before->num; before->root->right = before->left; } } } } getTrackList(); } void print() { struct binaryTreeNode *p = T.head; while (p) { printf("%d ", p->num); p = p->next; } printf("\n"); }
以下是各函数的注释:
void run() { int in, out; T.root = createNewTree(NULL);//创建图 getTrackList();//找到后继链表 putOutSection();//输出区间 scanf("%d", &in); cutInNode(in);//插入 print();//输出插入 deletNode(in);//删除插入 scanf("%d", &out); deletNode(out);//删除 print();//输出删除 }
struct binaryTreeNode *createNewTree(struct binaryTreeNode *root) { int num; struct binaryTreeNode *cur; scanf("%d", &num); if (num == -1) return NULL;//结束创建 cur = createNewNode();创建节点 cur->num = num; cur->left = createNewTree(cur);//递归创建 cur->right = createNewTree(cur); cur->root = root;//根节点赋值 return cur; }
struct binaryTreeNode *createNewNode() { struct binaryTreeNode *p; p = (struct binaryTreeNode *)malloc(sizeof(struct binaryTreeNode));//创建节点 p->num = 0;//初始化 p->left = NULL; p->right = NULL; p->next = NULL; p->before = NULL; return p; }
//栈操作 void pushStack(struct binaryTreeNode *node) { ++(S.top); S.L[S.top] = node; S.flag[S.top] = 0; } void popStack() { --(S.top); }
void getTrackList() { int i; struct binaryTreeNode *next; S.top = -1; pushStack(T.root); while(stackEmptyJudge())//栈不空 { next = NULL; switch(S.flag[S.top])//按栈顶元素的标记分类 { case 0 ://0次访问 { ++(S.flag[S.top]);//访问次数增加 if(S.L[S.top]->left) pushStack(S.L[S.top]->left);//压入左支 break; } case 1 : { ++(S.flag[S.top]);//访问次数增加 if(S.L[S.top]->right) pushStack(S.L[S.top]->right);//压入右支 break; } case 2 : { if(S.L[S.top]->right)//若栈顶有右支 { next = S.L[S.top]->right; while(next->left) next = next->left;//找到右支的最左,或右支 } else//若无右支 { i = S.top - 1; while(i >= 0 && S.flag[i] == 2) i--; if(i >= 0) next = S.L[i];//找到栈中从顶到底的第一个一次访问节点,就是后继 } S.L[S.top]->next = next;//后继连接 if(next) next->before = S.L[S.top];前驱连接 popStack();//两次访问后出栈 } } } next = T.root;//头尾赋值 while(next->left) next = next->left; T.head = next; next->before = NULL; next = T.root; while(next->right) next = next->right; T.end = next; next->next = NULL; }
int stackEmptyJudge() { if(S.top == -1) return 0;//判断栈是否空 return 1; }
struct binaryTreeNode *getNode(int num) { struct binaryTreeNode *p = T.root; while(1) { if(p->num == num) return p;//如果找到,返回找到的节点 if(p->num < num)//否则就找到最接近的节点,并返回,方便插入 { if(p->right) p = p->right; else return p; } else { if(p->left) p = p->left; else return p; } } }
void putOutSection() { int a, b; struct binaryTreeNode *p = T.head; scanf("%d%d", &a, &b); p = getNode(a);//找到节点 if(p->num <= a) p = p->next;//如果左区间的节点存在,或左区间值在找到的节点的右支(比如区间(10,15),但是只能找到9,10并不存在),就从后继开始输出 while(p && p->num < b)//遍历输出 { printf("%d ", p->num); p = p->next; } printf("\n"); }
void cutInNode(int num) { struct binaryTreeNode *p = getNode(num), *newNode = createNewNode(); newNode->num = num; newNode->root = p; if(num < p->num) p->left = newNode;//判断插左还是插右 else p->right = newNode; getTrackList();//后继链表更新 }
void deletNode(int num) { struct binaryTreeNode *p, *before, *next, *root; p = getNode(num); root = p->root; next = p->next; before = p->before; if(p->right == NULL && p->left == NULL)//左右都空 { if(root)//如果根存在 { if(root->left == p) root->left = NULL;//判断是删左还是删右 else root->right = NULL; } else T.root = NULL;//整棵树只有一个节点,这树就空了 } else { if(p->left && p->right)//左右都有 { if(p->right == next)//若右支就是后继 { p->num = next->num;//复制 p->right = next->right;//把后继的右支接到p的右支上 } else// { p->num = next->num;//复制 next->root->left = next->right;////吧后继的右支接到后继的根的左支上 } } else { if(p->right)//只有右 { if(p->right == next) { if(root) { if(root->right == p) root->right = next; else root->left = next; } else T.root = next; } else { p->num = next->num; next->root->left = next->right; } } els//e只有左 { if(p->left == before) { if(root) { if(root->right == p) root->right = before; else root->left = before; } else T.root = before; } else { p->num = before->num; before->root->right = before->left; } } } } getTrackList();//后继链表更新 }
void print() { struct binaryTreeNode *p = T.head; while (p)//遍历输出 { printf("%d ", p->num); p = p->next; } printf("\n"); }我估计是还有bug但是测了好多都还行。。。