二叉树基本算法
二叉树链式存储
typedef struct BiTNode{
ElemType data;
struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;
二叉树的遍历
先序遍历
void preOrder(BiTree T){
// 递归出口
if(T == NULL) return;
visit(T);
preOrder(T->lchild);
preOrder(T->rchild);
}
中序遍历
void inOrder(BiTree T){
// 递归出口
if(T == NULL) return;
preOrder(T->lchild);
visit(T);
preOrder(T->rchild);
}
后序遍历
void inOrder(BiTree T){
// 递归出口
if(T == NULL) return;
preOrder(T->lchild);
preOrder(T->rchild);
visit(T);
}
层序遍历
void levlOrder(BiTree T){
InitQueue(q); // 初始化队列
BiTree p; // 工作指针
EnQueue(q,T); // 将树根入队
while(p != NULL){
DeQueue(q,p); // 出队访问
visit(p); // 这里可以换成其他操作
// 处理左右子树
if(p->lchild != NULL) EnQueue(p->lchild);
if(p->rchild != NULL) EnQueue(p->rchild);
}
}
非递归先序遍历
void preOrder2(BiTree T){
InitStack(S); // 初始化栈
BiTree p = T; // 工作指针p负责遍历
while(p || ! IsEmpty(s)){ // 栈不空或者工作指针不空
if(p){
visit(p); // 先序位置
Push(S,p); // 访问左子树前先入栈
p = p->lchild; // 访问左子树
} else {
Pop(S,p); // 访问右子树前先出栈
p = p->rchild; // 访问右子树
}
}
}
非递归中序遍历
void inOrder2(BiTree T){
InitStack(S); // 初始化栈
BiTree p = T; // 工作指针p负责遍历
while(p || ! IsEmpty(s)){ // 栈不空或者工作指针不空
if(p){
Push(S,p); // 访问左子树前先入栈
p = p->lchild; // 访问左子树
} else {
Pop(S,p); // 访问右子树前先出栈
visit(p); // 中序位置
p = p->rchild; // 访问右子树
}
}
}
**助记: ** 非递归的先中遍历, 可以将 Push+p->lchild
和 Pop+p->rchild
看成原子操作
非递归后序遍历
void postOrder2(BiTree T){
InitStack(S); // 初始化栈
BiTree p = T; // 工作指针p负责遍历
r = NULL; // 最近访问的结点
while(p || ! IsEmpty(s)){ // 栈不空或者工作指针不空
if(p){
Push(S,p); // 访问左子树前先入栈
p = p->lchild; // 访问左子树
} else {
GetTop(S,p); // 取栈顶结点
if(p->rchild && p->rchild != r){ // 当前结点的右子结点存在且未被访问
p = p->rchild; // 访问右子树
}
// 这个else 相当于递归版本里的后序位置
else { // 右子结点不存在或已被访问
Pop(S,p);
visit(p); // 后序位置
r = p; // 记录最近访问过的结点
p = NULL;
}
}
}
}
线索二叉树
typedef struct ThreadNode{
ElemType data; // 数据元素
struct ThreadNode *lchild,*rchild; // 左右孩子指针
int ltag,rtag; // 左右线索标志
}
构造中序线索二叉树
void InThread(ThreadTree &p,ThreadTree &pre){
if(p == NULL) return;
InTread(p->lchild,pre); // 线索化左子树
if(p->lchild == NULL){ // 左子树为空,建立前驱线索
p->lchild = pre;
p->ltag = 1;
}
if(pre != NULL && pre->rchild == NULL){
pre->rchild = p; // 建立前驱节点的后继线索
pre->tag = 1;
}
pre = p;
InThread(p->rchild,pre); // 线索化右子树
}