1树的基本概念
1.1意义
树(Tree)是 n(n>=0) 个结点的有限集。n=0时称为空树。在任意一棵非空树中:
(1)有且仅有一个特定的称为 根(root) 的结点。
(2)当n>1时,其余结点可分为m(m>0)个互不相交的有限集T1,T2,…,Tm, 其中每一个集合本身又是一棵树,并且称为根的子树(SubTree)
1.2的构成
1.2.1节点
1.2.2度
节点的度数:节点孩子的个数
树的度:树中节点的度最大值。
1.2.3 层次
层次:从根开始定义起,根为第1层,根的子节点为第2层,以此类推;
1.2.4深度与高度
类别 | 说明 |
---|---|
节点的高度 | 节点到最远叶子节点的最长路径上边的数量。叶子节点高度为0。 |
节点的深度 | 节点到根节点的路径上边的数量。所有根节点深度为0。 |
树的高度 | 树的高度等于根节点的高度,等于最远叶子节点的深度。 |
树的深度 | 树的深度等于树的高度。 |
树的宽度 | 两个最长路径的叶子节点之间节点数 |
1.3树的分类
树按照子节点的数量分为二叉树和多叉树。
类别 | 说明 |
---|---|
二叉树 | 是n(n>=0)个结点的有限集合,该集合或者为空集(称为空二叉树),每个节点最多有2个子节点,分别称为根结点的左子树和右子树。 |
多叉树 | 是n(n>=0)个结点的有限集合,该集合或者为空集(称为空树)。每个节点有多个子节点 |
1.3.1多叉树
1.3.2 二叉树
特点
1:二叉树中每个结点最多有两颗子树,度没有超过2的。
2:左子树和右子树是有顺序的,不能颠倒。
树按照子树是否有序分为有序树和无序树。
类别 | 说明 |
---|---|
有序树 | 节点各子树从左到右有次序(不能互换)。 |
无序树 | 节点各子树从左到右无次序(能互换)。 |
1.3.3特殊的二叉树
斜树
满二叉树
满二叉树(Full Binary Tree):二叉树中的每个结点恰好有两个孩子结点且所有叶子结点都在同一层
完全二叉树
完全二叉树(Complete Binary Tree): 每层结点都完全填满,在最后一层上如果不是满的,则只缺少右边的若干结点。
1.4 二叉树的性质
1.4.1 通用性质
- 在非空二叉树上,第i层至多有2^{i-1} 个结点。
- 深度为k的二叉树至多有2^k-1个结点;
- 对任何一个二叉树,若其叶子结点数为n0,度为2的节点数为n2,则n0=n2+1;
1.4.2 满二叉树的性质
深度为k的满二叉树且有2^k-1个结点。
1.4.3 完全二叉树的性质
1. n个结点的完全二叉树的深度k=[log2 n]+1**,这里这个符号[x]表示小于等于x的整数;
2. 若对一棵有n个结点的完全二叉树(深度为[log2 n]+1)的结点按层(从第1层到第[log2 n]+1层)序自左至右进行编号,则对于编号为i(1≦i≦n)的结点:
1. 如果i=1,则结点i是二叉树的根,无双亲结点;如果i>1,则其双亲结点编号是[i/2]
2. 如果2i>n:则结点i为叶子结点,无左孩子;否则,其左孩子结点编号是2i。
3. 如果2i+1>n:则结点i无右孩子;否则,其右孩子结点编号是2i+1。
2树的表示法
2.1多叉树表示法
2.1.1 双亲表示法
struct Node{
char data;
int parent;
};
Node nodes[n];
2.1.2 孩子表示法
struct Node{
char data;
vector<int> children;
};
Node nodes[n];
优化 2.1.3双亲孩子表示法
struct Node{
char data;
vector<int> children;
};
Node nodes[n];
2.1.3孩子兄弟表示法
孩子兄弟表示法主要用来把多叉树转化成二叉树。
struct Node{
char data;
int firstchild;
int rightsib;
};
Node nodes[n];
2.2二叉树表示法
2.2.1 顺序存储方式
一棵深度为k的二叉树通常需要 2^k-1 个节点空间存储。
通常使用0表示空节点
2.2.2 链式存储方式
//孩子表示法
struct Node{
char data;
struct Node* right_child;
struct Node*left_child;
};
//孩子双亲表示法
struct Node{
char data;
struct Node* right_child;
struct Node* left_child;
struct Node* parent;
};
3多叉树遍历
3.1深度优先遍历
先序遍历
A → B → D → G → H → I → C → E → J → F
后序遍历
G → H → I → D → B → J → E → F → C → A
3.2 广度优先遍历(层次遍历)
A → B → C → D → E → F → G → H → I → J
4二叉树遍历
4.1 深度优先遍历
前序遍历结果:A → B → D → E → C → F → G
后序遍历结果:D → E → B → F → G → C → A
中序遍历结果:D → B → E → A → F → C → G
4.2 广度优先遍历
遍历结果:A → B → C → D → E → F → G
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
typedef char datatype;
typedef struct Node
{
datatype data;
struct Node *lchild;
struct Node *rchild;
}N, *BiTree;
typedef struct
{
BiTree da[1000];
int top;
}SeqStack;
SeqStack *InitStack()
{
SeqStack *s;
s = (SeqStack *)malloc(sizeof(SeqStack));
s->top = -1;
return s;
}
typedef struct wnode{
N *data;
struct wnode *next;
}S;
typedef struct snode{
S *front;
S *rear;
}Q;
Q *Init_LQueue(){
Q *q;
S *p;
q=(Q *)malloc(sizeof(Q));
p=(S *)malloc(sizeof(S));
p->next=NULL;
q->front=q->rear=p;
return q;
}
void InLQueue(Q *q,BiTree root){
S *p=(S *)malloc(sizeof(S));
p->data=root;
p->next=NULL;
q->rear->next=p;
q->rear=p;
}
int Empty_LQueue(Q *q){
if(q->front==q->rear) return 0;
else return 1;
}
void Out_LQueue(Q *q,BiTree *root){
S *p;
p=q->front->next;
q->front->next=p->next;
(*root)=p->data;
free(p);
if(q->front->next==NULL){
q->rear=q->front;
}
}
//判断栈是否为空
int IsEmpty(SeqStack *s)
{
if(s->top == -1)
return 1;
else
return 0;
}
void push(SeqStack *s, BiTree root)
{
BiTree p;
p = root;
if(s->top == 999)
return;
else {
s->top++;
s->da[s->top]=p;
}
}
void pop(SeqStack *s, BiTree *root)
{
BiTree p;
p = *root;
if(IsEmpty(s))
return;
else {
*root = s-> da[s->top];
s->top--;
}
}
void creat(BiTree *root){
char ch;
ch=getchar();
if(ch=='#'){
*root=NULL;
}
else{
*root=(N *)malloc(sizeof(N));
(*root)->data=ch;
creat(&((*root)->lchild));
creat(&((*root)->rchild));
}
}
//非递归先序
void PreOrder1(BiTree root)
{
SeqStack *s;
BiTree p;
s=InitStack();
p = root;
while(p != NULL || !IsEmpty(s)) {
while(p != NULL) {
printf("%c", p->data);
push(s,p);
p = p -> lchild;
}
if(!IsEmpty(s)) {
pop(s,&p);
p = p -> rchild;
}
}
}
//非递归中序
void InOrder(BiTree root){
SeqStack *s;
BiTree p;
s=InitStack();
p=root;
while(p!=NULL||!IsEmpty(s)){
if(p!=NULL){
push(s,p);
p=p->lchild;
}
else{
pop(s,&p);
Visit(p->data);
p=p->rchild;
}
}
}
//非递归后序
void PostOrder(BiTree root){
SeqStack *s;
BiTree p,q;
q=NULL;
s=InitStack();
p=root;
while(p!=NULL||!IsEmpty(s)){
while(p!=NULL){
push(s,p);
p=p->lchild;
}
if(!IsEmpty(s)){
Top(s,&p);
if((p->rchild==NULL)||(p->rchild==q)){
pop(s,&p);
Visit(p->data);
q=p;
p=NULL;
}
else{
p=p->rchild;
}
}
}
}
//层次遍历
void Levelorder(BiTree root){
Q *q;
BiTree p;
q=Init_LQueue();
InLQueue(q,root);
while(Empty_LQueue(q)){
Out_LQueue(q,&p);
printf("%c",p->data);
if(p->lchild!=NULL){
InLQueue(q,p->lchild);
}
if(p->rchild!=NULL){
InLQueue(q,p->rchild);
}
}
}
//结点所在层次
void TreeDepth(N *root,int h){
if(root){
printf("(%c,%d)",root->data,h);
TreeDepth(root->lchild,h+1);
TreeDepth(root->rchild,h+1);
}
}
//交换左右子树
void PerOrder0(N *root){
if(root){
//Visit(root->data);
N *p;
p=(N *)malloc(sizeof(N));
p=root->rchild;
root->rchild=root->lchild;
root->lchild=p;
PerOrder0(root->lchild);
PerOrder0(root->rchild);
}
}
//根节点到叶子节点路径
char arr[1000];
void TreeDepth(N *root,int h){
if(root){
//printf("(%c,%d)",root->data,h);
arr[h]=root->data;
int i=0;
if((root->lchild==NULL)&&(root->rchild==NULL)){
printf("%c:",root->data);
for(i=1;i<h;i++){
printf("%c",arr[i]);
}
cout1--;
if(cout1!=0){
printf("\n");}
}
TreeDepth(root->lchild,h+1);
TreeDepth(root->rchild,h+1);
}
}
//根据先序中序遍历序列来创建2茶树
int Lchild_len(char insequence[50],char root_data) //得到左孩子的长度
{
int len=strlen(insequence);
int i=0;
int sum=0; //记录左孩子长度
while(insequence[i]!=root_data)
{
i++;
sum++;
}
return sum;
}
int Rchild_len(char insequence[50],char root_data) //得到右孩子的长度
{
int i=0;
int sum=0; //记录右孩子长度
while(insequence[i]!='\0'&&insequence[i++]!=root_data);
while(insequence[i]!='\0')
{
sum++;
i++;
}
return sum;
}
tree* create_tree(char presequence[50],char insequence[50]) //创建二叉树
{
tree* temp=(tree*)malloc(sizeof(tree)); //创建结点
int L_len,R_len; //储存左右孩子长度
char L_presequence[50],L_insequece[50]; //创建左孩子时传入的左孩子的前序串和中序串
char R_presequence[50],R_insequece[50]; //创建右孩子时传入的右孩子的前序串和中序串
L_presequence[0]=L_insequece[0]=R_presequence[0]=R_insequece[0]='\0';
if(strlen(presequence)!=0&&strlen(insequence)!=0) //传入的序列串非空
{
temp->data=presequence[0]; //根结点数据赋值
L_len=Lchild_len(insequence,presequence[0]); //根据中序来获得孩子的长度
R_len=Rchild_len(insequence,presequence[0]);
strncpy(L_presequence,presequence+1,L_len); //得到要递归创建孩子时要传入的前序遍历串和中序遍历串
*(L_presequence+L_len)='\0'; //字符串末尾加上'\0'
strncpy(R_presequence,presequence+L_len+1,R_len);
*(R_presequence+R_len)='\0';
strncpy(L_insequece,insequence,L_len);
*(L_insequece+L_len)='\0';
strncpy(R_insequece,insequence+L_len+1,R_len);
*(R_insequece+R_len)='\0';
temp->Lchild=create_tree(L_presequence,L_insequece); //递归创建左子树
temp->Rchild=create_tree(R_presequence,R_insequece); //递归创建右子树
return temp; //返回结点地址
}
return NULL;
}
//求2叉树中某结点的双亲
BiTree parent(BiTree root,BiTree c){
BiTree *p;
if(root==NULL) return NULL;
if(root->lchild==c||root->rchild=c){
return root;
}
p=parent(root->rchild,c);
if(p!=NULL){
return p;
}
else{
return (parent(root->rchild,c));
}
}
int main(){
N *root;
creat(&root);
PerOrder(root);
printf("\n");
PerOrder1(root);
printf("\n");
PerOrder2(root);
printf("\n");
return 0;
}