数据结构(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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值