二叉树的性质和存储结构
1.第i层上有2的i-1次方个节点
2.深度为k的二叉树最多有2的k次方-1个节点(满二叉树)
最少有k个节点
3.对任意一个二叉树t,叶子数n,度为2的节点数m,则n=m+1
4.深度为k的
完全二叉树
序号与二叉树一一对应
1.对任意节点,右子树最大层次为i,左子树最大层次为i或i+1
2.叶子只能分布在最大的两层上
3.具有n个节点的完全二叉树深度为【log2的n】+1,不超过log2的n的最大整数
4.编号为i(i!=1)的双亲节点是【i/2】,左孩子是2i,右孩子是2i+1
【】代表不超过x的最大整数
二叉树的顺序存储,从上到下从左到右放进数组里
非完全二叉树按完全二叉树存储,其他地方补0
链式存储
typedef struct binode
{
int data;
struct binode *lchild,*rchild;
}binode,*bitree
n个结点的二叉链表中,有2n-(n-1)=n+1个指针域
三叉链表
typedef struct tnode
{
int data;
struct binode *lchild,*rchild,*parent;
}tnode,*ttree
二叉树的遍历
先序,中序,后序
若二叉树所有节点值不同,则序列唯一
先序+中序或者后序加中序可以确定一颗二叉树;
先序加中序:先序的第一个字母确定根,中序根的左边都在左,右边都在右
先序判断根,中序判断左右!!!!!
后序最后是根,跟先序倒过来
见数据结构王卓第7周12
算法
先序遍历算法**(递归)**
int preorder(bitree t)//指向
{
if(t==NULL)
{
return ;
}
else
cout<<t->data;//可以有不同操作
preorder(t->lchild);
preorder(t->rchild);
}
中序遍历
int inorder(biree t)
{
if(t==NULL)
{
return 0;
}
else
{
inorder(t->lchild);
cout<<t->data;
inorder(t->rchild);
}
}
后序遍历
int postorder(bitree t)
{
if(t==NULL)
{
return 0;
}
else
{
postorder(t->lchild);
postorder(t->rchild);
cout<<t->data;
}
}
每个节点遍历三次
第一次经过时输出:先序
二:中序
三:后续
时间效率:o(n)
空间效率:o(n)
非递归
基本思想:
1.建立一个栈
2.根节点进栈,访问左子树
3.根节点出栈,输出根节点,访问右子树
void in(bitree root)
{
if(t==NULL)
{
return;
}
bitree p=root;
stack<bitree>s;
while(p||s.empty())
{
if(p)
{
s.push(p);
p=p->lchild;
}
else
{
p=s.top();
s.pop();
cout<<p->data;
p=p->rchild;
}
}
}
二叉树的层级遍历
#include<iostream>
using namespace std;
typedef struct node//创建二叉链
{
int data;
struct node *lchild;
struct node *rchild;
}btnode;
typedef struct queue
{
int front;
int rear;
btnode *data[1000];
}sqqueue;
void initqueue(sqqueue*& q); // 初始化对立
bool emptyqueue(sqqueue*& q); // 判断队列空
bool enqueue(sqqueue*& q, btNode*& bt); // 入队
bool dequeue(sqqueue*& q, btNode*& bt); // 出队
int main()
{
return 0;
}
void initqueue(sqqueue*& q)
{
q=new squeue;
q->rear=q->front=0;
}
bool emptyqueue(sqqueue*& q)
{
if(q->front==q->rear)
{
return true;
}
else
{
return false
}
}
bool enqueue(sqqueue*& q, btNode*& bt)
{
if(q->rear==1000-1)
return false;
else
{
q->rear+1;
q->data[q->rear]=bt;
return true;
}
}
bool dequeue(sqqueue*& q, btNode*& bt)
{
if(q->front==q->rear)
{
return false;
}
else
{
bt=q->data[q->front];
q->front++;
}
}
void levelorder(btNode*& bt)
{
sqqueue *q;
initqueue(q);
if(bt)
{
enqueue(q,bt);
}
while(!emptyqueue(q))
{
dequeue(bt);
cout<<bt->data<<endl;
if(bt->lchild!=NULL)
{
enqueue(bt->lchild);
}
if(bt->rchild!=NULL)
{
enqueue(bt->rchild);
}
}
}
线索二叉树
增加两个指针域,ltag,rtag
tag=0指向孩子,=1指向前后继
树的存储结构(不是二叉树)
第八周09
1、双亲表示法:二维数组,一个表示本身信息,另外一个表示其双亲的位置(找双亲容易,找孩子难)
typedef struct ptnode
{
int data;
int parent;
}ptnode;
typedef struct
{
ptnode nodes[100];
int r,n;//根节点的位置和节点个数
}pttree;
2、孩子链表(找孩子容易,找双亲难)
typedef struct ctnode//孩子节点结构
{
int child;
struct ctnode *next;
}*childptr;
typedef struct
{
int data;
int parent;//带双亲的孩子链表
child ptr;//孩子链表头节点
}ctbox;
typedef struct
{
ctbox nodes[100];
int n,r;//定义节点数和根节点的位置
}
3.孩子兄弟表示法(找双亲难,可以再增加一个指针域)
typedef struct csnode
{
int data;
struct csnode *child,*brother;
}csnode *cstree;
树与二叉树的转换
树转换成二叉树
1.兄弟之间加一根线
2.只保留双亲和第一个孩子之间的关系
口诀:兄弟相连留长子
二叉树转换成树
1.找到所有右孩子和双亲连线
2.去掉原来的右孩子线
左孩右右连双亲,去掉原来右孩线
森林转换成二叉树
每棵树变二叉根相连,转45度
二叉树转换成森林
1.根节点与其右孩子的连线全部抹掉
2.剩余的数全部转成树
树和森林的遍历
回顾:二叉树4种遍历方式
先序中序,后续,层次
数的遍历:三种:先序,后续,层次
森林的遍历:
(先序(先根)和中序(后根))
1.第一棵树的根节点,第一棵树的子树森林;
2.其他书构成的森林