5.3 二叉树的遍历和线索二叉树
5.3.03
编写后序遍历二叉树的非递归算法
思路:1. 将元素沿着左孩子依次入栈;2.读栈顶,如果右孩子不空且未被访问过,则将右子树执行1,否则出栈并访问
void PostOrder(BiTree T)
{
InitStack(S);
p = T;
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{
pop(S,p);
visit(p->data);
r = p;
p = NULL;
}
}//end else
}// end while
}
5.3.04
二叉树的自下而上、从右到左的层次遍历算法
void InvertLevel(BiTree bt){
Stack s; Queue Q;
if(bt != NULL){
InitStack(s);
InitQueue(Q);
EnQueue(Q,bt);
while(IsEmpty(Q) == false){
DeQueue(Q,p);
Push(s,p);
if(p->lchild)
EnQueue(Q,p->lchild);
if(p->rchild)
EnQueue(Q,p->rchild);
}// end while
while(IsEmpty(s) == false){
Pop(s,p);
visit(p->data);
}
}// end if
}
5.3.05
假设二叉树采用二叉链表存储结构,设计一个非递归算法求二叉树的高度。
int Btdepth(BiTree T)
{
if(!T) return 0;
int front = -1, rear = -1;
int last = 0, level = 0;
BiTree Q[MaxSize];
Q[++rear] = T;
BiTree p;
while(front<rear){
p = Q[++front];
if(p->lchild) Q[++rear] = p->lchild;
if(p->rchild) Q[++rear] = p->rchild;
if(front == last){
level++;
last = rear;
}
}//end while
return level;
}
//递归法
int Btdepth2(BiTree T){
if(T==NULL) return 0;
ldep = Btdepth2(T->lchild);
rdep = Btdepth2(T->rchild);
if(ldep>rdep) return ldep+1;
else return rdep+1;
}
5.3.06
设一棵二叉树中各结点的值不同,其先序遍历序列和中序遍历序列分别存于两个一维数组A[1…n]和B[1…n]中,建立二叉链表
这道题思路很难啊,想不出来力TT
BiTree PreInCreat(ElemType A[], ElemType B[], int l1, int h1, int l2, int h2){
//l1,h1为先序的第一和最后一个节点下标,l2,h2为中序的第一和最后一个下标
root = (BiTNode *) malloc (sizeof(BiTNode));
root->data = A[l1];
for(i = l2; B[i]!=root->data;i++);
llen = i-l2;
rlen = h2-i;
if(llen) root->lchild = PreInCreat(A,B,l1+1,l1+llen,l2,l2+llen-1);
else root->lchild = NULL;
if(rlen) root->rchild = PreInCreat(A,B,h1-rlen+1,h1,h2-rlen+1,h2);
else root->rchild = NULL;
return root;
}
5.3.07
二叉树按二叉链表形式存储,判断是否是完全二叉树
我也不会,看的答案。建立队列之后先让父节点进去,然后抽出父节点让子节点进去,没有就
bool IsComplete(BiTree T)
{
InitQueue(Q);
if(!T) return 1;
EnQueue(Q,T);
while(!IsEmpty(Q)){
DeQueue(Q,p);
if(p){
EnQueue(Q,p->lchild);
EnQueue(Q,p->rchild);
}
else
while(!IsEmpty(Q)){
DeQueue(Q,p);
if(p) return 0;
}
}//end while
return 1;
}
5.3.08
假设二叉树采用二叉链表存储结构存储,计算二叉树所有双分支节点个数。
int cntdl(BiTree b){
if(b == NULL) return 0;
else if(b->lchild != NULL && b->rchild != NULL)
return cntdl(b->lchild)+cntdl(b->rchild)+1;
else return cntdl(b->child)+cntdl(b->rchild);
}
5.3.09
左节点和右节点交换一哈
void swap(BiTree b)
{
if(b){
swap(b->lchild);
swap(b->rchild);
temp = b->lchild;
b->lchild = b->rchild;
b->rchild = temp;
}
}
5.3.12
在二叉树中寻找值为x的结点,试编写算法打印值为x的结点的所有祖先,假设值为x的结点不多于一个
typedef struct{
BiTree t;
int tag; //tag=0表示左子女被访问,tag=1表示右子女被访问
}stack;
void Search(BiTree bt, ElemType x)
{
stack s[];
top = 0;
while(bt!=NULL||top>0){
while(bt!=NULL && bt->data != x){
s[++top].t = bt;
s[top].tag = 0;
bt = bt->lchild;//沿着左分支往下
}
if(bt!=NULL && bt->data == x){
printf("所有节点值为:\n");
for(i=1;i<=top;i++)
printf("%d ",s[i].t->data);
exit(1);
}
while(top != 0 && s[top].tag == 1) top--;
if(top != 0){
s[top].tag = 1;
bt = s[top].t->rchild;
}
}// end while
}
5.3.13
设一棵二叉树的结点结构为(LLINK,INFO,RLINK),ROOT为指向该二叉树根节点的指针,p和q分别为指向该二叉树中任意两个结点的指针,试编写算法ANCESTER(ROOT,p,q,r),找到p和q的最近公共祖先结点r
思路完全一样啊TT
typedef struct{
BiTree t;
int tag; //tag=0表示左子女被访问,tag=1表示右子女被访问
}stack;
stack s[],s1[];
BiTree ANCESTER(BiTree ROOT,BiNode *p, BiNode *q))
{
top = 0; bt = ROOT;
while(bt!=NULL||top>0){
while(bt!=NULL && bt->data != x){
s[++top].t = bt;
s[top].tag = 0;
bt = bt->lchild;//沿着左分支往下
}
while(top != 0 && s[top].tag == 1){
if(s[top].t == p){
for(i = 1;i <= top;i++)
s1[i] = s[i];
top1 = top;
}
if(s[top].t == q)
for(i = top; i>0; i--){
for(j = top1; j>0; j--)
if(s1[j].t == s[i].t) return s[i].t;
}
top--;
}// end while
if(top! = 0){
s[top].tag = 0;
bt = s[top].t->rchild;
}
}//end while
return NULL;//找不到
}
5.3.15
设有一棵满二叉树(所有节点值均不同),已知其先序序列为pre,设计一个算法求其后续序列post
void PreToPost(ElemType pre[], int l1, int h1, ElemType post[], int l2, int h2)
{
int half;
if(h1>l1){
post[h2] = pre[l1];
half = (h1-l1)/2;//满二叉树
PreToPost(pre,l1+1,l1+half,post,l2,l2+half-1);
PreToPost(pre,l1+half+1,h1,post,l2+half,l2-1);
}
}
5.3.16
设计一个算法将二叉树的叶结点按从左到右的顺序连成一个单链表,表头指针为head,二叉树按二叉链表方式存储,连接时用叶节点的右指针域来存放单链表指针。
LinkedList head, pre = NULL;
LinkedList InOrder(BiTree bt)
{
if(bt){
InOrder(bt->lchild);
if(bt->lchild == NULL && bt->rchild == NULL)
if(pre == NULL){
head = bt;
pre = bt;
}
else{
pre->rchild = bt;
pre = bt;
}
InOrder(bt->rchild);
pre->rchild = NULL;
}
return head;
}
5.3.17
试设计判断两棵二叉树是否相似的算法(指是否是空二叉树或只有一个根节点,或T1的左子树和T2的左子树是相似的)
int similar(BiTree T1, BiTree T2)
{
int leftS,rightS;
if(T1 == NULL && T2 == NULL)
return 1;
else if(T1 == NULL || T2 == NULL)
return 0;
else{
leftS = similar(T1->lchild, T2->lchild);
rightS = similar(T1->rchild, T2->rchild);
return leftS&&rightS;
}
return -1;
}
5.3.18
写出在中序线索二叉树里查找指定节点在后序的前驱结点的算法
BiThrTree InPostPre(BiThrTree t, BiThrTree p)
{
BiThrTree q;
if(p->rtag == 0) p = q->rchild; //p有右子女,右子女是其后序前驱
else if(p->ltag == 0) q = p->lchild; //p只有左子女,左子女是其后序前驱
else if(p->lchild == NULL) q = NULL;//都没有,没有前驱
else {//p祖先的左子女
while(p->ltag == 1 && p->lchild !=NULL) p = p->child;
if(p->ltag == 0) q = p->lchild;
else q = NULL;
}
return q;
}
5.3.19
二叉树的带权路径长度(WPL)是二叉树中所有叶结点的带权路径长度之和,给定一棵二叉树T,采用二叉链表存储,结点结构为left,weight,right。其中叶结点的weight域存放该结点的非负权值。设root为指向T的根节点的指针,请设计求T的WPL的算法。
带权路径长度=叶子结点深度与其指定权重的乘积总和。
typedef struct BiTNode{
int weight;
struct BiTNode *lchild, *rchild;
}BiTNode, *BiTree;
//先序遍历
int WPL(BiTree root){
return wpl_PreOrder(root, 0);
}
int wpl_PreOrder(BiTree root, int deep){
static int wpl = 0;
if(root->lchild == NULL && root->rchild == NULL) wpl += deep * root->weight;
if(root->lchild != NULL)
wpl_PreOrder(root->lchild, deep+1);
if(root->rchild != NULL)
wpl_PreOrder(root->rchild, deep+1);
return wpl;
}
//层次遍历
#define MaxSize 100
int wpl_LevelOrder(BiTree root)
{
BiTree q[MaxSize];
int end1,end2;//end1为头指针,end2为尾指针,队列最多容纳MaxSize-1个元素
end1 = end2 = 0;
int wpl = 0, deep = 0;
BiTree lastNode; //记录当前层的最后一个结点
BiTree newlastNode; //记录下一层的后一个结点
lastNode = root;
newlastNode = NULL;
q[end2++] = root; //根节点入队
while(end1 != end2){
BiTree t = q[end1++];
if(t->lchild == NULL && t->rchild == NULL){
wpl += deep*t->weight;
}//叶结点の统计
if(t->lchild != NULL){
q[end2++] = t->lchild;
newlastNode = t->lchild;
}// 设下一层的最后一个结点为该结点的左节点
if(t->rchild != NULL)
{
q[end2++] = t->rchild;
newlastNode = t->rchild;
}
if(t == lastNode){
lastNode = newlastNode;
deep += 1;
}
}// end while
return wpl;
}
5.3.20
请设计一个算法,将给定的表达式树(二叉树)转换为等价的中缀表达式(通过括号反映操作符的计算次序)并输出。
typedef struct node{
char data[10];
struct node *left, *right;
}BTree;
void BTreeToE(BTree *root){
BtreeToExp(root, 1);
}
void BTreeToExp(BTree *root, int deep)
{
if(root == NULL) return;
else if(root->left == NULL && root->right == NULL)
printf("%s",root->data);
else{
if(deep>1) printf("(");
BtreeToExp(root->left, deep+1);
printf("%s",root->data);
BtreeToExp(root->right, deep+1);
if(deep>1) printf(")");
}
return;
}
后记
好难啊好难啊好难啊!!!!!后面我还会回来刷的!