C++算法二叉树

1、各部分名称

        1、根节点 

                为二叉树最顶端的节点。

        2、父节点

                父节点拥有1~2个孩子节点,除去最下端的节点,基本都是父节点。

        3、子节点

                子节点是父节点引出来的节点。

        4、叶子节点

                叶子节点为最底端的节点。

        

二叉树的各部分

2、分类

首先,二叉树属于树形结构,二叉树分为几种类别:

1、满二叉树

        指叶子节点都在最后一层,而且除叶子节点以外,其他的所有节点都有两个子节点。

2、完全二叉树

        去掉最后一层节点后,剩下来的树是满二叉树,还有一个要求,最后一层必须是左右分布

满二叉树

完全二叉树

3、各个种类的关系

        画个韦恩图来理解一下

        

韦恩图

        可以从图中看到,满二叉树在完全二叉树里面,因为它包含了完全二叉树的所有特征 ,所以在完全二叉树里面。

3、二叉树的度量

        1、高度

                可以从字面意思来理解一下,高度是从0开始,从叶子节点开始,往上一层高度就加一

        2、深度

                深度与高度相反,也是从0开始,但是从根节点开始,往下一层深度就加一

        3、层数

                层数最好理解,从1开始,从根节点开始,往上一层层数加一

二叉树的度量

 4、 二叉树的一些常用公式

完全二叉树

  1.  求二叉树节点之上至多节点个数2^{i-1},i为当前层数
  2. 求二叉树至多有多少个节点2^{n}-1,n为层数

大概呢,萌新大概只要懂这两条公式就行啦。不要去学什么像求卡兰特数的公式,只要懂这点就阔以啦ヾ(≧ ▽ ≦)ゝ。

5、二叉树的实现

        这一部分是最难的部分,也是最后一个部分,赶紧冲!

        1、存储

                        存储当然是用结构体啦,结构体保存着:自己的值,左孩子,右孩子

                        例:

typedef struct treeNode
{
	char data;			//数据域字符表示
	struct treeNode* LChild;//左孩子
	struct treeNode* RChild;//右孩子
}TREE,*LPTREE;

                         肥肠简单,大家应该学会了👌👌👌👌

                         连接也蛮简单

                        直接去改结构体里的值就可以了

                        写个函数传3个参数:父节点,左孩子,右孩子

                        上例子               

void insertNode(LPTREE parentNode, LPTREE LChild, LPTREE RChild)
{
	parentNode->LChild = LChild;//连接左孩子
	parentNode->RChild = RChild;//连接右孩子
}

                               看了这些,大家应该会了链式存储了吧。

        2、遍历

                1、前序

                        前序遍历顺序为:根—>左—>右。

                         意思就是我先遍历父节点,再遍历左孩子,最后遍历右孩子

                        以最上面的满二叉树为例,前序遍历顺序为:

                        1—>2—>4—>5—>3—>6—>7

                2、中序

                        中序遍历顺序为:左—>根—>右

                        意思呢,应该不用多讲

                        还是以最上面的满二叉树为例,中序遍历顺序为:

                        4—>2—>5—>1—>6—>3—>7

                3、后序

                        中序遍历顺序为:左—>右—>根

                        意思呢,应该不用多讲

                        还是以最上面的满二叉树为例,后序遍历顺序为:

                        4—>5—>2—>6—>7—>3—>1、

讲完了遍历,最后献上完整代码:

