4.1什么是树&二叉树
该树的每个结点至多只有两颗子树
特殊的二叉树
1.满二叉树
2.完全二叉树
注:判断二叉树是否为完全二叉树https://blog.csdn.net/lin1094201572/article/details/86083106
4.2二叉树的存储
1.顺序存储结构
2.链式存储机构
4.3.1二叉树的遍历
根节点的访问顺序是先还是中还是后决定先,中,后序访问
1.先序遍历(PreOrder):
void preOrder(BinaryTree T){
if(T!=NULL){
visit(T);
preOrder(T->lchild);
preOrder(T->rchild);
}
}
2.中序遍历(InOrder)
递归算法:
void inOrder(BinaryTree T){
if(T!=NULL){
inOrder(T->lchild);
visit(T);
inOrder(T->rchild);
}
}
非递归算法:
1.利用栈
void inOrder_no_recursion(BinaryTree T){
initStack(S);BinaryTree p=T;
while(p||!isEmpty(S)){
if(p){
Put(S,p);
p=p->lchild;
}else{
Pop(S,p);
p=p->rchild;
}
}
}
3.后序遍历(PostOrder)
void postOrder(BinaryTree T){
if(T!=NULL){
postOrder(T->lchild);
postOrder(T-rchild);
visit(T);
}
}
已知(先或后)+中序可唯一确定一棵二叉树。
时间复杂度分析和空间复杂度
1.三种遍历都访问每个结点故遍历时间复杂度为O(n)
2.递归所需最多的栈个数由二叉树的深度h决定,最坏情况为全为度为1的单支结点深度为n则空间复杂度为O(n).
4.层次遍历(LevelOrder)
1.利用队列
1)队列中首先加入根结点, 队中A
2)队列出队得得队首元素,访问出队元素
3)将出队元素的左右子结点加入队列,
循环2)3)
队中:A–null–BC–CEF–EF–F--null
void levelOrder(BinaryTree T){
initQueue(Q);
BinaryTree p=T;EnQueue(S,p);
while(p){
DeQueue(S,p);visit(p);
if(p->lchild!=NULL) EnQueue(S,p->lchild);
if(p->rchild!=NULL) EnQueue(S,p->rchild);
}
}
4.3.2 线索二叉树
将链式存储的二叉树的空指针利用,一个结点添加两个个标签域。分别为ltag,rtag.
将空白指针指向前驱或后继,左空指向前驱,有空指向后继,称为线索。
前驱,后继由当前线索数的顺序(先,中,后序)决定。
将二叉树以某种次序线索化后得到线索二叉树
ltag为0指向左儿子结点,为1指向该前驱。
rtag为0指向右儿子结点,为1指向该后继。
该线索二叉树结构体如下:
typedef struct struct_ThreadNode{
ElemType elem;
struct struct_ThreadNode *lchild,*rchild;
int ltag,rtag;
}ThreadNode ,*ThreadTree;
Demo of the algorithm of InOrder-ThreadTree :
void in_Thread(ThreadTree &p,ThreadTree &pre){//p,pre需修改结点故引用,引用为c++中添加特性
if(p!=NULL){
//递归线索化左子树
//将当前结点的左右若空线索化,左空前驱(中序前驱为pre),右空后继(中序,后继为根结点p)。
pre = p;//线索化后前驱结点变换为当前根结点。
//递归线索化右子树
}
}
The code of sort InOrder-ThreadTree by InOrder:
void inorder_ThreadTree(ThreadTree T){
for(ThradNode *p=FirstNode(T);p!=NULL;p=NextNode(T)) visit(p);
}