数据结构之二叉树

基本概念

  1. 树是n(n>=0)个结点的有限集(n=0时称为空树)
  2. 非空树应该满足:
    1)有且仅有一个特定的称为根的结点。
    2)当n>1时,其余结点可分为m(m>0)个互不相交的有限集T1,T2,…,Tm,其中每个集合本身又是一棵树,并且称为根的子树
  3. 树的特点
    1)树的根结点没有前驱,除根结点外的所有结点有且只有一个前驱
    2)树中所有结点可以有0个或多个后继

二叉树

基本概念:

1.特点:每个结点至多只有两颗子树(即二叉树中不存在度大于2的结点),并且二叉树的子树有左右之分,其次序不能任意颠倒
2. 概念:二叉树是n(n>=0)个结点的有限集合;当n=0时为空二叉树;由一个根节点和两个互不相交的被称为根的左子树和右子树组成。左右子树又分别是一颗二叉树。
3. 满二叉树:每一层结点数满足2^(层数-1)

代码实现

1.二叉树的链式存储

1.二叉树建树
2.前序遍历
在这里插入图片描述
前序遍历实际上就是先找到父节点写下来,然后在父节点后面写下该父节点的子结点,最后就是这个树的打印结果(大白话就是:爸爸应该领着他的两个儿子)
3.中序遍历
在这里插入图片描述
中序遍历就是:找到父节点然后将父节点放在中间,该父节点对应的子节点放在两边(大白话就是:父亲在中间,两个儿子在左右当护法)
4.后序遍历
在这里插入图片描述
后序遍历实际上就是先找到父节点,然后将父节点的子节点先写出来,最后写出父节点(大白话就是儿子先趟趟水,父亲在出来)
5.中序遍历非递归(辅助栈)
6.层次遍历(辅助队列)

#include<stdio.h>
#include<stdlib.h>
#define MaxSize 100

// 树
typedef char Elemtype;

typedef struct BiNode {
	Elemtype data;
	struct BiNode* lchild;
	struct BiNode* rchild;
}BiNode, * BiTree;

typedef struct BLNode {
	BiTree p;
	struct BLNode* next;
}BLNode, * Blist;

// 栈
typedef BiTree BiElemtype;
typedef struct {
	BiElemtype data[MaxSize];
	int top;
}Stack;

// 初始化栈
void InitStack(Stack& S)
{
	S.top = -1;
}

// 判断栈为空
bool  S_IsEmpty(Stack S)
{
	if (S.top == -1)
		return true;
	return false;
}

// 入栈
bool Push_S(Stack& S, BiElemtype e)
{
	if (S.top == MaxSize - 1)
		return false;
	S.data[++S.top] = e;
	return true;
}

// 出栈
bool Pop_S(Stack& S, BiElemtype& e)
{
	if (S.top == -1)
		return false;
	e = S.data[S.top--];
	return true;
}

// 队列
typedef struct TLNode {
	BiElemtype data1;
	struct TLNode* next;
}TLNode, * TList;

typedef struct {
	TList front, rear;
}BQueue;

// 初始化队列
void Init_Queue(BQueue& Q)
{
	Q.front = Q.rear = (TList)malloc(sizeof(TLNode));
	Q.rear->next = NULL;
}

// 判断队列是否为空
bool Q_IsEmpty(BQueue Q)
{
	if (Q.front == Q.rear)
		return true;
	return false;
}

// 入队 - 尾插法
void Q_Push(BQueue& Q, BiElemtype e)
{
	TList p = (TList)malloc(sizeof(TLNode));
	p->data1 = e;
	p->next = NULL;
	Q.rear->next = p;
	Q.rear = p;
}

// 出队 - 头部删除
bool Q_Pop(BQueue& Q, BiElemtype& e)
{
	if (Q.front == Q.rear)
		return false;
	TList p = Q.front->next;
	e = p->data1;
	Q.front->next = p->next;
	if (p == Q.rear)
		Q.rear = Q.front;
	free(p);
	p = NULL;
	return true;
}

// 前序遍历
void PreOrder(BiTree tree)
{
	if (tree != NULL)
	{
		putchar(tree->data);
		PreOrder(tree->lchild);
		PreOrder(tree->rchild);
	}
}

// 中序遍历
void InOrder(BiTree tree)
{
	if (tree != NULL)
	{
		InOrder(tree->lchild);
		putchar(tree->data);
		InOrder(tree->rchild);
	}
}

// 后序遍历
void PosOrder(BiTree tree)
{
	if (tree != NULL)
	{
		PosOrder(tree->lchild);
		PosOrder(tree->rchild);
		putchar(tree->data);
	}
}

// 中序遍历非递归
void InOrder2(BiTree tree)
{
	Stack S;
	InitStack(S);
	BiTree T = tree;
	while (T || !S_IsEmpty(S))
	{
		if (T)
		{
			Push_S(S, T);
			T = T->lchild;
		}
		else
		{
			Pop_S(S, T);
			putchar(T->data);
			T = T->rchild;
		}
	}
}

// 层次遍历(广度优先遍历)
void LevelOrder(BiTree tree)
{
	BQueue Q;
	Init_Queue(Q);
	BiTree T = tree;
	Q_Push(Q, T); // 入队树根
	while (!Q_IsEmpty(Q))
	{
		Q_Pop(Q, T);
		putchar(T->data);
		if (T->lchild != NULL)
			Q_Push(Q, T->lchild);
		if (T->rchild != NULL)
			Q_Push(Q, T->rchild);
	}
}


int main(void)
{
	BiTree tree = NULL; // 树根
	BiTree pnew;
	char c;
	Blist phead = NULL, ptail = NULL, plist = NULL, pcur = NULL;
	while (scanf("%c", &c) != EOF)
	{
		if (c == '\n')
			break;
		pnew = (BiTree)calloc(1, sizeof(BiNode));
		pnew->data = c;
		plist = (Blist)calloc(1, sizeof(BLNode));
		plist->p = pnew;
		if (tree == NULL)
		{
			tree = pnew;
			phead = plist;
			ptail = plist;
			pcur = plist;
			continue;
		}
		else {
			ptail->next = plist;
			ptail = plist;
		}
		if (pcur->p->lchild == NULL)
			pcur->p->lchild = pnew;
		else if (pcur->p->rchild == NULL)
		{
			pcur->p->rchild = pnew;
			pcur = pcur->next;
		}
	}
	printf("--------前序遍历--------\n");
	PreOrder(tree);
	printf("\n--------中序遍历--------\n");
	InOrder(tree);
	printf("\n--------后序遍历--------\n");
	PosOrder(tree);
	printf("\n--------中序遍历非递归--------\n");
	InOrder2(tree);
	printf("\n--------层次遍历--------\n");
	LevelOrder(tree);
	return 0;
}


写在最后:这部分代码有些长,需要耐下性子来读,中序遍历非递归以及层次遍历,我就不用图来表达了,大家可以自己用笔画一画,并不是很难,加油!

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值