首页 > 其他分享 >二叉树(存储结构,三种遍历方式,构建树)——C语言描述

二叉树(存储结构,三种遍历方式,构建树)——C语言描述

时间:2022-10-15 16:45:39浏览次数:97  
标签:DataPtr 结点 遍历 int BiTreeNode C语言 二叉树 Data TraIndex

二叉树(存储结构,三种遍历方式,构建树)——C语言描述

目录

0 测试用例框架

https://blog.csdn.net/m0_59469991/article/details/127137119?csdn_share_tail=%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%22%2C%22rId%22%3A%22127137119%22%2C%22source%22%3A%22m0_59469991%22%7D

1 定义

​ 二叉树是n(n >= 0)个结点的有限集合,该集合或者空集(称为空二叉树),或者由一个根结点和两棵互不相交的,分别称为根结点的左子树和右子树的二叉树组成

2 特殊二叉树

​ 斜树,满二叉树,完全二叉树

3 二叉树的性质

(1)在二叉树的第 i 层至多有2^(i-1)个结点

(2)深度为k的二叉至多有2^k – 1个结点

(3)对于任何一棵二叉树T,如果其终端结点数位n0,度为2的结点数为n2,则 n0 = n2 + 1

(4)具有n个结点的完全二叉树的深度为(log2n) + 1

(5)如果对一颗有n个结点的完全二叉树(深度为(log2n) + 1)的结点按层序编号(从第1层到第(log2n)+1层,每层从左到右),对任一结点j(1 <= i <= n)有:

①如果i = 1,则结点i是二叉树的根,无双亲;如果i>1,则其双亲是结点i/2;

②如果2i > n,则结点i无左孩子(结点i为叶子结点);否则其左孩子是结点2i;

① 如果2i + 1 > n,则结点i无右孩子;否则其右孩子是结点2i+1

4 二叉树存储结构

​ 采用链式存储结构

typedef struct _BINARY_TREE_NODE {
​     int Data;
​     struct _BINARY_TREE_NODE *LeftChild;
​     struct _BINARY_TREE_NODE *RightChild;
}BINARY_TREE_NODE;

5 二叉树的遍历方式

采用递归方式

5.1 前序遍历

​ 根-左-右

代码:

void PreOrderTraversePrintBinaryTree(const BINARY_TREE_NODE *BiTreeNode) {	
	if (BiTreeNode == NULL) {
		return;
	} else {
		printf("BiTreeNode->Data = %d\n", BiTreeNode->Data);
		PreOrderTraversePrintBinaryTree(BiTreeNode->LeftChild);
		PreOrderTraversePrintBinaryTree(BiTreeNode->RightChild);
	}
}

5.2 前序遍历

​ 左-根-右

代码:

void InOrderTraversePrintBinaryTree(const BINARY_TREE_NODE *BiTreeNode) {
	if (BiTreeNode == NULL) {
		return;
	} else {
		PreOrderTraversePrintBinaryTree(BiTreeNode->LeftChild);
		printf("BiTreeNode->Data = %d\n", BiTreeNode->Data);
		PreOrderTraversePrintBinaryTree(BiTreeNode->RightChild);
	}
}

5.3 后序遍历

​ 左-右-根

代码:

void PostOrderTraversePrintBinaryTree(const BINARY_TREE_NODE *BiTreeNode) {
	if (BiTreeNode == NULL) {
		return;
	} else {
		PreOrderTraversePrintBinaryTree(BiTreeNode->LeftChild);
		PreOrderTraversePrintBinaryTree(BiTreeNode->RightChild);
		printf("BiTreeNode->Data = %d\n", BiTreeNode->Data);
	}
}

6 二叉树的构建

​ 使用前序遍历的方式创建。

(1)结点法

每个结点都输入进去,包括叶子结点的两个孩子结点

void PreOderBuildBinaryTree01(BINARY_TREE_NODE **BiTreeNodePtr, int *DataPtr, int Index)

​ BiTreeNodePtr表示树结点的地址,DataPtr表示结点的数据(以前序遍历的顺序排列,叶子结点的两个孩子结点,其值为0,表示结点地址为空),Index表示结点数据的下标。

代码:

