术语:

节点深度:对任意节点x,x节点的深度表示为根节点到x节点的路径长度。所以根节点深度为0,第二层节点深度为1,以此类推
节点高度:对任意节点x,叶子节点到x节点的路径长度就是节点x的高度
树的深度:一棵树中节点的最大深度就是树的深度,也称为高度
父节点:若一个节点含有子节点,则这个节点称为其子节点的父节点
子节点:一个节点含有的子树的根节点称为该节点的子节点
节点的层次:从根节点开始,根节点为第一层,根的子节点为第二层,以此类推
兄弟节点:拥有共同父节点的节点互称为兄弟节点
度:节点的子树数目就是节点的度
叶子节点:度为零的节点就是叶子节点
祖先:对任意节点x,从根节点到节点x的所有节点都是x的祖先(节点x也是自己的祖先)
后代:对任意节点x,从节点x到叶子节点的所有节点都是x的后代(节点x也是自己的后代)
森林:m颗互不相交的树构成的集合就是森林
--------------------- 
作者:zeling1005 
来源:CSDN 
原文:https://blog.csdn.net/u014532217/article/details/79118023 
版权声明:本文为博主原创文章,转载请附上博文链接!

树、二叉树、森林的转换

https://blog.csdn.net/jiashuai94/article/details/80760041

二叉树的遍历

#include<bits/stdc++.h>
using namespace std;
typedef int ElemType;
typedef struct tree{
	ElemType elem;
	int time;
	tree *left,*right;
};
tree* creat(){
	tree *t;
	int x;
	cin>>x;
	if(!x) return NULL;
	else{
		t=(tree*)malloc(sizeof(tree));
		t->elem=x;
		t->left=creat();
		t->right=creat();
	}
	return t;
}
void preorder(tree* root){//递归先序 
	if(root!=NULL){
		cout<<root->elem<<" ";
		preorder(root->left);
		preorder(root->right);
	}
}
void inorder(tree* root){//递归中序 
	if(root!=NULL){
		inorder(root->left);
		cout<<root->elem<<" ";
		inorder(root->right);
	}
}
void postorder(tree* root){//递归后序 
	if(root!=NULL){
		postorder(root->left);
		postorder(root->right);
		cout<<root->elem<<" ";
	}
}
void preorder2(tree *root){//非递归先序 
	stack<tree*> st;
	while(st.size()>0||root!=NULL){
		while(root!=NULL){
			st.push(root);
			cout<<root->elem<<" ";
			root=root->left;
		}
		if(st.size()>0){
			root=st.top();
			st.pop();
			root=root->right;
		}
	}
	cout<<endl;
}
void inorder2(tree *root){//非递归中序 
	stack<tree*> st;
	while(st.size()>0||root!=NULL){
		while(root!=NULL){//一直深入左子树 
			st.push(root);
			root=root->left;
		}
		if(st.size()>0){//此时在最左 
			root=st.top();//返回上一结点 
			st.pop();
			cout<<root->elem<<" ";
			root=root->right;//深入右子树 
		}
	}
	cout<<endl;
}
void postorder2(tree *root){//非递归后序 
	stack<tree*> st;
	tree *p;
	while(root!=NULL||st.size()>0){
		while(root!=NULL){
			root->time++;
			st.push(root);//第一次入栈,不用访问 
			root=root->left;
		}
		if(st.size()){
			root=st.top();
			st.pop();
			if(root->time==1){
				root->time++;
				st.push(root);//第二次入栈(即遇到),不用访问 
				root=root->right;
			}
			else{
				cout<<root->elem<<" ";
				root=NULL;//root结点已经是第三次遇见,那么左右子树也已经访问过,可置NULL,也可去掉 
			}
		}
	}
	cout<<endl;
}
//本质和2一样 
void preorder3(tree *root){
	stack<tree*> st;
	if(!root) return;
	st.push(root);
	while(!st.empty()){
		tree *t=st.top();
		st.pop();
		printf("%d ",t->elem);
		if(t->right) st.push(t->right);
		if(t->left) st.push(t->left);
	}
}
void inorder3(tree *root){
	if(!root) return;
	stack<tree*> st;
	tree *p=root;
	while(!st.empty()||p){
		while(p){
			st.push(p);
			p=p->left;
		}
		p=st.top();
		st.pop();
		printf("%d ",p->elem);
		//如果有右孩子赋值为右孩子 
		if(p->right){
			p=p->right;
		}
		//否则赋值为NULL,下一次循环跳过while,找到新结点的右孩子 
		else p=NULL;
	}
}
void postorder3(tree* root){
	//两个栈
	/*
	stack<tree*> st1,st2;
	st1.push(root);
	while(!st1.empty()){
		tree *cur = st1.top();
		st1.pop();
		st2.push(cur);
		if(cur->left) st1.push(cur->left);
		if(cur->right) st1.push(cur->right);
	} 
	while(!st2.empty()){
		cout<<st2.top()->elem<<" ";
		st2.pop();
	}
	*/
	//一个栈
	/**/
	stack<tree*> st;
	st.push(root);
	tree *c= root;
	while(!st.empty()){
		tree *cur=st.top();
		if(cur->left && cur->left!=c && cur->right!=c){
			st.push(cur->left);
		}
		else if(cur->right && cur->right!=c){
			st.push(cur->right);
		}
		else{
			st.pop();
			c=cur;
			cout<<cur->elem<<" ";
		}
	}
}
 
