- 试给出二叉树的自下而上,自右而左的层次遍历算法
思路:按照层次遍历的思想正常遍历,但是多使用一个栈来存储层次遍历中出队列的元素,层次遍历结束后把栈中元素全部出栈,出栈的顺序就是题目要求的层次遍历算法。还有一种思路,用一个链表存储层次遍历的结果,然后对链表进行倒置。两种思路都可以。
树定义
#ifndef TREE_H
#define TREE_H
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
// 二叉树的顺序存储结构,适合于完全二叉树和满二叉树
#define MaxSize 100
typedef int ElemType;
typedef char DataType;
typedef struct TreeNode{
ElemType value;//结点中的数据元素
bool isEmpty;//结点是否为空
}TreeNode;
// TreeNode t[MaxSize] //初始化长度为MaxSize的数组t
// for(int i=0;i<MaxSize;i++){
// t[i].isEmpty=true;//初始化标记为空
// }
// 二叉树的链式存储
typedef struct BiTNode{
DataType data;
struct BiTNode *lchild,*rchild;
// struct BiTNode *parent;//用来方便存储父节点指针,这也是所谓的三叉链表
}BiTNode,*BiTree;
void createTree(BiTree *T);//先序创建一棵树 ABD##E##CF##G##
#endif
栈定义和实现
#ifndef LISTACK_H
#define LISTACK_H
#include<stdio.h>
#include<stdbool.h>
#include<stdlib.h>
#include "tree.h"
// 链栈,不带头结点的情况
typedef BiTree TreeType;//入栈的节点是一棵树,不是树的一个节点,否则树会断层
typedef struct LinkNode{
TreeType data;//数据域
struct LinkNode *next;
}LinkNode,*LinkStack;
bool InitStack4(LinkStack *s);//初始化不带头结点的栈
bool Push4(LinkStack *s,TreeType x);//入栈
bool Pop4(LinkStack *s,TreeType *x);//出栈
void printfStack4(LinkStack s);//打印
bool EmptyStack4(LinkStack s);//空栈
bool GetTop(LinkStack s,TreeType *x);
#endif
#include "listack.h"
bool InitStack4(LinkStack *s){
*s=NULL;//栈空,不带头结点
return true;
}
bool EmptyStack4(LinkStack s){
if(s==NULL){
return true;
}
return false;
}
// x在这里表示的是一棵树
bool Push4(LinkStack *s,TreeType x){
LinkNode *p=(LinkNode *)malloc(sizeof(LinkNode));
if(p==NULL)
return false;
p->data=x;
// 这一步很容易错
p->next=(*s);
(*s)=p;
return true;
}
bool Pop4(LinkStack *s,TreeType *x){
// printf("Pop-%d",x);
if((*s)==NULL)//空表
return false;
LinkNode *p=*s;
*s=(*s)->next;
*x=p->data;
free(p);
return true;
}
bool GetTop(LinkStack s,TreeType *x){
if(s==NULL)
return false;
*x=s->data;
return true;
}
void printfStack4(LinkStack s){
// s=NULL;
LinkNode *p=s;
while(p!=NULL){
printf("%c->",p->data->data);
p=p->next;
}
printf("\n");
}
队列定义和实现
#ifndef LINKQUEUE_H
#define LINKQUEUE_H
#include<stdio.h>
#include<stdbool.h>
#include<stdlib.h>
#include "listack.h"
// typedef int ElemType;
typedef struct LinkNode2{//链式队列结点
TreeType data;
struct LinkNode2 *next;
}LQNode;
typedef struct{//链式队列
LQNode *front,*rear;
}LQueue;
// 带头结点的初始化
void InitLQueue_withHead(LQueue *Q);
// 队列为空
bool LQueueEmpty_withHead(LQueue Q);
// 入队
void EnLQueue_withHead(LQueue *Q,TreeType x);
// 出队
bool DeLQueue_withHead(LQueue *Q,TreeType *x);
void printfLQueue_withHead(LQueue Q);
#endif
#include "linkqueue.h"
// 带头结点的初始化
void InitLQueue_withHead(LQueue *Q){
(*Q).front=(LQNode *)malloc(sizeof(LQNode));
(*Q).rear=(*Q).front;
(*Q).front->next=NULL;
}
bool LQueueEmpty_withHead(LQueue Q){
if(Q.front==Q.rear)
return true;
return false;
}
// 入队
void EnLQueue_withHead(LQueue *Q,TreeType x){
LQNode *s=(LQNode *)malloc(sizeof(LQNode));
s->data=x;
s->next=NULL;
(*Q).rear->next=s;
(*Q).rear=s;//修改表尾指针
}
// 出队
bool DeLQueue_withHead(LQueue *Q,TreeType *x){
if((*Q).front==(*Q).rear)//空队
return false;
LQNode *p=(*Q).front->next;
*x=p->data;
(*Q).front->next=p->next;
if((*Q).rear==p)//最后一个结点出队
(*Q).rear=(*Q).front;
free(p);
return true;
}
void printfLQueue_withHead(LQueue Q){
if(Q.front==Q.rear)
return;
LQNode *p=Q.front->next;
while(p!=NULL){
printf("%d<-",p->data);
p=p->next;
}
printf("\n");
}
倒置层次遍历实现
#include "tree.h"
#include "listack.h"
#include "linkqueue.h"
// create——ABD##E##CF##G##
void createTree(BiTree *T){
DataType ch;
scanf("%c",&ch);
// while(getchar()!='\n');//当获取一个有效字符时结束循环
if(ch=='#'){
*T=NULL;
return;
}
else{
*T=(BiTNode *)malloc(sizeof(BiTNode));
(*T)->data=ch;
createTree(&((*T)->lchild));
createTree(&((*T)->rchild));
}
}
void level(BiTree T){
// 创建并初始化一个栈
LinkStack L;
InitStack4(&L);
// 创建并初始化一个队列
LQueue Q;
InitLQueue_withHead(&Q);
BiTNode* temp=NULL;//用来存储出队列的元素
//层次遍历
EnLQueue_withHead(&Q,T);
Push4(&L,T);
while(!LQueueEmpty_withHead(Q)){//如果队列不为空
DeLQueue_withHead(&Q,&temp);
if(temp->lchild!=NULL){
EnLQueue_withHead(&Q,temp->lchild);
Push4(&L,temp->lchild);
}
if(temp->rchild!=NULL){
EnLQueue_withHead(&Q,temp->rchild);
Push4(&L,temp->rchild);
}
}
// while()
printfStack4(L);
}
void test4(){
BiTree T;
printf("请连续输入字符,中间不要有空格和换行。。。\n");
createTree(&T);
level(T);
}
实现截图
- 假设二叉树采用二叉链表的存储结构,设计一个非递归算法求二叉树的高度
思路和二叉树的先序遍历的非递归实现一样。只是这里把输出改为对高度的的++和- -。
// 利用栈来实现先序遍历的非递归算法
int PreOrder(BiTree T){
LinkStack S;
InitStack4(&S);
BiTNode *p=T;
int length=0;//高度
int temp=0;//临时变量
while(p!=NULL||!EmptyStack4(S)){
if(p!=NULL){
// printf("%c",p->data);
temp++;
Push4(&S,p);
p=p->lchild;
}else{//说明左子树已经遍历完成
Pop4(&S,&p);
length=length>=temp?length:temp;
temp--;//这里把结点出栈,所以这里的temp要--
p=p->rchild;
}
}
return length;
printf("\n");
}
- 编程求以孩子兄弟表示法存储的森林的叶子结点数
思路:首先用孩子兄弟表示法存储的森林是以二叉树的存储方式保存的,其左子树代表当前结点的第一个孩子结点,右子树代表当前结点的右兄弟,如果右兄弟还有右兄弟(同一层),那么其右兄弟的右兄弟存储在右兄弟的右子树上,以此类推。以此为思路,当左孩子为空说明是叶子节点,把叶子节点的数量 1 加上右兄弟的数量,就是森林的叶子结点的数量。实现如下:
#ifndef TREEPLUS_H
#define TREEPLUS_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
typedef char ElemType;
// 孩子兄弟表示法(链式存储)——树和二叉树相互转化的问题
typedef struct CSNode{
ElemType data;
struct CSNode *firstchild,*nextsibling;//第一个孩子和右兄弟指针
}CSNode,*CSTree;
void createTreeplus(CSTree *T);//创建一棵树
#endif
#include "treeplus.h"
// create——ABD##E##CF##G##
void createTreeplus(CSTree *T){
ElemType ch;
scanf("%c",&ch);
// while(getchar()!='\n');//当获取一个有效字符时结束循环
if(ch=='#'){
*T=NULL;
return;
}
else{
*T=(CSNode *)malloc(sizeof(CSNode));
(*T)->data=ch;
createTreeplus(&((*T)->firstchild));
createTreeplus(&((*T)->nextsibling));
}
}
#include "treeplus.h"
int leaves_num(CSTree T){
if(T==NULL)
return 0;
if(T->firstchild==NULL)//表示一定是叶子节点
return 1+leaves_num(T->nextsibling);//返回叶子结点数目以及它兄弟的数量
else
return leaves_num(T->firstchild)+leaves_num(T->nextsibling);//返回孩子子树和兄弟子树叶子数之和
}
int test5_167(){
CSTree T;
createTreeplus(&T);
printf("%d\n",leaves_num(T));
}
void main(){
printf("请输入一棵树。。。\n");
test5_167();
}
- 以孩子兄弟链表为存储结构,请设计递归算法求树的深度
思路:和二叉树求树高差不多
#include "treeplus.h"
// create——ABD##E###
int height(CSTree T){
if(T==NULL)
return 0;
int hc=0,hs=0;
hc=height(T->firstchild)+1;//第一个子女的树高,所以后面要加1
hs=height(T->nextsibling);//兄弟结点的树高,同一层,所以不用+1
if(hc>hs)
return hc;
else
return hs;
}
void test6_167(){
CSTree T;
createTreeplus(&T);
printf("%d\n",height(T));
}