二叉树的创建以及前中后序递归完整代码:
//二叉树的创建与遍历
#include <bits/stdc++.h>
using namespace std;
#define N 20
//定义结构体 作为结点
typedef struct Tree {
char data;
struct Tree* LeftChild;
struct Tree* RightChild;
} BiTNode, *BiTree;
//BiTNode为结点 BiTree为结点数组
//创建二叉树
BiTree CreateTree() {
//创建一个根节点
BiTree tree;
char ch;
cin>>ch;
//结束创建
if(ch == '#') {
return NULL;
} else {
//创建等大小等类型的根节点
tree = (BiTree)malloc(sizeof(BiTNode));
tree->data = ch;
tree->LeftChild = CreateTree();
tree->RightChild = CreateTree();
return tree;
}
}
//非递归 前序遍历
void NPreOrder(BiTree bt) {
//相当于 BiTNode** s
BiTree* s;
BiTree p;
int top = -1;
//创建栈
s = (BiTree*)malloc((N+1) * sizeof(BiTree));
//s[0]=bt top=0
s[++top] = bt;
while(top != -1) {
p = s[top--];
//输出是s[top] top再--
cout<<p->data;
if(p->RightChild) {
//让新的二叉树结点进栈
s[++top] = p->RightChild;
}
if(p->LeftChild) {
//这里必须右结点先进栈 再是左节点
s[++top] = p->LeftChild;
}
}
}
//递归 前序遍历
void YPreOrder(BiTree bt) {
//前序递归遍历中左右
if(bt) {
cout<<bt->data;
YPreOrder(bt->LeftChild);
YPreOrder(bt->RightChild);
}
}
//非递归 中序遍历
void NInOrder(BiTree bt) {
BiTree* s;
BiTree p, q;
s = (BiTree*)malloc((N+1) * sizeof(BiTree));
//top = -1 就是栈空的意思
int top = -1;
if(bt) {
while(bt) {
s[++top] = bt;
//左子树全部进栈一直到最左的叶子节点
bt = bt->LeftChild;
}
while(top != -1) {
//取出栈顶元素之后 top再减去一
p = s[top--];
cout<<p->data;
//看看当前结点是否有右子结点
while(p->RightChild) {
//有则赋给q 并且进栈
q = p->RightChild;
s[++top] = q;
//再看看有没有左子结点
while(q->LeftChild) {
s[++top] = q->LeftChild;
q = q->LeftChild;
}
//跳出第二个while循环
break;
}
}
}
}
//递归 中序遍历
void YInOrder(BiTree bt) {
//前序递归遍历中左右
if(bt) {
YInOrder(bt->LeftChild);
cout<<bt->data;
YInOrder(bt->RightChild);
}
}
/*
后序遍历的非递归算法是三种顺序中最复杂的,原因在于,后序遍历是先访问左、右子树,再访问根节点,
而在非递归算法中,利用栈回退到时,并不知道是从左子树回退到根节点,还是从右子树回退到根节点,
如果从左子树回退到根节点,此时就应该去访问右子树,
而如果从右子树回退到根节点,此时就应该访问根节点。
所以相比前序和后序,必须得在压栈时添加信息,
以便在退栈时可以知道是从左子树返回,还是从右子树返回进而决定下一步的操作
*/
//非递归 后序遍历
void NPostOrder(BiTree bt) {
BiTree* s;
BiTree p, q;
q = NULL;
s = (BiTree*)malloc((N+1) * sizeof(BiTree));
int top = -1;
while(bt!=NULL||top!=-1) {
//遍历完左边的树
if(bt) {
s[++top] = bt;
bt = bt->LeftChild;
} else {
//取出栈顶元素做一个试探
bt = s[top];
//如果没有右子结点或者右子结点已经遍历过了
if(bt->RightChild==NULL||bt->RightChild==q) {
cout<<bt->data;
//保存到q, 为下一次已处理结点前驱
q=bt;
top--;
bt = NULL;
} else {
//正经遍历右结点
bt = bt->RightChild;
}
}
}
}
//递归 后序遍历
void YPostOrder(BiTree bt) {
//前序递归遍历中左右
if(bt) {
YPostOrder(bt->LeftChild);
YPostOrder(bt->RightChild);
cout<<bt->data;
}
}
//主函数
int main() {
BiTree pt;
cout<<"创建二叉树"<<endl;
pt = CreateTree();
cout<<"前序非递归遍历"<<endl;
NPreOrder(pt);
cout<<endl;
cout<<"前序递归遍历"<<endl;
YPreOrder(pt);
cout<<endl;
cout<<"中序非递归遍历"<<endl;
NInOrder(pt);
cout<<endl;
cout<<"中序递归遍历"<<endl;
YInOrder(pt);
cout<<endl;
cout<<"后序非递归遍历"<<endl;
NPostOrder(pt);
cout<<endl;
cout<<"后序递归遍历"<<endl;
YPostOrder(pt);
cout<<endl;
return 0;
}
二叉查找树的创建以及查找,插入,删除操作的实现
//二叉查找树
#include <bits/stdc++.h>
using namespace std;
#define N 20
//定义结构体 作为结点
typedef struct Tree {
int data;
struct Tree* LeftChild;
struct Tree* RightChild;
} BiTNode, *BiTree;
//BiTNode为结点 BiTree为结点数组
//创建二叉树
BiTree CreateTree() {
//创建一个根节点
BiTree tree;
int data;
cin>>data;
//结束创建
if(data == -1) {
return NULL;
} else {
//创建等大小等类型的根节点
tree = (BiTree)malloc(sizeof(BiTNode));
tree->data = data;
tree->LeftChild = CreateTree();
tree->RightChild = CreateTree();
return tree;
}
}
//查找
int Find(int data, BiTree bt) {
while(bt!=NULL) {
if(data < bt->data) {
bt = bt->LeftChild;
} else if(data > bt->data) {
bt = bt->RightChild;
} else {
return 1;
}
}
return 0;
}
//插入
int Insert(int data, BiTree bt) {
//创建一个空指针
BiTree null = NULL;
BiTree p;
p->data = data;
while(bt!=NULL) {
if(data > bt->data) {
if(bt->RightChild == NULL) {
bt->RightChild = p;
return 1;
}
bt = bt->RightChild;
}
else {
if(bt->LeftChild) {
bt->LeftChild = p;
return 1;
}
bt = bt->LeftChild;
}
}
}
//删除
//删除操作比较复杂 得分三种情况
//1 要删除的节点没有子节点
//2 要删除的节点只有一个子节点
//3 要删除的节点有两个子节点
int Delete(int data, BiTree bt) {
//如果树为空 直接退出
if(bt == NULL) {
return 0;
}
//用来指向要删除的节点 初始化指向根节点
BiTree p = bt;
//q记录的是p的父节点
BiTree q;
while(p!=NULL && p->data!=data) {
q = p;
if(p->data < data) {
p = p->RightChild;
} else {
p = p->LeftChild;
}
}
if(p == NULL) {
//没有找到
return 0;
}
//如果要删除的节点是叶子节点
if(p->LeftChild==NULL && p->RightChild==NULL) {
free(p);
p = NULL;
return 1;
}
//如果要删除的节点只有左节点
else if(p->LeftChild!=NULL && p->RightChild==NULL) {
//如果是根节点 直接删除
if(p==bt) {
free(p);
p = NULL;
bt = NULL;
}
//判断要删除的节点是双亲的左孩子时
//将双亲的指针域指向删除节点的左孩子
else if(p == q->LeftChild) {
q->LeftChild = p->LeftChild;
free(p);
p = NULL;
}
//判断要删除的节点是双亲的左孩子时
//将双亲的指针域指向删除节点的左孩子
else if(p == q->RightChild) {
q->RightChild = p->LeftChild;
free(p);
p = NULL;
}
return 1;
}
//如果要删除的节点只有右节点
else if(p->LeftChild==NULL && p->RightChild!=NULL) {
//如果是根节点 直接删除
if(p==bt) {
free(p);
p = NULL;
bt = NULL;
}
//判断要删除的节点是双亲的左孩子时
//将双亲的指针域指向删除节点的左孩子
else if(p == q->LeftChild) {
q->LeftChild = p->RightChild;
free(p);
p = NULL;
}
//判断要删除的节点是双亲的左孩子时
//将双亲的指针域指向删除节点的左孩子
else if(p == q->RightChild) {
q->RightChild = p->RightChild;
free(p);
p = NULL;
}
return 1;
}
//当待删除节点的左右子节点都存在时
else {
//找到根节点右子树最左边的节点(也就是替代节点)
BiTree tmp = p->RightChild;
//记录替代节点的父节点
BiTree tmp_parent = p;
while(tmp->LeftChild) {
tmp_parent = tmp;
tmp = tmp->LeftChild;
}
//如果替代节点在双亲节点的左边
//则双亲结点指向替代节点的右边
if(tmp_parent->LeftChild == tmp) {
tmp_parent->LeftChild = tmp->RightChild;
} else {
tmp_parent->RightChild = tmp->RightChild;
}
//改变数据
p->data = tmp->data;
free(tmp);
tmp = NULL;
}
}
//递归 前序遍历
void YPreOrder(BiTree bt) {
//前序递归遍历中左右
if(bt) {
cout<<bt->data<<" ";
YPreOrder(bt->LeftChild);
YPreOrder(bt->RightChild);
}
}
//主函数
int main() {
BiTree pt;
cout<<"创建二叉树"<<endl;
pt = CreateTree();
cout<<endl<<"前序递归遍历插入新节点前的二叉树"<<endl;
YPreOrder(pt);
cout<<endl;
/*
cout<<endl<<"查找节点"<<endl;
int data; cin>>data;
cout<<"需要查找的节点对应的数字是: "<<data<<endl;
if(Find(data, pt) == 1) cout<<"该节点存在!!!"<<endl;
else cout<<"该节点不存在!!!"<<endl;
cout<<endl<<"插入节点"<<endl;
int data1; cin>>data1;
cout<<"需要插入的节点对应的数字是: "<<data1<<endl;
if(Insert(data1, pt) == 1) cout<<"插入成功!!!"<<endl;
else cout<<"插入失败!!!"<<endl;
cout<<endl<<"前序递归遍历插入新节点后的二叉树"<<endl;
YPreOrder(pt);
*/
cout<<endl<<"删除节点"<<endl;
int data2;
cin>>data2;
cout<<"需要删除的节点对应的数字是: "<<data2<<endl;
if(Delete(data2, pt) == 1) cout<<"删除成功"<<endl;
else cout<<"删除失败"<<endl;
cout<<endl<<"前序递归遍历删除了节点后的二叉树"<<endl;
YPreOrder(pt);
}