二叉树

  • 树是一种数据结构,再介绍二叉树之前,先解释一下什么是树;

1.树由 根结点 开始,它从 根结点 一直延申到 叶结点结束,根结点 与 叶结点之间的结点统称为 内部结点
2.树的每一个结点上都可以存储数据,同时存储着下一个 子节点 的地址,因此 树 可以看作是由一个根结点起始的 多条多向链表
3.从图的概念来看,树也可以看作是 不包含回路的连通无向图

有关树的基础概念:
根节点:一棵树只有一个根结点,不过也存在没有根结点的树,这种树称为空树
叶节点:树的末尾结点,叶结点的下一级不会再有结点,即 叶结点指向 空;
内部节点:根结点与叶结点之间的所有结点;
:连通两个结点的路径称为 边;一棵树的 边数=结点数-1
子节点,父节点,兄弟结点,祖宗结点:即字面意思,不解释;
树的层次:即树从根结点至叶结点最大有多少层;
结点的度:结点的子树棵数成为 结点的度;
树的度:也叫树的宽度,它从所有 结点的度中 挑选最大的作为 树的度;
森林:多棵树组合在一起成为森林;

【注意】对于任意一个结点,它自己既是自己的祖宗结点,也是自己的子孙结点;

  • 二叉树

二叉树是 树里面应用非常广泛的一种 特殊树的结构;
对 二叉树的定义:二叉树的每一个结点至多有两个子结点;言外之意即 二叉树也可以是一颗空树

满二叉树:树的每层的结点个数都达到了当层能达到的最大值;

完全二叉树:除最下面一层外,其它各层都达到了当层能达到的结点最大值,且对于最下面一层,只有从左至右存在若干连续结点,而它的右边无结点;

故满二叉树包含在完全二叉树之内;
堆也是一种特殊的完全二叉树;

  • 有关二叉树的基本操作

(1)利用链表的方式定义二叉树

struct node{
    int data;
    node *lchild;//指向左子树结点的指针
    node *rchild;//指向右子树结点的指针
}

(1’’)利用动态数组的方式定义二叉树

struct node{
    int data;
    int lchild;
    int rchild;
}Node[maxn];

(2)新建结点

node *newnode(int x)
{
    node *root=new node;
    root->data=x;
    root->lchild=root->rchild=NULL;
    return root;//建立了一个左右子结点暂时指向空的新结点,且该结点的数据域为x;
}

(2’’)静态实现新建结点

int index=0;
node *newnode(x)
{
    Node[index].data=x;
    Node[index].lchild=Node[index].rchild=-1;//-1用来表示NULL;
    return index++;//返回下标,并自加;
}

(3)查找,修改结点

void search(node *root,int x,int data)
{
    if(root==NULL)
        return;//递归边界
    if(root->data==x)
        root->data=data;//实现修改
    search(root->lchild,x,data);
    search(root->lchild,x,data);//递归
}

(3’’) 静态实现查找,修改结点

void search(node *root,int x,int data)
{
    if(root==-1)
        return;
    if(Node[root].data==x)
        Node[root].data=data;
    search(Node[root].lchild,x,data);
    search(Node[root].rchild,x,data);
}

可以看出 用链表实现与静态实现差别不大,下面的代码中将省略静态实现

(4)插入结点

void insert(node *&root,int x)//这里需要对root用引用,因为涉及到对二叉树结构的修改
{
    if(root=NULL){  //找到插入位置
        root=newnode(x);//新建结点
        return;
    }
    if()//根据需要选择插入左子树还是右子树
        insert(root->lchild,x);
    else
        insert(root->rchild,x);
}

(5)创建二叉树

node *create(int data[],int n)
{
    node *root=NULL;
    for(int i=0;i<n;i++)
    {
        insert(root,data[i]);
    }
    return root;
}
  • 二叉树的遍历

二叉树的遍历有四种遍历方法,分别是 先序遍历,中序遍历,后序遍历以及层序遍历;其中前三种遍历方法一般用DFS实现,层序遍历一般用BFS实现;
另外注意,这里的先序,中序,以及后序都是相对于根结点来说的,遍历过程中左子树的遍历始终在右子树之前,只是根结点的遍历顺序进行了更改;

先序遍历:

void preorder(node *root)
{
    if(node==NULL)
        return;
    cout<<root->data;
    preorder(root->lchild);
    preorder(root->rchild);
}

中序遍历:

void inorder(node *root)
{
    if(node==NULL)
        return;
    preorder(root->lchild);
    cout<<root->data;
    preorder(root->rchild);
}

后序遍历:

void postorder(node *root)
{
    if(node==NULL)
        return;
    preorder(root->lchild);
    preorder(root->rchild);
    cout<<root->data;
}

注意 cout<data; 语句的顺序;

层序遍历:

void C_order(node *root)
{
    queue<node *> q;
    q.push(root);
    while(!q.empty())
    {
        node *now=q.front();
        q.pop();
        cout<<now->data;
        if(now->lchild!=NULL) q.push(root->lchild);
        if(now->rchild!=NULL) q.push(root->rchild);
    }
}
  • 利用遍历序列构建二叉树

通过遍历序列,我们可以还原二叉树;
我们只需要两种方式的序列数据即可还原,但这两种遍历方法中必须要有一个为中序遍历

一个例子,利用 后序遍历和中序遍历的数据还原二叉树,并在之后输出它的 层序遍历数据:

#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
const int maxn=50;
struct node{
    	int data;
    	node *lchild;
    	node *rchild;
};
int n;
int pre[maxn],in[maxn],post[maxn];
node *create(int postL,int postR,int inL,int inR)
{
	if(postL>postR)
		return NULL;
	node *root=new node;
	root->data=post[postR];
	int k;
	for(k=inL;k<=inR;k++)
	{
		if(in[k]==post[postR])
			break;
	}
	int numLeft=k-inL;
	root->lchild=create(postL,postL+numLeft-1,inL,k-1);
	root->rchild=create(postL+numLeft,postR-1,k+1,inR);
	return root;
}
int num=0;
void bfs(node *root)
{
	queue<node *> q;
	q.push(root);
	while(!q.empty())
	{
		node *now=q.front();
		q.pop();
		cout<<now->data;
		num++;
		if(num<n) cout<<" ";
		if(now->lchild!=NULL) q.push(now->lchild);
		if(now->rchild!=NULL) q.push(now->rchild);
	}
}
int main()
{
	cin>>n;
	for(int i=0;i<n;i++)
	{
		cin>>post[i];
	}
	for(int i=0;i<n;i++)
	{
		cin>>in[i];
	}
	node *root=create(0,n-1,0,n-1);
	bfs(root);
	return 0;
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值