void PreOderBuildBinaryTree01(BINARY_TREE_NODE **BiTreeNodePtr, int *DataPtr, int Index) {
	static int TraIndex = 0;

	printf("PreOderBuildBinaryTree01 start\n");

	if (DataPtr[TraIndex] == 0) {
		*BiTreeNodePtr = NULL;
		TraIndex++;
		return ;
	} else {
		*BiTreeNodePtr = (BINARY_TREE_NODE *)malloc(sizeof(BINARY_TREE_NODE));
		printf("In else, DataPtr[TraIndex] = %d\n", DataPtr[TraIndex]);
		(*BiTreeNodePtr)->Data = DataPtr[TraIndex];
		TraIndex++;

		PreOderBuildBinaryTree01(&((*BiTreeNodePtr)->LeftChild), DataPtr, TraIndex);
		PreOderBuildBinaryTree01(&((*BiTreeNodePtr)->RightChild), DataPtr, TraIndex);
	}

	printf("PreOderBuildBinaryTree01 end\n\n");
}

(2)结点孩子法

void PreOderBuildBinaryTree02(BINARY_TREE_NODE **BiTreeNodePtr, BINARY_TREE_NODE_DATA *DataPtr, int Index, int IfExistNodeFlag)

​ BiTreeNodePtr表示树结点的地址,DataPtr表示结点的数据(以前序遍历的顺序排列,BINARY_TREE_NODE_DATA数据结构如下),IfExistNodeFlag表示该结点是否存在,1为存在,0表示不存在。

typedef struct _BINARY_TREE_NODE_DATA {
	int BiTreeNodeData;
	int IsExistLeftChildFlag;
	int IsExistRightChildFlag;
}BINARY_TREE_NODE_DATA;

代码:

void PreOderBuildBinaryTree02(BINARY_TREE_NODE **BiTreeNodePtr, BINARY_TREE_NODE_DATA *DataPtr, int Index, int IfExistNodeFlag) {
	static int TraIndex = 0;
	int IfExistLeftChildNodeFlag;
	int IfExistRightChildNodeFlag;
	
	printf("PreOderBuildBinaryTree02 start\n");

	if (IfExistNodeFlag == 0) {
		*BiTreeNodePtr = NULL;
		//TraIndex++;
		return;
	} else {
		*BiTreeNodePtr = (BINARY_TREE_NODE *)malloc(sizeof(BINARY_TREE_NODE));
		printf("In else, DataPtr[%d] = %d\n", TraIndex, DataPtr[TraIndex]);
		(*BiTreeNodePtr)->Data = DataPtr[TraIndex].BiTreeNodeData;
		IfExistLeftChildNodeFlag = DataPtr[TraIndex].IsExistLeftChildFlag;
		IfExistRightChildNodeFlag = DataPtr[TraIndex].IsExistRightChildFlag;
		printf("IfExistLeftChildNodeFlag = %d, IfExistRightChildNodeFlag = %d\n", IfExistLeftChildNodeFlag, IfExistRightChildNodeFlag);

		TraIndex++;

		PreOderBuildBinaryTree02(&((*BiTreeNodePtr)->LeftChild), DataPtr, TraIndex, IfExistLeftChildNodeFlag);

		printf("In Right, TraIndex = %d\n", TraIndex);
		PreOderBuildBinaryTree02(&((*BiTreeNodePtr)->RightChild), DataPtr, TraIndex, IfExistRightChildNodeFlag);
	}

	printf("PreOderBuildBinaryTree02 end\n\n");
}

测试用例:

static int PreOrderTraverseCompareNum = 0;

