二叉树生成及遍历

二叉树生成及遍历

前言:由于这样介绍的为二叉树,这里只介绍关于树的基本概念。

一、树的简介

树是一种数据结构,它是由n(n>0)个有限结点组成的一个具有层次关系的集合。树的每个结点有零个或多个子节点,没有父结点的结点称为根节点;每一个非根结点有且仅有一个父节点,除了根节点外,每个子节点可以分为多个不相交的子树。


二、二叉树简介

(摘自百度)二叉树(Binary tree)是树形结构的一个重要类型。许多实际问题抽象出来的数据结构往往是二叉树形式,即使是一般的树也能简单地转换为二叉树,而且二叉树的存储结构及其算法都较为简单,因此二叉树显得特别重要。二叉树特点是每个结点最多只能有两棵子树,且有左右之分。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NusVSS8V-1597061357637)(C:\Users\漠殇\AppData\Roaming\Typora\typora-user-images\image-20200810174931880.png)]

满二叉树:一个高度为h的二叉树,如果其节点个数为2 ^ h - 1,则,这个二叉树就是满二叉树。

一棵高度为h的二叉树,其节点最大容量为 2 ^ h - 1;

一棵高度为h的二叉树的第i层( i <= h )的节点数量是2 ^ i - 1;

完全二叉树:一棵高度为h的完全二叉树,其节点总数在

[2 ^ (h - 1 ) - 1 + 1 => 2 ^ (h - 1 ), 2 ^ h -1]范围内

在完全二叉树中,若一个节点是非叶子节点,则,其子节点有两种情况:

1、左右孩子节点都存在;

2、只存在左孩子,不存在右孩子。

在二叉树中,存在一个等式: n0 = n2 + 1

n0为叶子节点个数,n2为度为2的节点个数。


三、生成二叉树

这里我们使用的是通过输入字符串来生成二叉树。

如:A ( B ( D ( F , G ) , J ( , L ( k ) ) ) , C ( E ( H , I ) ) )

在处理这个字符串之前,我们需要将整个流程过一遍。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YLNdGDDK-1597061357641)(C:\Users\漠殇\AppData\Roaming\Typora\typora-user-images\image-20200810190333210.png)]

我们发现,这里共存在七个状态:开始、根、子树、数据、逗号、右括号、结束

这就构建起了整个生成二叉树的体系结构。

细化到每个状态,应该做什么,怎么做,可以慢慢的去优化。

在数据前面如果是左括号的话,那么,这个数据一定是上一个数据的左孩子,当遇到“,”时,后面无论如何,都会变为右孩子状态。

存储数据使用的的堆栈,遇到左括号,将左括号之前的数据入栈,遇到右括号,将栈顶元素出栈。

在这里插入图片描述

四、二叉树的递归

二叉树的遍历中,递归是一种很好的方法

二叉树的表示有三种:先根序 :根 (左子树) (右子树)

中跟序:(左子树) 根 (右子树)

后根序:(左子树) (右子树) 根。

上面的三种方法,充满了浓浓的递归的味道。访问顺序即是递归顺序。

void middleRootVisited(const B_TREE *root) {
	if (NULL == root) {
		return;
	}
	middleRootVisited(root->left);
	printf("%c ", root->data);
	middleRootVisited(root->right);
}

void lastRootVisited(const B_TREE *root) {
	if (NULL == root) {
		return;
	}
	lastRootVisited(root->left);
	lastRootVisited(root->right);
	printf("%c ", root->data);
}

void destoryBTree(B_TREE **root) {
	if (NULL == root) {
		return;
	}
	destoryBTree(root->left);
	destoryBTree(root->right);
	free(root);
}

五、全部代码

btree.c

#include <stdio.h>
#include <malloc.h>
#include <ctype.h>

#include "mec.h"
#include "mecError.h"
#include "btree.h"
#include "stack.h"

extern const char *errMess;

#define	BTREE_STATUS_BEGIN		1
#define	BTREE_STATUS_ROOT		2
#define	BTREE_STATUS_SUB_TREE	3
#define	BTREE_STATUS_DATA		4
#define	BTREE_STATUS_COMMA		5
#define	BTREE_STATUS_RIGHTBK	6
#define	BTREE_STATUS_END		7

