数据结构(C语言)之——链二叉树
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef char ElemType; //定义元素类型
typedef struct BiTNode {
ElemType elem; //数据域
struct BiTNode *lchild, *rchild; //左右孩子指针
}BiTNode;
typedef struct BiTree {
BiTNode* root; //根结点
int length; //结点个数
}BiTree;
//通过扩展先序遍历序列创建一颗二叉树
void preOrderCreateBiTree(BiTree* t, BiTNode* &node, char* chars, int &index) {
if(chars[index] == '#') {
node = NULL;
index += 1;
}else {
node = (BiTNode*)malloc(sizeof(BiTNode));
node->elem = chars[index];
t->length += 1;
index += 1;
preOrderCreateBiTree(t, node->lchild, chars, index);
preOrderCreateBiTree(t, node->rchild, chars, index);
}
}
BiTree* createBiTree(){
BiTree* t = (BiTree*)malloc(sizeof(BiTree));
t->length = 0;
t->root = NULL;
int length;
printf("输入二叉树的扩展先序遍历序列的最大长度:");
scanf("%d", &length);
char* chars = (char*)malloc(sizeof(char)*(length+1));
printf("输入二叉树的扩展先序遍历序列(空结点用'#'表示,如abd#i###cfh##g###):\n");
scanf("%s", chars);
int index = 0;
preOrderCreateBiTree(t, t->root, chars, index);
printf("输入成功!\n");
free(chars);
return t;
}
//通过后序遍历销毁二叉树
bool releaseBiTNode(BiTNode* node) {
if(node == NULL) return false;
releaseBiTNode(node->lchild);
releaseBiTNode(node->rchild);
free(node);
return true;
}
void releaseBiTree(BiTree* t) {
releaseBiTNode(t->root);
free(t);
}
//访问结点数据
void visit(BiTNode* node) {
printf("%c", node->elem);
}
//先序遍历二叉树(根左右)
void preOrderLoop(BiTNode* node) {
if(node != NULL) {
visit(node); //访问根结点
preOrderLoop(node->lchild); //递归遍历左子树
preOrderLoop(node->rchild); //递归遍历右子树
}
}
void preOrder(BiTree* t) {
preOrderLoop(t->root);
}
//中序遍历二叉树(左根右)
void inOrderLoop(BiTNode* node) {
if(node != NULL) {
inOrderLoop(node->lchild); //递归遍历左子树
visit(node); //访问根结点
inOrderLoop(node->rchild); //递归遍历右子树
}
}
void inOrder(BiTree* t) {
inOrderLoop(t->root);
}
//后序遍历二叉树(左右根)
void postOrderLoop(BiTNode* node) {
if(node != NULL) {
postOrderLoop(node->lchild); //递归遍历左子树
postOrderLoop(node->rchild); //递归遍历右子树
visit(node); //访问根结点
}
}
void postOrder(BiTree* t) {
postOrderLoop(t->root);
}
//层序遍历二叉树(使用链队列)
typedef struct LinkNode {
BiTNode* node;
struct LinkNode* next;
}LinkNode;
typedef struct {
LinkNode *front, *rear; //队首和队尾指针
}LinkQueue;
LinkQueue* createQueue() {
LinkQueue* q = (LinkQueue*)malloc(sizeof(LinkQueue));
q->front = (LinkNode*)malloc(sizeof(LinkNode));
q->front->next = NULL;
q->rear = q->front;
return q;
}
void releaseQueue(LinkQueue* q) {
LinkNode* p;
while(q->front != NULL) {
p = q->front;
q->front = q->front->next;
free(p);
}
free(q);
}
void inQueue(LinkQueue* q, BiTNode* node) {
LinkNode* s = (LinkNode*)malloc(sizeof(LinkNode));
s->node = node;
s->next = q->rear->next;
q->rear->next = s; //新结点插入到rear之后
q->rear = s; //修改表尾指针
}
BiTNode* outQueue(LinkQueue* q) {
if(q->front == q->rear) return NULL; //空队
BiTNode* return_ptr = q->front->next->node;
LinkNode* p = q->front->next;
q->front->next = q->front->next->next;
if(p == q->rear) { //最后一个结点出队,需要改变指针
q->rear = q->front;
}
free(p);
return return_ptr;
}
//判断队列是否为空
bool isEmptyQueue(LinkQueue* q) {
return q->front == q->rear ? true : false; //队空条件
}
//对二叉树进行层次遍历
void levelOrder(BiTree* t) {
LinkQueue* q = createQueue();
BiTNode* ptr;
inQueue(q, t->root); //根结点入队
while(!isEmptyQueue(q)) { //队列非空
ptr = outQueue(q); //队头结点出队
visit(ptr); //访问这个结点
if(ptr->lchild != NULL) {
inQueue(q, ptr->lchild); //左孩子入队
}
if(ptr->rchild != NULL) {
inQueue(q, ptr->rchild); //右孩子入队
}
}
releaseQueue(q);
}
//求二叉树的深度(应用后序遍历)
int depthLoop(BiTNode* node) {
if(node == NULL) return 0;
else {
int left_depth = depthLoop(node->lchild);
int right_depth = depthLoop(node->rchild);
//树的深度=Max(左子树的深度,右子树的深度)+1
return left_depth > right_depth ? left_depth+1 : right_depth+1;
}
}
int depth(BiTree* t) {
return depthLoop(t->root);
}
//求二叉树的结点个数
int length(BiTree* t) {
return t->length;
}
//求二叉树的叶子结点个数(应用先序遍历)
void lengthLeafLoop(BiTNode* node, int &count) {
if(node == NULL) return;
if(node->lchild == NULL && node->rchild == NULL) count++;
lengthLeafLoop(node->lchild, count);
lengthLeafLoop(node->rchild, count);
}
int lengthLeaf(BiTree* t) {
int count = 0;
lengthLeafLoop(t->root, count);
return count;
}
//求二叉树的度为1的结点个数(即只有一个孩子的结点,应用先序遍历)
void lengthDegree1Loop(BiTNode* node, int &count) {
if(node == NULL) return;
if((node->lchild == NULL && node->rchild != NULL) ||
(node->lchild != NULL && node->rchild == NULL)) {
count ++;
}
lengthDegree1Loop(node->lchild, count);
lengthDegree1Loop(node->rchild, count);
}
int lengthDegree1(BiTree* t) {
int count = 0;
lengthDegree1Loop(t->root, count);
return count;
}
//输出二叉树中每个叶子结点到根节点的路径
void printfLeafPathLoop(BiTNode* node, char* path, int &pathLength) {
if(node != NULL) { //结点存在判断是叶子结点还是非叶子结点
path[pathLength] = node->elem; //将结点信息保存到路径中
if(node->lchild == NULL && node->rchild == NULL) { //如果是叶子结点
printf("%c:", path[pathLength]); //输出该叶子结点的路径信息
for(int i=pathLength; i>=0; i--) printf("%c", path[i]);
printf("\n");
}else { //如果是非叶子结点
pathLength += 1; //长度加1,用来存放孩子结点
printfLeafPathLoop(node->lchild, path, pathLength);
printfLeafPathLoop(node->rchild, path, pathLength);
pathLength -= 1; //回退
}
}
}
void printLeafPath(BiTree* t) {
char* path = (char*)malloc(sizeof(char)*depth(t)); //存储路径信息(路径长度不超过树的深度)
int pathLength = 0; //存储当前路径长度
printfLeafPathLoop(t->root, path, pathLength);
free(path);
}
int main() {
//创建二叉树
BiTree* t = createBiTree();
//先序遍历二叉树
printf("先序遍历二叉树:"); preOrder(t); printf("\n");
//中序遍历二叉树
printf("中序遍历二叉树:"); inOrder(t); printf("\n");
//后序遍历二叉树
printf("后序遍历二叉树:"); postOrder(t); printf("\n");
//层序遍历二叉树
printf("层序遍历二叉树:"); levelOrder(t); printf("\n");
//求二叉树的深度
printf("二叉树的深度:%d\n", depth(t));
//求二叉树的结点个数
printf("二叉树的结点个数:%d\n", length(t));
//求二叉树的叶子结点个数
printf("二叉树的叶子结点个数:%d\n", lengthLeaf(t));
//求二叉树的度为1的结点个数
printf("二叉树的度为1的结点个数:%d\n", lengthDegree1(t));
//输出二叉树中每个叶子结点到根节点的路径
printf("输出二叉树中每个叶子结点到根节点的路径:\n"); printLeafPath(t);
//销毁二叉树
releaseBiTree(t);
return 0;
}
结果:
输入二叉树的扩展先序遍历序列的最大长度:20
输入二叉树的扩展先序遍历序列(空结点用'#'表示,如abd#i###cfh##g###):
abd#i###cfh##g###
输入成功!
先序遍历二叉树:abdicfhg
中序遍历二叉树:dibahfgc
后序遍历二叉树:idbhgfca
层序遍历二叉树:abcdfihg
二叉树的深度:4
二叉树的结点个数:8
二叉树的叶子结点个数:3
二叉树的度为1的结点个数:3
输出二叉树中每个叶子结点到根节点的路径:
i:idba
h:hfca
g:gfca