二叉树是比较重要的数据结构,它查询,删除,添加效率都很高,在很多算法比如回溯算法,递归算法,DFS都有利用到二叉树的模型,很多高级数据结构底层都是二叉树比如优先队列底层就是完全二叉树,并查集底层也是二叉树实现, 集合底层就是红黑数实现,后面的红黑树,ALV树,B+,B-,B树其实都是二叉树进化来其删除,推荐,查询更高。
这里首先给出二叉树基本操作包括增,删,查,4种遍历,以及一些操作后面陆续更新其他几种树
本代码都是c++实现
本人水平不是很高,望大家多多指点
#include<iostream>
#include<string>
#include<stack>
#include<queue>
using namespace std;
struct BSTNode{ //声明二叉树
int data;
BSTNode *left,*right;
};
/********************
@declde 插入关键字 注意bt一定是指针的引用
@param bt 当前节点的引用
@param key 关键字
********************/
bool insertValue(BSTNode* &bt,int key){
if(bt==NULL){
bt=new BSTNode;
bt->data=key;
bt->left=NULL;
bt->right=NULL;
return true;
}
if(bt->data==key)
return false;
if(bt->data>key)
return insertValue(bt->left,key);
if(bt->data<key)
return insertValue(bt->right,key);
}
/********************
@declde 通过关键字去递归检索二叉树 查找成功返回其节点 否则返回NULL
@param bt 当前节点的引用
@param key 关键字
@return 返回当前节点的指针
********************/
BSTNode* SearchBST(BSTNode* &bt,int key){ //检索
if(bt==NULL||bt->data==key)
return bt;
return key<bt->data?SearchBST(bt->left,key):SearchBST(bt->right,key);
}
/********************
@declde 通过关键字去递归检索二叉树 查找成功返回其节点 否则返回NULL 同时可以获取其父亲节点的指针
@param bt 当前节点的引用
@param key 关键字
@param parent 父亲节点为一个指针的引用
@param temp 辅助指针 指向当前节点的父亲指针 初始默认值为空
@return 返回当前节点的指针
********************/
BSTNode* SearchBST(BSTNode* &bt,int key,BSTNode* &parent,BSTNode *temp=NULL){
if(bt==NULL)
{
parent=NULL;
return NULL;
}
else if(bt->data==key){
parent=temp;
return bt;
}
return key<bt->data?SearchBST(bt->left,key,parent,bt):SearchBST(bt->right,key,parent,bt);
}
BSTNode* maxNode(BSTNode* bt,BSTNode* &parent,BSTNode *temp=NULL){
if(bt==NULL){
parent=NULL;
return NULL;
}
if(bt->right==NULL){
parent=temp;
return bt;
}
return maxNode(bt->right,parent,bt);
}
BSTNode* maxNode(BSTNode* bt){
return bt->right!=NULL?maxNode(bt->right):bt;
}
BSTNode* minNode(BSTNode* bt){ //获取树的最小值节点的指针
return bt->left?minNode(bt->left):bt;
}
BSTNode* minNode(BSTNode* bt,BSTNode* &parent,BSTNode *temp=NULL){
if(bt==NULL){
parent=NULL;
return NULL;
}
if(bt->left==NULL){
parent=temp;
return bt;
}
return minNode(bt->left,parent,bt);
}
/********************
3种基础遍历
递归方式太简单了没写
以下都是非递归利用到栈这种数据结构
其中后序遍历比较复杂
**********************/
void BSTPreLe(BSTNode* &bt){ //非递归先序遍历
stack<BSTNode*> s;
BSTNode* p=bt;
while(1){
while(p){
cout<<p->data;
s.push(p);
p=p->left;
}
if(s.empty())
break;
p=s.top()->right;
s.pop();
}
}
void BSTIoTra(BSTNode* &bt){ //非递归中序遍历
stack<BSTNode*> s;
BSTNode* p=bt;
while(1){
while(p){
s.push(p);
p=p->left;
}
if(s.empty())
break;
cout<<s.top()->data;
p=s.top()->right;
s.pop();
}
}
void BSTPoTra(BSTNode* &bt){ //非递归后序遍历 重点难得理解 性质:搜索到当前节点 其栈里都为其祖先节点
stack<BSTNode*> s;
BSTNode *last=NULL; //标记指针
BSTNode* p=bt;
while(1){
while(p){
s.push(p);
p=p->left;
}
if(s.empty())
break;
if(last==s.top()->right){
cout<<s.top()->data;
last=s.top();
s.pop();
}
else{
p=s.top()->right;
last=NULL;
}
}
}
/*
层次遍历
利用队列实现
*/
void BSTLeTra(BSTNode* &bt){ //层次遍历
queue<BSTNode*> q;
q.push(bt);
while(!q.empty()){
cout<<q.front()->data;
if(q.front()->left){
q.push(q.front()->left);
}
if(q.front()->right){
q.push(q.front()->right);
}
q.pop();
}
}
/*
重点在于什么时候换层操作
*/
int BSTMaxWidth(BSTNode* &bt){ //h获取树的最大宽度(基于bfs搜索)
queue<BSTNode*> q;
q.push(bt);
BSTNode* tail; //辅助指针
BSTNode* last=bt; //指向每一层最后一个节点
int max=0;
int count=0; //记录每一层的节点数
while(!q.empty()){
cout<<q.front()->data;
count++;
if(q.front()->left){
q.push(q.front()->left);
tail=q.front()->left;
}
if(q.front()->right){
q.push(q.front()->right);
tail=q.front()->right;
}
if(last==q.front()){ //进入下一层
max=max>count?max:count;
count=0;
cout<<endl;
last=tail;
}
q.pop();
}
return max;
}
/*****************************************************************
当前节点左右节点都存在 进行删除操作
找到左边子树的最大值节点或者找到右边子树的最小节点 替换掉将要删除的节点的值 然后去删除最大节点或最小节点
注意最大节点左子树可能存在的情况或者最小节点可能存在的情况 不能直接进行删除 删除要传指针的引用
******************************************************************/
void Delete1(BSTNode* p,BSTNode * &r){
if(r->right==NULL){
BSTNode *q;
p->data=r->data;
q=r;
r=r->left;
delete q;
}
else
Delete1(p,r->right);
}
void Delete(BSTNode* &p){
BSTNode* q;
if(p->left==NULL&&p->right==NULL)
{
q=p;
p=NULL;
delete q;
}
else if(p->left==NULL){
q=p;
p=p->right;
delete q;
}
else if(p->right==NULL){
q=p;
p=p->left;
delete q;
}
// 5
// 2 7
// 1
else{ //左右孩子都有
Delete1(p,p->left);
}
}
bool BSTDelete(BSTNode* &bt,int key){ //删除操作接口
if(bt==NULL)
return false;
else if(bt->data==key){
Delete(bt);
return true;
}
return key<bt->data?BSTDelete(bt->left,key):BSTDelete(bt->right,key);
}
int BSTHeight(BSTNode* &bt){
if(bt==NULL)
return 0;
else
{
int left=BSTHeight(bt->left)+1;
int right=BSTHeight(bt->right)+1;
return left>right?left:right;
}
}
int main(){
BSTNode* bt=NULL;
insertValue(bt,5);
insertValue(bt,2);
insertValue(bt,1);
insertValue(bt,7);
BSTLeTra(bt);
}