int NumOfNode(tree *root){
	if(root==NULL) return 0;
	return 1+NumOfNode(root->left)+NumOfNode(root->right);
}
int NumOfLeaf(tree *root){
	if(root!=NULL){
		if(root->left==NULL && root->right==NULL)
			return 1;
		return NumOfLeaf(root->left)+NumOfLeaf(root->right);
	}
}
int DepthOfTree(tree *root){//求树深 
	if(root==NULL) return 0;
	int dl=DepthOfTree(root->left);
	int dr=DepthOfTree(root->right);
	return 1+max(dl,dr);
}
int main(){
	tree *root;
	root=creat();
	postorder(root);
	cout<<endl;
	postorder3(root);
	cout<<endl;
//	postorder(root);
//	cout<<endl;
//	postorder2(root);
//	cout<<endl;
//	inorder(root);
//	cout<<endl;
//	cout<<"结点数:"<<NumOfNode(root)<<endl;
//	cout<<"叶结点数:"<<NumOfLeaf(root)<<endl;
//	cout<<"树深:"<<DepthOfTree(root)<<endl;
	return 0;
}
//11 12 14 0 16 0 0 0 12 15 0 0 0

非递归写法详解: 

https://blog.csdn.net/woshinannan741/article/details/52825163 

线索二叉树 

二叉树每个结点都有指针left和right,当子树为空时它们是空链域,为了避免空间浪费,若结点的左子树为空,则指向遍历序列的前驱,若结点的右子树为空,则指向遍历序列的后继

 

https://blog.csdn.net/u014492609/article/details/40477795

哈弗曼树

https://blog.csdn.net/luoluozlb/article/details/52122874

#include<bits/stdc++.h>
using namespace std;
typedef int ElemType;
const int MAX=1e5+5;
typedef struct HuffTree{
	int weight;//权值
	int lch,rch;
	int tag;
	bool operator<(const HuffTree& temp) const{
		return this->weight<temp.weight;
	} 
}HuffTree;
int hufftree(HuffTree *&ht){
	int n;//叶子结点的个数 
	cin>>n;
	ht = new HuffTree[2*n];
	for(int i=1;i<=n;i++){
		cin>>ht[i].weight;
		ht[i].lch=ht[i].rch=ht[i].tag=0;
	}
	int i=0;
	while(i<n-1){//合并n-1次 
		int x1=0,m1=0x3f3f3f3f;//m1是最小值单元,x1为下标 
		int x2=0,m2=0x3f3f3f3f;//m2是次小值单元,x2为下标 
		for(int j=1;j<=n+i;j++){
			if(ht[j].weight<m1&&!ht[j].tag){
				m2=m1;
				x2=x1;
				m1=ht[j].weight;
				x1=j;
			}
			else if(ht[j].weight<m2&&!ht[j].tag){
				m2=ht[j].weight;
				x2=j;
			}
		}
		i++;
		ht[x1].tag=ht[x2].tag=1;
		ht[n+i].weight=ht[x1].weight+ht[x2].weight;
		ht[n+i].tag=0;
		ht[n+i].lch=x1;
		ht[n+i].rch=x2;
	}
	return 2*n-1;
}
int hufftree_WPL(HuffTree *ht,int i,int depth){
	if(!ht[i].lch&&!ht[i].rch){
		return ht[i].weight*depth;
	}
	else{
		return hufftree_WPL(ht,ht[i].lch,depth+1)+hufftree_WPL(ht,ht[i].rch,depth+1);
	}
}
int main(){
	int n;
	HuffTree *ht;
	n=hufftree(ht);
	printf("    tag   lch weight rch\n");
	for(int i=1;i<=n;i++){
		printf("%d    %d    %d    %d    %d\n",i,ht[i].tag,ht[i].lch,ht[i].weight,ht[i].rch);
	}
	cout<<hufftree_WPL(ht,n,0);
	return 0;
}

