二叉树的创建,遍历,增删查基本操作详解

二叉树的创建以及前中后序递归完整代码:

//二叉树的创建与遍历 

#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);
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值