typedef struct BTREE_ARG {
	int status;
	boolean ok;
	boolean finished;
	int index;
	boolean whichChild;
	B_TREE *root;
	B_TREE *tmp;
	MEC_STACK *stack;
}BTREE_ARG;

#define	LEFT_CHILD		1
#define RIGHT_CHILD		2

#define LEFT_BRACKET_TOO_MUCH	-1
#define RIGHT_BRACKET_TOO_MUCH	-2

typedef void (*dealFun)(BTREE_ARG *arg, int ch);

static void dealBTreeBegin(BTREE_ARG *arg, int ch);
static void dealBTreeRoot(BTREE_ARG *arg, int ch);
static void dealBTreeSubTree(BTREE_ARG *arg, int ch);
static void dealBTreeData(BTREE_ARG *arg, int ch);
static void dealBTreeComma(BTREE_ARG *arg, int ch);
static void dealBTreeRightBk(BTREE_ARG *arg, int ch);
static void dealBTreeEnd(BTREE_ARG *arg, int ch);

static boolean isData(const int ch);
static void dealRoot(BTREE_ARG *arg, int ch);
static void dealLeftBracket(BTREE_ARG *arg);
static void dealRightBracket(BTREE_ARG *arg);
static void dealComma(BTREE_ARG *arg);
static void dealNode(BTREE_ARG *arg, int ch);
static int getStackDeep(const char *str);

static int getStackDeep(const char *str) {
	int index;
	int match = 0;
	int maxMatch = 0;

	for (index = 0; match >= 0 && str[index]; index++) {
		if ('(' == str[index]) {
			++match;
			maxMatch = maxMatch < match ? match : maxMatch;
		} else if (')' == str[index]) {
			--match;
			if (match < 0) {
				return RIGHT_BRACKET_TOO_MUCH;
			}
		}
	}

	return match == 0 ? maxMatch : LEFT_BRACKET_TOO_MUCH;
}

static void dealNode(BTREE_ARG *arg, int ch) {
	B_TREE *parent = NULL;

	arg->tmp = (B_TREE *) calloc(sizeof(B_TREE), 1);
	arg->tmp->data = ch;

	parent = readTop(arg->stack);
	if (LEFT_CHILD == arg->whichChild) {
		parent->left = arg->tmp;
	} else {
		parent->right = arg->tmp;
	}

	arg->status = BTREE_STATUS_DATA;
	arg->index++;
}

static void dealComma(BTREE_ARG *arg) {
	B_TREE *parent = NULL;

	parent = readTop(arg->stack);
	if (parent->right != NULL) {
		errMess = "二叉树不允许有超过2个节点!";
		arg->ok = FALSE;

		return;
	}

	arg->whichChild = RIGHT_CHILD;
	arg->status = BTREE_STATUS_COMMA;
	arg->index++;
}

static void dealRightBracket(BTREE_ARG *arg) {
	pop(arg->stack);

	arg->status = BTREE_STATUS_RIGHTBK;
	arg->index++;
}

static void dealLeftBracket(BTREE_ARG *arg) {
	arg->whichChild = LEFT_CHILD;
	push(arg->stack, arg->tmp);

	arg->status = BTREE_STATUS_SUB_TREE;
	arg->index++;
}

static void dealRoot(BTREE_ARG *arg, int ch) {
	arg->root = (B_TREE *) calloc(sizeof(B_TREE), 1);
	arg->root->data = ch;
	arg->tmp = arg->root;
	
	arg->status = BTREE_STATUS_ROOT;
	arg->index++;
}

static boolean isData(const int ch) {
	return isalnum(ch);
}

const dealFun functions[] = {
	NULL,
	dealBTreeBegin,
	dealBTreeRoot,
	dealBTreeSubTree,
	dealBTreeData,
	dealBTreeComma,
	dealBTreeRightBk,
	dealBTreeEnd,
};

static void dealBTreeEnd(BTREE_ARG *arg, int ch) {
	arg->finished = TRUE;
}

static void dealBTreeRightBk(BTREE_ARG *arg, int ch) {
	if (',' == ch) {
		dealComma(arg);
	} else if (')' == ch) {
		dealRightBracket(arg);
	} else {
		arg->status = BTREE_STATUS_END;
	}
}