AVL深入解读

https://blog.csdn.net/qpzkobe/article/details/81611486

https://blog.csdn.net/Love_Irelia97/article/details/82895991

#include <bits/stdc++.h>
#define rep1(i,s,e,c) for(int i=s;i<e;i=i+c)
#define rep2(i,s,e,c) for(int i=s;i<=e;i=i+c)
#define rep3(i,e,s,c) for(int i=e;i>=s;i=i-c)
using namespace std;
typedef long long ll;
typedef int ElemType;
const int MAXSIZE=10005;
struct AVLtree{
	ElemType elem;
	int bf,height;//bf=左子树高度减去右子树高度 
	AVLtree *left,*right;
	//构造函数 
	AVLtree(ElemType x):elem(x),left(NULL),right(NULL),bf(0),height(0){}
};
int getHeight(AVLtree *t){
	return (t==NULL?-1:t->height);
}
void reHeight_bf(AVLtree *root){
	int hl=getHeight(root->left);
	int hr=getHeight(root->right);
	//更新树高和平衡因子
	root->height=max(hl,hr)+1;
	root->bf=hl-hr; 
}
void LL_Rotate(AVLtree *&root){//LL表示插入到左子树的左子树,需要右旋 
	AVLtree *t = root;
	AVLtree *L = root->left;//root的左子树 
	AVLtree *LR = L->right;//root的左子树的右子树
	//开始右旋 
	L->right=t;
	t->left=LR;
	root=L; 
	//旋转后结点位置变化,更新树高
	reHeight_bf(root->right);
	reHeight_bf(root); 
}
void RR_Rotate(AVLtree *&root){//RR表示插入到右子树的右子树,需要左旋 
	AVLtree *t = root;
	AVLtree *R = root->right;//root的右子树 
	AVLtree *RL = R->left;//root的右子树的左子树
	//开始左旋 
	R->left=t;
	t->right=RL;
	root=R;
	//旋转后结点位置变化,更新树高
	reHeight_bf(root->left);//或者t 
	reHeight_bf(root); 
}
void LR_Rotate(AVLtree *&root){
	RR_Rotate(root->left);//先对root的左子树根结点左旋 
	LL_Rotate(root);//再对root结点右旋 
}
void RL_Rotate(AVLtree *&root){
	LL_Rotate(root->right);
	RR_Rotate(root);
}
bool insertElem(AVLtree *&root,ElemType elem){
	if(root==NULL){
		root = new AVLtree(elem);
		return true;
	}
	//AVL树满足BST性质,不允许有相同的值存在
	if(elem==root->elem){
		return false;
	} 
	else if(elem<root->elem){
		insertElem(root->left,elem);
		reHeight_bf(root);//插入后更新平衡因子bf 
		if(root->bf>1){
			//结点插入到左子树的左结点,LL
			if(elem<root->left->elem){
				LL_Rotate(root);
			} 
			//否则插入到左子树的右结点 ,LR
			else{
				LR_Rotate(root);
			}
		}
	}
	else{
		insertElem(root->right,elem);
		reHeight_bf(root);
		if(root->bf<-1){
			//结点插入到右子树的右结点,RR
			if(elem>root->right->elem){
				RR_Rotate(root);
			} 
			//否认则插入到右子树的左结点,RL
			else{
				RL_Rotate(root);
			} 
		}
	}
	return true;
}
//中序遍历下的前驱 
AVLtree* find_LeftMax(AVLtree *root){
	AVLtree *t=root->left;//左子树中找最右下结点 
	while(t->right!=NULL){
		t=t->right;
	}
	return t;
}
//中序遍历下的后继
AVLtree* find_RightMin(AVLtree *root){
	AVLtree *t=root->right;//右子树中找最左下结点 
	while(t->left!=NULL){
		t=t->left;
	}
	return t;
} 
bool deleteElem(AVLtree *&root,const int x){
	if(root==NULL) return false;
	//查找到要删除的结点
	if(x==root->elem){
		AVLtree *t=root;
		//左右子树都存在 
		if(root->left!=NULL && root->right!=NULL){
			//若删除结点的左子树高度>右子树高度
			//找到该结点的前驱
			if(getHeight(root->left)>getHeight(root->right)){
				t=find_LeftMax(root);
				root->elem=t->elem;
				deleteElem(root->left,t->elem);
			} 
			//否则找该结点的后继
			else{
				t=find_RightMin(root);
				root->elem=t->elem;
                deleteElem(root->right,t->elem);
			} 
		}
		else{
			root=(root->left)?root->left:root->right;
			delete t;
		}
	} 
	//左子树递归
	else if(x<root->elem){
		//未找到删除结点,直接返回
		if(!deleteElem(root->left,x)){
			return false;
		} 
		reHeight_bf(root);
		//删除左子树结点后失去平衡 
		if(root->bf<-1){
			AVLtree *t=root->right;
			//右子树的左子树比右子树的右子树高
			//相当于在右子树的左子树插入结点
			if(getHeight(t->left)>getHeight(t->right)){
				RL_Rotate(root);
			} 
			//否则相当在右子树的右子树插入结点,RR
			else{
				RR_Rotate(root);
			} 
		}
	} 
	//右子树递归 
	else{
		//未找到删除结点,直接返回
		if(!deleteElem(root->right,x)){
			return false;
		} 
		reHeight_bf(root);
		//删除右子树结点后失去平衡
		if(root->bf>1){
			AVLtree *t=root->left;
			//左子树的左子树比左子树的右子树高
			//相当于在左子树的左子树插入结点,LL
			if(getHeight(t->left)>getHeight(t->right)){
				LL_Rotate(root);
			} 
			else{
				LR_Rotate(root);
			}
		} 
	}
	return true;
}
void inorder(AVLtree *root){//非递归中序
	stack<AVLtree*> st;
	while(st.size()>0||root!=NULL){
		while(root!=NULL){
			st.push(root);
			root=root->left;
		}
		if(st.size()>0){
			root=st.top();
			st.pop();
			cout<<root->elem<<" ";
			root=root->right;
		}
	}
}
void inorder2(AVLtree *root){
	if(root!=NULL){
		if(root->left!=NULL)
			inorder2(root->left);
		cout<<root->elem<<" ";
		if(root->right!=NULL)
			inorder2(root->right);
	}
	
}
void preorder(AVLtree *root)
{
	if(root!=NULL){
		cout<<root->elem<<" ";
		if(root->left!=NULL)
			preorder(root->left);
		if(root->right!=NULL)
		preorder(root->right);	
	}	
}
void postorder(AVLtree *root)
{
	if(root!=NULL){
		if(root->left!=NULL)
			postorder(root->left);
		if(root->right!=NULL)
			postorder(root->right);	
		cout<<root->elem<<" ";
	}	
}
int main()
{
    AVLtree *root=NULL;
	ElemType data_arr[]={1,21,2,205,13,50,6};
	for(int i=0;i<7;i++){//根据插入元素操作得到AVL树 
		insertElem(root,data_arr[i]);
	}
	inorder2(root);
	cout<<endl;
	preorder(root);
	cout<<endl;
    return 0;
}                                 

