树的基本操作加例题

树之详解

记住:递归一定有出口,有结束条件

基操

求二叉树的高度

思路:

分析二叉树的深度(高度)和它的左、右子树深度之间的关系。从二叉树深度的定义可知,二叉树的深度应为其左、右子树深度的最大值加1。由此,需先分别求得左、右子树的深度,算法中“访问结点”的操作为:求得左、右子树深度的最大值,然后加 1

int GetHeight( BinTree BT )
{
int l=0,r=0;
if(!BT)
return 0;
else
{
l=GetHeight(BT->Left);
r=GetHeight(BT->Right);
return (l>=r?l:r)+1; //假想一下,当左子树不为NULL 右子树为NULL返回给l 接收自然是1.
}
}

二叉树的四种遍历

void InorderTraversal( BinTree BT )
{
	if(BT==NULL) return ;

		
		InorderTraversal(BT->Left);
           printf(" %c",BT->Data);
		InorderTraversal(BT->Right);
	
}
void PreorderTraversal( BinTree BT )
{
    
	if(BT==NULL) return ;
	

      printf(" %c",BT->Data);
        PreorderTraversal(BT->Left);
        PreorderTraversal(BT->Right);
	
}
void PostorderTraversal( BinTree BT )
{
    if(BT==NULL) return ;
	
	PostorderTraversal(BT->Left);
        PostorderTraversal(BT->Right);
        printf(" %c",BT->Data);
	
}
void LevelorderTraversal( BinTree BT )
{
    BinTree a[100],temp;
    int head=0,rear=0;
    if(BT)
    {
        a[rear++]=BT;
        while(head-rear)
        {
            temp=a[head++];
            printf(" %c",temp->Data);
            if(temp->Left) a[rear++]=temp->Left;
            if(temp->Right) a[rear++]=temp->Right;
        }
    }
}

完全二叉树

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lW5lLtHX-1645454020566)(C:\Users\86159\AppData\Roaming\Typora\typora-user-images\image-20211004155456855.png)]

满二叉树

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hW1iIEsU-1645454020567)(C:\Users\86159\AppData\Roaming\Typora\typora-user-images\image-20211004155504924.png)]

7-5 完全二叉搜索树 (20 分)

一个无重复的非负整数序列,必定对应唯一的一棵形状为完全二叉树的二叉搜索树。本题就要求你输出这棵树的层序遍历序列。

输入格式:

首先第一行给出一个正整数 N(≤1000),随后第二行给出 N 个不重复的非负整数。数字间以空格分隔,所有数字不超过 2000。

输出格式:

在一行中输出这棵树的层序遍历序列。数字间以 1 个空格分隔,行首尾不得有多余空格。

输入样例:
10
1 2 3 4 5 6 7 8 9 0
输出样例:
6 3 8 1 5 7 9 0 2 4
题目分析:

1 一颗完全二叉树的中序遍历对应着从小到达的数列

2 将数组从小到大排序

3 将排序好的数组根据中序遍历构造完全二叉树

4 层序输出二叉树 即从1到N

代码:
//在完全二叉树里,一个结点i的左儿子坐标必为2*i 右儿子的坐标必为2*i+1


#include<bits/stdc++.h>
using namespace std;
int n;
const int N = 10001; 
int a[N];
int pos[N];
int cnt=1;
bool cmp(int a,int b)
{
	return a<b;
}

void Bulidtree(int index)
{
	if(index*2<=n)Bulidtree(index*2); //遍历左子树 
	pos[index]=a[cnt++]; //遍历节点 
	if(index*2+1<=n)Bulidtree(index*2+1);  //遍历右子树
}
int main()
{
	cin>>n;
	for(int i=1;i<=n;i++)
	cin>>a[i];
	sort(a+1,a+n+1,cmp);
	Bulidtree(1);
	for(int i=1;i<=n;i++)
	{
		if(i!=1)
		cout<<" "<<pos[i];
		else cout<<pos[i];
	}
}

二叉搜索树的建立和查找