void PreOrderTraverseCompare(const int *CmpNode, const BINARY_TREE_NODE *BiTreeNode, unsigned int Index) {	
	if (BiTreeNode == NULL) {
		return;
	} else {
		if (BiTreeNode->Data == CmpNode[Index]) {
			PreOrderTraverseCompareNum++;
		}
	
		Index++;
		PreOrderTraverseCompare(CmpNode, BiTreeNode->LeftChild, Index);
		PreOrderTraverseCompare(CmpNode, BiTreeNode->RightChild, Index);	
	} 
}
void CmpPreOderBuildBinaryTree(const int *CmpNode, const BINARY_TREE_NODE *BiTreeNode, int Num) {
	unsigned int Index = 0;
	
	TestNum++;

	PreOrderTraverseCompare(CmpNode, BiTreeNode, Index);	

	if (PreOrderTraverseCompareNum != PreOrderTraverseCompareNum) {
		FaildNum++;
	} else {
		PassNum++;
	}
}
void TestPreOderBuildBinaryTree(void) {
	/*Test01*/
	BINARY_TREE_NODE *BiTreeNodePtr01 = NULL;
	int Data01[] = {10, 20, 0, 40, 0, 0, 30, 0, 0};
	int Index01 = 0;
	int CmpBiTreeNodeData01[] = { 10, 20, 40, 30 };

	/*Test02*/
	BINARY_TREE_NODE *BiTreeNodePtr02 = NULL;
	BINARY_TREE_NODE_DATA Data02[] = { {10, 1, 1}, {20, 0, 1}, {40, 0, 0}, {30, 0, 0} };
	int Index02 = 0;
	int IfExistNodeFlag02 = 1;
	int CmpBiTreeNodeData02[] = {10, 20, 40, 30};

	printf("-------Test start----------\n");
	InitNum();
	/*Test01*/
	printf("-------Test 01----------\n");
	PreOderBuildBinaryTree01(&BiTreeNodePtr01, Data01, Index01);
	printf("PreOrderTraversePrintBinaryTree\n");
	PreOrderTraversePrintBinaryTree(BiTreeNodePtr01);
	printf("InOrderTraversePrintBinaryTree\n");
	InOrderTraversePrintBinaryTree(BiTreeNodePtr01);
	printf("PostOrderTraversePrintBinaryTree\n");
	PostOrderTraversePrintBinaryTree(BiTreeNodePtr01);
	CmpPreOderBuildBinaryTree(CmpBiTreeNodeData01, BiTreeNodePtr01, Index01);

	/*Test02*/
	printf("\n-------Test 02----------\n");
	PreOderBuildBinaryTree02(&BiTreeNodePtr02, Data02, Index02, IfExistNodeFlag02);
	printf("PreOrderTraversePrintBinaryTree\n");
	PreOrderTraversePrintBinaryTree(BiTreeNodePtr02);
	printf("InOrderTraversePrintBinaryTree\n");
	InOrderTraversePrintBinaryTree(BiTreeNodePtr02);
	printf("PostOrderTraversePrintBinaryTree\n");
	PostOrderTraversePrintBinaryTree(BiTreeNodePtr02);
	CmpPreOderBuildBinaryTree(CmpBiTreeNodeData02, BiTreeNodePtr02, Index02);

	/*Test Result*/
	printf("\n-------Test result----------\n");
	TestResult();
}

结果:

-------Test start----------

-------Test 01----------

PreOderBuildBinaryTree01 start

In else, DataPtr[TraIndex] = 10

PreOderBuildBinaryTree01 start

In else, DataPtr[TraIndex] = 20

PreOderBuildBinaryTree01 start

PreOderBuildBinaryTree01 start

In else, DataPtr[TraIndex] = 40

PreOderBuildBinaryTree01 start

PreOderBuildBinaryTree01 start

PreOderBuildBinaryTree01 end

PreOderBuildBinaryTree01 end

PreOderBuildBinaryTree01 start

In else, DataPtr[TraIndex] = 30

PreOderBuildBinaryTree01 start

PreOderBuildBinaryTree01 start

PreOderBuildBinaryTree01 end

PreOderBuildBinaryTree01 end

PreOrderTraversePrintBinaryTree

BiTreeNode->Data = 10

BiTreeNode->Data = 20

BiTreeNode->Data = 40

BiTreeNode->Data = 30

InOrderTraversePrintBinaryTree

BiTreeNode->Data = 20

BiTreeNode->Data = 40

BiTreeNode->Data = 10

BiTreeNode->Data = 30

PostOrderTraversePrintBinaryTree

BiTreeNode->Data = 20

BiTreeNode->Data = 40

BiTreeNode->Data = 30

BiTreeNode->Data = 10

-------Test 02----------