#include <stdio.h>
#include <stdlib.h>
/*
*	1.了解二叉树
*		1.1基本概念
*			根结点
*			右子树指针
*			左子树指针
*			孩子结点
*			父结点
*			兄弟结点
*			姐妹结点
*	2.二叉树的遍历
*/
//描述单一个体
typedef struct treeNode
{
	char data;			//数据域字符表示
	struct treeNode* LChild;//左孩子
	struct treeNode* RChild;//右孩子
}TREE,*LPTREE;
//别名中LP一般表示指针别名
LPTREE createNode(char data)
{
	LPTREE newNode = (LPTREE)malloc(sizeof(TREE));
	newNode->data = data;//把自己赋值一下
	newNode->LChild = NULL;//左孩子设为空
	newNode->RChild = NULL;//右孩子设为空
	return newNode;
}
//没有规律的树
void insertNode(LPTREE parentNode, LPTREE LChild, LPTREE RChild)
{
	parentNode->LChild = LChild;//连接左孩子
	parentNode->RChild = RChild;//连接右孩子
}
//打印当前结点中的元素
void printCurNodeData(LPTREE curData)
{
	printf("%c\t", curData->data);
}
//递归法:领悟
//先序:根左右
void preOrder(LPTREE root)
{
	if (root != NULL)
	{
		printCurNodeData(root);//输出自己,也就是根
		preOrder(root->LChild);//然后递归左孩子,因为它们也有自己的左孩子与右孩子
		preOrder(root->RChild);//最后递归右孩子,跟上面一样的道理
	}
}
void preOrderBystack(LPTREE root)
{
	if (root == NULL)
		return;
	//准备栈
	struct treeNode* stack[10];//存储每次打印节点的位置
	int stackTop = -1;//栈顶标记
	//stackTop=50
	//栈容量的是0-50
	LPTREE pMove = root;//从根节点开始打印
	while (stackTop!=-1||pMove)
	{
		//根 左 右
		//找到最左边
		while (pMove)
		{
			//把路径入栈+打印走过的节点
			printf("%c\t", pMove->data);
			stack[++stackTop] = pMove;
			pMove = pMove->LChild;
		}
		//无路可走的处理
		if (stackTop != -1)
		{
			pMove = stack[stackTop];//获取栈顶元素
			stackTop--;//然后处理栈顶标记
			pMove = pMove->RChild;
		}

	}
}


//中序:左根右
void midOrder(LPTREE root)
{
	if (root != NULL)
	{
		midOrder(root->LChild);//左孩子
		printCurNodeData(root);//根节点
		midOrder(root->RChild);//右孩子
	}
}
void midOrderBystack(LPTREE root)
{
	if (root == NULL)
	{
		return;
	}
	//栈的准备操作
	struct treeNode* stack[10];
	int stackTop = -1;

	//定义移动的指针
	LPTREE pMove = root;
	while (stackTop != -1 || pMove)
	{
		//走到最左边,把走过的节点入栈
		while (pMove)
		{
			stack[++stackTop]=pMove;
			pMove = pMove->LChild;
		}
		//出栈
		if (stackTop != -1)
		{
			pMove = stack[stackTop--];
			printf("%c\t",pMove->data);
			pMove = pMove->RChild;
		}
	}
}




//后序:左右根
void lastOrder(LPTREE root)
{
	if (root != NULL)
	{
		lastOrder(root->LChild);//左孩子
		lastOrder(root->RChild);//右孩子
		printCurNodeData(root);//根节点
	}
}
void lastOrderBysatck(LPTREE root)
{
	if (root == NULL)
		return;
	struct treeNode* stack[10];
	int stackTop = -1;

	struct treeNode* pMove = root;
	struct treeNode* pLastVisit = NULL;//访问标记

	//左右根

	while (pMove)
	{
		stack[++stackTop] = pMove;
		pMove = pMove->LChild;
	}
	while (stackTop != -1)
	{
		pMove = stack[stackTop--];
		//当前节点左右是否被访问
		if (pMove->RChild == NULL || pMove->RChild == pLastVisit)
		{
			//如果被访问就可以打印当前节点数据
			printf("%c\t", pMove->data);
			pLastVisit = pMove;
		}
		else
		{
			//右边没有被访问访问
			stack[++stackTop] = pMove;
			pMove = pMove->RChild;
			while (pMove)
			{
				stack[++stackTop] = pMove;
				pMove = pMove->LChild;
			}
		}
	}
}

int main()
{
	//死板的创建过程,无实际作用
	LPTREE A = createNode('A');
	LPTREE B = createNode('B');
	LPTREE C = createNode('C');
	LPTREE D = createNode('D');
	LPTREE E = createNode('E');
	LPTREE F = createNode('F');
	LPTREE G = createNode('G');
	insertNode(A, B, C);
	insertNode(B, D, NULL);
	insertNode(D, NULL, G);
	insertNode(C, E, F);
	printf("先序递归:\n");
	preOrder(A);
	printf("\n先序非递归\n");
	preOrderBystack(A);
	printf("\n中序递归:\n");
	midOrder(A);
	printf("\n中序非递归:\n");
	midOrderBystack(A);
	printf("\n后序递归:\n");
	midOrder(A);
	printf("\n后序非递归:\n");
	midOrderBystack(A);
	printf("\n");
	system("pause");
	return 0;
}

最后,该告别了,拜拜!👋👋👋

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值