结构体:

struct BinaryTree_Node
{
	int key;     // 节点的键。本例中,节点的值部分等于键 。 
	
	BinaryTree_Node* lChild;  // 左子节点 
	BinaryTree_Node* rChild;  // 右子节点 
	
	// 节点的构造函数 
	BinaryTree_Node(int v) : key(v), lChild(NULL), rChild(NULL)
	{
	}BYk
};

typedef BinaryTree_Node* BT_Node;

建立函数:

//二叉搜索树 左小右大

void Create_BinaryTree(BT_Node &node, int key)
{
	if (node == NULL)  // 节点为空,插入之 
	{
		node = new BinaryTree_Node(key);
		return;
	}
	
	if (key < node->key) //比节点的值小,插在左子树
		Create_BinaryTree(node->lChild, key);  // 插入到左子树中 
	
	else	//比节点的值大 插在右子树
		Create_BinaryTree(node->rChild, key);  // 插入到右子树中 
	
	return;
 } 

7-7 建立二叉搜索树并查找父结点 (20 分)

按输入顺序建立二叉搜索树,并搜索某一结点,输出其父结点。

输入格式:

输入有三行: 第一行是n值,表示有n个结点; 第二行有n个整数,分别代表n个结点的数据值; 第三行是x,表示要搜索值为x的结点的父结点。

输出格式:

输出值为x的结点的父结点的值。 若值为x的结点不存在,则输出:It does not exist. 若值为x的结点是根结点,则输出:It doesn’t have parent.

输入样例:

2
20
30
20

输出样例:

It doesn't have parent.

代码:

#include<bits/stdc++.h>
using namespace std;

struct BinaryTree_node
{
	int data;
	BinaryTree_node *lchild;
	BinaryTree_node *rchild;
	
	BinaryTree_node(int key): data(key), lchild(NULL) ,rchild(NULL)
	{
		
	}
};
typedef BinaryTree_node* BT_node;

void Create_BinaryTree(BT_node &node,int data)
{
	//注意这个& &可以取地址,会给改变主函数中root的值 如果不加则不改变 
	if(node==NULL)
	{
		node = new BinaryTree_node(data); //构造函数 创建新节点 
		return; 
	}
	if(data<node->data)
	Create_BinaryTree(node->lchild,data);
	else
	Create_BinaryTree(node->rchild,data);
	
	return ;
}

void search_Root(BT_node parent,BT_node node,int data)// parent 记录父节点  
{
	if(node==NULL)
	{
		cout<<"It does not exist."<<endl;
		return ;
	}
	if(node->data==data)
    {
        cout<<parent->data<<endl;
        return ;
    }
	else if(node->data>data)
		 return search_Root(node,node->lchild,data);
	else 
		return search_Root(node,node->rchild,data);
}


int main()
{
	BT_node root =NULL; //创建根节点 
	int n,data;
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		cin>>data; 
		Create_BinaryTree(root,data);
	}
	int x;
	cin>>x;
	if(root==NULL)  //根节点为空,即根本没有数据 
	{
		cout<<"It does not exist."<<endl;
		return 0;
	}
	if(root->data==x)
	{
		cout<<"It doesn't have parent."<<endl;
		return 0;
	}
	search_Root(NULL,root,x); 
	
	
}

根据中序后序遍历建立二叉树

思路:

1 在中序中找到与后序最后一个值相同的坐标

2 根据那个坐标一分为左右子树,并确定左右子树的后序遍历界限

L2-006 树的遍历 (25 分)

给定一棵二叉树的后序遍历和中序遍历,请你输出其层序遍历的序列。这里假设键值都是互不相等的正整数。

输入格式:

输入第一行给出一个正整数N(≤30),是二叉树中结点的个数。第二行给出其后序遍历序列。第三行给出其中序遍历序列。数字间以空格分隔。

输出格式:

在一行中输出该树的层序遍历的序列。数字间以1个空格分隔,行首尾不得有多余空格。

输入样例:

7
2 3 1 5 7 6 4
1 2 3 4 5 6 7

输出样例:

4 1 6 3 5 7 2

代码:

1 先根据后序遍历和中序遍历建立二叉树

2 使用BFS 层序遍历二叉树

#include<bits/stdc++.h>
using namespace std;
const int N = 10001;
int mid[N];
int final[N];
int n;
struct BitTree
{
	int data;
	BitTree* lchild;
	BitTree* rchild;
};
typedef BitTree* Bit;
Bit Create(int l1,int r1,int l2,int r2)//l1,r1 为中序的界限,l2,r2为后序的界限,自己画一下找坐标填进去
{
	if(l1>r1||l2>r2)
	return NULL;
	Bit root =new BitTree;
	root->data=final[r2];
	root->lchild=NULL;
	root->rchild=NULL;
	int i;
	for(i=0;i<n;i++)
	{
		if(mid[i]==final[r2])break;
	}
	//num 记录根节点的左边有多少个节点 
	int num= i-l1;
	
	root->lchild=Create(l1,i-1,l2,l2+num-1);//注意Create第四个参数必须是l2+num-1;
	root->rchild=Create(i+1,r1,l2+num,r2-1);
	return root;
	
}
void layershow(Bit root)
{
	queue<Bit>que;
	que.push(root);
	cout<<root->data;
	while(que.size())
	{
		Bit node =que.front();
		que.pop();
		if(node->lchild)
		{
			que.push(node->lchild);
			cout<<" "<<node->lchild->data;
		}
		if(node->rchild)
		{
			que.push(node->rchild);
			cout<<" "<<node->rchild->data;
		}
		
	}
}
int main()
{
	
	cin>>n;
	for(int i=0;i<n;i++)
	cin>>final[i];
	for(int i=0;i<n;i++)
	cin>>mid[i];
	Bit root = new BitTree;
	root=Create(0,n-1,0,n-1);
	layershow(root);
	
	
}

根据前序中序 输出后序遍历

#include<bits/stdc++.h>
using namespace std;
const int  N =10001;
int first[N];
int mid[N];
int n;
struct BitTree
{
	int data;
	BitTree* lchild;
	BitTree* rchild;
};
typedef BitTree* Bit;

Bit Create(int l1,int r1,int l2,int r2)
{
	if(l1>r1||l2>r2)
	return NULL;
	Bit root =new BitTree;
	root->data=first[l2];
	root->lchild=NULL;
	root->rchild=NULL;
	int i;
	for(i=0;i<n;i++)
	{
		if(first[l2]==mid[i])break;
	}
	int num=i-l1;
	root->lchild=Create(l1,i-1,l2+1,l2+num);
	root->rchild=Create(i+1,r1,l2+num+1,r2);
	return root;
}
void post(Bit root)
{
	if(root==NULL)return ;
	post(root->lchild);
	post(root->rchild);
	cout<<root->data<<" ";
}
void layershow(Bit root)
{
	queue<Bit>que;
	que.push(root);
	cout<<root->data;
	while(que.size())
	{
		Bit node =que.front();
		que.pop();
		if(node->lchild)
		{
			que.push(node->lchild);
			cout<<" "<<node->lchild->data;
		}
		if(node->rchild)
		{
			que.push(node->rchild);
			cout<<" "<<node->rchild->data;
		}
		
	}
}

int main()
{

	cin>>n;
	for(int i=0;i<n;i++)
	cin>>mid[i];
	for(int i=0;i<n;i++)
	cin>>first[i];
	Bit root = new BitTree;
	root=Create(0,n-1,0,n-1);
	layershow(root);
	cout<<endl;
	post(root);
}

L2-011 玩转二叉树 (25 分)

给定一棵二叉树的中序遍历和前序遍历,请你先将树做个镜面反转,再输出反转后的层序遍历的序列。所谓镜面反转,是指将所有非叶结点的左右孩子对换。这里假设键值都是互不相等的正整数。

输入格式:

输入第一行给出一个正整数N(≤30),是二叉树中结点的个数。第二行给出其中序遍历序列。第三行给出其前序遍历序列。数字间以空格分隔。

输出格式:

在一行中输出该树反转后的层序遍历的序列。数字间以1个空格分隔,行首尾不得有多余空格。

输入样例:

7
1 2 3 4 5 6 7
4 1 3 2 6 5 7

输出样例:

4 6 1 7 5 3 2

反转后的层序遍历,只要把右子树的输出放在左子树前面就好了

代码:

#include<bits/stdc++.h>
using namespace std;
const int  N =10001;
int first[N];
int mid[N];
int n;
struct BitTree
{
	int data;
	BitTree* lchild;
	BitTree* rchild;
};
typedef BitTree* Bit;

Bit Create(int l1,int r1,int l2,int r2)
{
	if(l1>r1||l2>r2)
	return NULL;
	Bit root =new BitTree;
	root->data=first[l2];
	root->lchild=NULL;
	root->rchild=NULL;
	int i;
	for(i=0;i<n;i++)
	{
		if(first[l2]==mid[i])break;
	}
	int num=i-l1;
	root->lchild=Create(l1,i-1,l2+1,l2+num);
	root->rchild=Create(i+1,r1,l2+num+1,r2);
	return root;
}
void post(Bit root)
{
	if(root==NULL)return ;
	post(root->lchild);
	post(root->rchild);
	cout<<root->data<<" ";
}
void layershow(Bit root)
{
	queue<Bit>que;
	que.push(root);
	cout<<root->data;
	while(que.size())
	{
		Bit node =que.front();
		que.pop();
        	if(node->rchild)
		{
			que.push(node->rchild);
			cout<<" "<<node->rchild->data;
		}
		if(node->lchild)
		{
			que.push(node->lchild);
			cout<<" "<<node->lchild->data;
		}
	
		
	}
}

int main()
{

	cin>>n;
	for(int i=0;i<n;i++)
	cin>>mid[i];
	for(int i=0;i<n;i++)
	cin>>first[i];
	Bit root = new BitTree;
	root=Create(0,n-1,0,n-1);
	layershow(root);

	
}

7-23 还原二叉树 (25 分)

给定一棵二叉树的先序遍历序列和中序遍历序列,要求计算该二叉树的高度。

输入格式:

输入首先给出正整数N(≤50),为树中结点总数。下面两行先后给出先序和中序遍历序列,均是长度为N的不包含重复英文字母(区别大小写)的字符串。

输出格式:

输出为一个整数,即该二叉树的高度。

输入样例:

9
ABDFGHIEC
FDHGIBEAC

输出样例:

5

代码:

#include<bits/stdc++.h>
using namespace std;
struct BitTree
{
	char data;
	BitTree* lchild;
	BitTree* rchild;
		
};
typedef BitTree* Bit;
int n;
const int N = 1001;
char pre[N];
char mid[N];

Bit BulidTree(int l1,int r1,int l2,int r2)
{
	if(l1>r1||l2>r2) return NULL;
	Bit root =new BitTree;
	root->data=pre[l2];
	root->lchild=NULL,root->rchild=NULL;
	int i;
	for(i=0;i<n;i++)
	if(pre[l2]==mid[i])break;
	int cnt = i-l1;
	root->lchild=BulidTree(l1,i-1,l2+1,l2+cnt);
	root->rchild=BulidTree(i+1,r1,l2+cnt+1,r2);
	
	return root;
}
int Gethight(Bit root)
{
	if(root==NULL) return 0;
	int l=Gethight(root->lchild);
	int r=Gethight(root->rchild);
	return (l>=r?l:r)+1;
}
int main()
{
	cin>>n;
	getchar();
	for(int i=0;i<n;i++)
	cin>>pre[i];
	getchar();
	for(int i=0;i<n;i++)
	cin>>mid[i];
	Bit root =new BitTree;
	root = BulidTree(0,n-1,0,n-1);
	cout<<Gethight(root);
	
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值