PreOderBuildBinaryTree02 start

In else, DataPtr[0] = 10

IfExistLeftChildNodeFlag = 1, IfExistRightChildNodeFlag = 1

PreOderBuildBinaryTree02 start

In else, DataPtr[1] = 20

IfExistLeftChildNodeFlag = 0, IfExistRightChildNodeFlag = 1

PreOderBuildBinaryTree02 start

In Right, TraIndex = 2

PreOderBuildBinaryTree02 start

In else, DataPtr[2] = 40

IfExistLeftChildNodeFlag = 0, IfExistRightChildNodeFlag = 0

PreOderBuildBinaryTree02 start

In Right, TraIndex = 3

PreOderBuildBinaryTree02 start

PreOderBuildBinaryTree02 end

PreOderBuildBinaryTree02 end

In Right, TraIndex = 3

PreOderBuildBinaryTree02 start

In else, DataPtr[3] = 30

IfExistLeftChildNodeFlag = 0, IfExistRightChildNodeFlag = 0

PreOderBuildBinaryTree02 start

In Right, TraIndex = 4

PreOderBuildBinaryTree02 start

PreOderBuildBinaryTree02 end

PreOderBuildBinaryTree02 end

PreOrderTraversePrintBinaryTree

BiTreeNode->Data = 10

BiTreeNode->Data = 20

BiTreeNode->Data = 40

BiTreeNode->Data = 30

InOrderTraversePrintBinaryTree

BiTreeNode->Data = 20

BiTreeNode->Data = 40

BiTreeNode->Data = 10

BiTreeNode->Data = 30

PostOrderTraversePrintBinaryTree

BiTreeNode->Data = 20

BiTreeNode->Data = 40

BiTreeNode->Data = 30

BiTreeNode->Data = 10

-------Test result----------

Print test result;

TestNum = 2, PassNum = 2, FaildNum = 0

标签:DataPtr,结点,遍历,int,BiTreeNode,C语言,二叉树,Data,TraIndex
From: https://www.cnblogs.com/meditatorss/p/16794485.html

相关文章

  • List集合存储学生对象用三种方式遍历
    packagepackage5;importpackage4.Student;importjava.util.ArrayList;importjava.util.Iterator;importjava.util.List;//List集合存储学生对象用三种方式遍......
  • C语言文件基本操作
    什么是文件与普通文件载体不同,文件是以硬盘为载体存储在计算机上的信息集合,文件可以是文本文档、图片、程序等等。文件通常具有点+三个字母的文件扩展名,用于指示文件类型(......
  • 226. 翻转二叉树
    题目描述解题思路二叉树的题一般都有对应的模板,我们做题时可以参考对应模板二叉树解题的思维模式分两类:1、是否可以通过遍历一遍二叉树得到答案?如果可以,用一个trav......
  • 【C语言】函数调用操作符、结构成员访问操作符、隐私类型转换、操作数优先级大小。
    ......
  • C语言实现stat
    mystat用c语言实现statstat命令的作用stat命令显示文件或目录的详细属性信息包括文件系统状态,比ls命令输出的信息更详细首先学习一下statmanstatman-kstat|g......
  • 用C语言实现猜数字游戏
    #每日美图分享#今天我们来用C语言代码来制作一个猜数字的游戏。基本思路:1.开始时,执行菜单来选择是否进行游戏。2.选择进行游戏后我们需要电脑生成一个的随机数。3.搞定随机......
  • C语言小白刷题
     1.有n个评委,他们给出score个分数,请用代码写出平均值,ave代表平均值intmain(){intn,i=1,score,sum=0,ave;printf("请输入评委人数:");scanf("%......
  • 【C语言】函数调用操作符、结构成员访问操作符、隐私类型转换。
    ......
  • 617. 合并二叉树
    /***Definitionforabinarytreenode.*structTreeNode{*intval;*TreeNode*left;*TreeNode*right;*TreeNode():val(0),left(......
  • 124.二叉树的最大路径和
    路径被定义为一条从树中任意节点出发,沿父节点-子节点连接,达到任意节点的序列。同一个节点在一条路径序列中至多出现一次。该路径至少包含一个节点,且不一定经过根节点......