【C和C++学习记录】层次建树与4种遍历

文章介绍了如何在C++中使用Function.h定义二叉树结构、辅助队列以及四个基本遍历方法(前序、中序、后序和层次遍历),并通过CreateTree函数创建二叉树并演示了队列的操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、Function.h

结构体的定义和函数声明

#pragma once

#include<stdio.h>
#include<stdlib.h>

typedef char BiElemType; 
typedef struct BNodeTree {
	BiElemType Data;      //树中结点存储的数据的类型
	struct BNodeTree* lchild, * rchild;
}BNodeTree, * BTree;

//Tag结构体为二叉树的辅助队列
typedef struct Tag {
	BTree p; // 树的某个结点的起始地址
	struct Tag* next;
}Tag, * pTag;

void PreOrder(BTree T); //前序遍历==深度遍历
void InOrder(BTree T);  // 中序遍历
void PostOrder(BTree T); //后序遍历
void LevelOrder(BTree T); //层次遍历==广度优先遍历

// 队列的结构体
typedef BTree ElemType;
typedef struct LinkNode { //链表
	ElemType Data;
	struct LinkNode* next;
}LinkNode;

typedef struct LinkQueue { //队列
	LinkNode* front, * rear;
}LinkQueue;

void InitLinkQueue(LinkQueue& LQ);//初始化队列
bool IsEmpty(LinkQueue LQ);//判空
void EnLinkQueue(LinkQueue& LQ, ElemType x);//入队
bool DeLinkQueue(LinkQueue& LQ, ElemType& x);//出队

2、层次建树(CreateTree.cpp)

BTree CreateTree() {
	BTree pnew;  //指向当前新建的结点
	BTree tree = NULL;
	BiElemType NewVal;

	//队列的相关指针,newplist.p指向新加入队列的结点,即指向树新加的结点pnew
	//front,rear为队列的头尾指针
	//pcur指向要新加入结点的父结点,
	pTag newplist = NULL, pfront = NULL, prear = NULL, pcur = NULL;

	while (scanf("%c", &NewVal)) {
		if (NewVal == '\n') {//输入到回车为止
			break;
		}

		//为新结点创建空间,calloc可以把这个结点的空间里所有的成员都赋予初值0,即为NULL
		pnew = (BTree)calloc(1, sizeof(BNodeTree)); //让pnew指向新加入的结点
		pnew->Data = NewVal; //给新结点赋值

		newplist = (pTag)calloc(1, sizeof(Tag));  //为新加入到辅助队列的结点,创建空间,原理同上
		newplist->p = pnew; //newplist.p指向新加入队列的结点

		if (tree == NULL) { //如果树根为空
			tree = pnew; //先让树根指向新加入的新结点
			pfront = newplist;  //队列中的所有成员都指向newplist,即都指向新加入的结点
			prear = newplist;
			pcur = newplist;
		}
		else {
			//入队操作
			//newplist->next = NULL;
			prear->next = newplist;
			prear = newplist;

			if (pcur->p->lchild == NULL) {//如果当前父结点的左孩子为空,则加入
				pcur->p->lchild = pnew;
			}
			else if (pcur->p->rchild == NULL) {//如果当前父结点的右孩子为空,则加入
				pcur->p->rchild = pnew;
				pcur = pcur->next;  //当前父结点已满,指向下一个父结点,即之后新加进来的结点都要加到下一个父结点下
			}
		}
	}
	
	return tree;//返回树根
}

3、队列基本操作(LinkQueue.cpp)

#define _CRT_SECURE_NO_WARNINGS 1
#include"Function.h"

void InitLinkQueue(LinkQueue &LQ)//初始化队列
{
	LQ.front = LQ.rear = (LinkNode*)malloc(sizeof(LinkNode));//新建头结点,并让front,和rear指向头结点
	LQ.front->next = NULL;
}

bool IsEmpty(LinkQueue LQ) {//判空
	//if (LQ.front == LQ.rear) {
	//	printf("队列为空!");
	//	return true;
	//}
	//else {
	//	printf("队列不为空!");
	//	return false;
	//}
	return LQ.front == LQ.rear;
}

void EnLinkQueue(LinkQueue &LQ, ElemType x) {//入队
	LinkNode* s = (LinkNode*)malloc(sizeof(LinkNode));
	s->Data = x;
	s->next = NULL;
	LQ.rear->next = s;
	LQ.rear = s;
}

bool DeLinkQueue(LinkQueue& LQ, ElemType& x) {//出队
	if (IsEmpty(LQ))
	{
		printf("队列为空\n");
		return false;
	}
	LinkNode* q = (LinkNode*)malloc(sizeof(LinkNode));
	q = LQ.front->next;
	x = q->Data;
	LQ.front->next = q->next;
	if (q == LQ.rear) {
		LQ.rear = LQ.front;
	}
	free(q);  //释放出队的结点q
	return true;
}

4、四种遍历方式

#define _CRT_SECURE_NO_WARNINGS 1
#include"Function.h"

void PreOrder(BTree T)  //前序遍历:根左右
{
	if (T) { //如果树根不为空
		printf("%c ", T->Data); //打印根结点
		PreOrder(T->lchild);  //遍历左子树
		PreOrder(T->rchild); //遍历右子树
	}
}
void InOrder(BTree T) //中序遍历:左根右
{
	if (T) {
		InOrder(T->lchild);
		printf("%c ", T->Data);
		InOrder(T->rchild);
	}
}

void PostOrder(BTree T)//后序遍历:左右根
{
	if (T) {	
		PostOrder(T->lchild);
		PostOrder(T->rchild);
		printf("%c ", T->Data);
	}
}

void LevelOrder(BTree T) {  //层次遍历:从上到下,从左到右
	LinkQueue LQ;
	InitLinkQueue(LQ);  //初始化队列
	BTree P;
	EnLinkQueue(LQ, T); //把根结点加入队列

	while (!IsEmpty(LQ)) {  //队列不为空
		DeLinkQueue(LQ, P);  //弹出当前遍历到的结点
		putchar(P->Data);  //打印

		if (P->lchild) {  //左子树不为空
			EnLinkQueue(LQ, P->lchild);
		}
		if (P->rchild) { //右子树不为空
			EnLinkQueue(LQ, P->rchild);
		}
	}
}

5、主函数和运行结果

int main()
{
	BTree tree = CreateTree(); //返回树根
	printf("\nPreOrder:");
	PreOrder(tree);
	printf("\nInOrder:");
	InOrder(tree);
	printf("\nPostOrder:");
	PostOrder(tree);
	printf("\nLevelOrder:");
	LevelOrder(tree);
	return 0;
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值