static void dealBTreeComma(BTREE_ARG *arg, int ch) {
	if (')' == ch) {
		dealRightBracket(arg);
	} else if (isData(ch)) {
		dealNode(arg, ch);
	} else {
		arg->ok = FALSE;
		errMess = "此处希望出现\"数据\"或\")\"。";
	}
}

static void dealBTreeData(BTREE_ARG *arg, int ch) {
	if ('(' == ch) {
		dealLeftBracket(arg);
	} else if (',' == ch) {
		dealComma(arg);
	} else if (')' == ch) {
		dealRightBracket(arg);
	} else {
		arg->ok = FALSE;
		errMess = "此处希望出现\")\"或\",\"。";
	}
}

static void dealBTreeSubTree(BTREE_ARG *arg, int ch) {
	if (isData(ch)) {
		dealNode(arg, ch);
	} else if (',' == ch) {
		dealComma(arg);
	} else {
		arg->ok = FALSE;
		errMess = "此处希望出现\"数据\"或\",\"。";
	}
}

static void dealBTreeRoot(BTREE_ARG *arg, int ch) {
	if ('(' == ch) {
		dealLeftBracket(arg);
	} else {
		arg->status = BTREE_STATUS_END;
	}
}

static void dealBTreeBegin(BTREE_ARG *arg, int ch) {
	if (isData(ch)) {
		dealRoot(arg, ch);
	} else {
		arg->status = BTREE_STATUS_END;
	}
}

boolean createBTree(const char *str, B_TREE **root) {
	BTREE_ARG arg = {
		BTREE_STATUS_BEGIN,		// int status;
		TRUE,					// boolean ok;
		FALSE,					// boolean finished;
		0,						// int index;
		LEFT_CHILD,				// boolean whichChild;
		NULL,					// B_TREE *root;
		NULL,					// B_TREE *tmp;
		NULL, 					// MEC_STACK *stack;
	};
	int ch;
	int stackCapacity;

	if (NULL == str || NULL == root || NULL != *root) {
		return FALSE;
	}
	stackCapacity = getStackDeep(str);
	if (stackCapacity < 0) {
		arg.ok = FALSE;
		errMess = LEFT_BRACKET_TOO_MUCH == stackCapacity
			? "括号不匹配,左括号多余!"
			: "括号不匹配,右括号多余!";
	} else {
		initStack(&arg.stack, stackCapacity);
	}


	while (arg.ok && !arg.finished) {
		arg.index += skipBlank(str + arg.index);
		ch = str[arg.index];

		functions[arg.status](&arg, ch);
	}

	destoryStack(&arg.stack);

	if (arg.ok) {
		*root = arg.root;
	} else {
		destoryBTree(arg.root);
	}

	return arg.ok;
}

void firstRootVisited(const B_TREE *root) {
	if (NULL == root) {
		return;
	}
	printf("%c ", root->data);
	firstRootVisited(root->left);
	firstRootVisited(root->right);
}

void middleRootVisited(const B_TREE *root) {
	if (NULL == root) {
		return;
	}
	middleRootVisited(root->left);
	printf("%c ", root->data);
	middleRootVisited(root->right);
}

void lastRootVisited(const B_TREE *root) {
	if (NULL == root) {
		return;
	}
	lastRootVisited(root->left);
	lastRootVisited(root->right);
	printf("%c ", root->data);
}

void destoryBTree(B_TREE **root) {
	if (NULL == root) {
		return;
	}
	destoryBTree(root->left);
	destoryBTree(root->right);
	free(root);
}



btree.h

#ifndef _MEC_BINATRY_TREE_H_
#define _MEC_BINATRY_TREE_H_

typedef struct B_TREE {
	int data;
	struct B_TREE *left;
	struct B_TREE *right;
}B_TREE;

boolean createBTree(const char *str, B_TREE **root);
void destoryBTree(B_TREE **root);
void firstRootVisited(const B_TREE *root);
void middleRootVisited(const B_TREE *root);
void lastRootVisited(const B_TREE *root);

#endif

猜你喜欢

转载自blog.csdn.net/weixin_45483328/article/details/107921000