无视下面的代码,只是我又敲了一遍练手 

#include <bits/stdc++.h>
#define rep1(i,s,e,c) for(int i=s;i<e;i=i+c)
#define rep2(i,s,e,c) for(int i=s;i<=e;i=i+c)
#define rep3(i,e,s,c) for(int i=e;i>=s;i=i-c)
using namespace std;
typedef long long ll;
const int MAX=2e5+1;
const int MOD=1e9+7;
typedef int ElemType;
struct Node{
	ElemType elem;
	int bf,height;
	Node *left,*right;
	Node(ElemType x):elem(x),bf(0),height(0),left(NULL),right(NULL) {}
};
typedef Node *AVLtree;
int getHeight(AVLtree p){
	return p==NULL?-1:p->height;
}
void reHeight_bf(AVLtree p){
	int hl=getHeight(p->left);
	int hr=getHeight(p->right);
	p->height=max(hl,hr)+1;
	p->bf=hl-hr;
}
void LL_Rotate(AVLtree &p){
	AVLtree L=p->left;
	AVLtree LR=L->right;
	p->left=LR;
	L->right=p;
	p=L;
	reHeight_bf(p->right);
	reHeight_bf(p);
}
void RR_Rotate(AVLtree &p){
	AVLtree R=p->right;
	AVLtree RL=R->left;
	p->right=RL;
	R->left=p;
	p=R;
	reHeight_bf(p->left);
	reHeight_bf(p);
}
void LR_Rotate(AVLtree &p){
	RR_Rotate(p->left);
	LL_Rotate(p);
}
void RL_Rotate(AVLtree &p){
	LL_Rotate(p->right);
	RR_Rotate(p);
}
bool insertElem(AVLtree &p,ElemType x){
	if(p==NULL){
		p=new Node(x);
		return true;
	}
	if(x==p->elem){
		return false;
	}
	if(x<p->elem){
		insertElem(p->left,x);
		reHeight_bf(p);
		if(p->bf>1){
			if(x<p->left->elem){
				LL_Rotate(p);
			}
			else{
				LR_Rotate(p);
			}
		}
	}
	else{
		insertElem(p->right,x);
		reHeight_bf(p);
		if(p->bf<-1){
			if(x>p->right->elem){
				RR_Rotate(p);
			}
			else RL_Rotate(p);
		}
	}
	return true;
}
AVLtree find_LeftMax(AVLtree p){
	AVLtree t=p->left;
	while(t->right)
		t=t->right;
	return t;
}
AVLtree find_RightMin(AVLtree p){
	AVLtree t=p->right;
	while(t->left)
		t=t->left;
	return t;
}
bool deleteElem(AVLtree &p,int x){
	if(p==NULL) return false;
	if(x==p->elem){
		AVLtree t=p;
		if(p->left && p->right){
			if(getHeight(p->left)>getHeight(p->right)){
				t=find_LeftMax(p);
				p->elem=t->elem;
				deleteElem(p->left,p->elem);
			}
			else{
				t=find_RightMin(p);
				p->elem=t->elem;
				deleteElem(p->right,p->elem);
			}
		}
		else{
			p=p->left?p->left:p->right;
			delete t;
		}
	}
	else if(x<p->elem){
		if(!deleteElem(p->left,x)){
			return false;
		}
		reHeight_bf(p);
		if(p->bf<-1){
			AVLtree t=p->right;
			if(getHeight(t->left)>getHeight(t->right)){
				RL_Rotate(p);
			}
			else{
				RR_Rotate(p);
			}
		}
	}
	else{
		if(!deleteElem(p->right,x)){
			return false;
		}
		reHeight_bf(p);
		if(p->bf>1){
			AVLtree t=p->left;
			if(getHeight(t->left)>getHeight(t->right)){
				LL_Rotate(p);
			}
			else{
				LR_Rotate(p);
			}
		}
	}
	return true;
}
void preorder(AVLtree p){
	stack<AVLtree> st;
	while(!st.empty()||p){
		while(p){
			st.push(p);
			cout<<p->elem<<" ";
			p=p->left;
		}
		if(!st.empty()){
			p=st.top();
			st.pop();
			p=p->right;
		}
	}
	cout<<endl;
}
void inorder(AVLtree p){
	stack<AVLtree> st;
	while(!st.empty()||p){
		while(p){
			st.push(p);
			p=p->left;
		}
		if(!st.empty()){
			p=st.top();
			st.pop();
			cout<<p->elem<<" ";
			p=p->right;
		}
	}
	cout<<endl;
}
int main()
{    
    AVLtree root=NULL;//root一定要初始化NULL,不然insert的时候会出事 
    ElemType data_arr[]={1,21,2,205,13,50,6};
	for(int i=0;i<7;i++){//根据插入元素操作得到AVL树 
		insertElem(root,data_arr[i]);
	}
	deleteElem(root,205);
	preorder(root);
	inorder(root);
    return 0;
}

 

指针和引用的区别 

https://blog.csdn.net/superwangxinrui/article/details/80565594 

*&和&*(去搜),引用的指针和指针的引用,离变量越近越先解读,如上述代码中的AVLtree *&root,首先&表示引用,然后是AVLtree*类型的变量。

B树

字典树

红黑树

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值