二叉树生成及遍历
前言:由于这样介绍的为二叉树,这里只介绍关于树的基本概念。
一、树的简介
树是一种数据结构,它是由n(n>0)个有限结点组成的一个具有层次关系的集合。树的每个结点有零个或多个子节点,没有父结点的结点称为根节点;每一个非根结点有且仅有一个父节点,除了根节点外,每个子节点可以分为多个不相交的子树。
二、二叉树简介
(摘自百度)二叉树(Binary tree)是树形结构的一个重要类型。许多实际问题抽象出来的数据结构往往是二叉树形式,即使是一般的树也能简单地转换为二叉树,而且二叉树的存储结构及其算法都较为简单,因此二叉树显得特别重要。二叉树特点是每个结点最多只能有两棵子树,且有左右之分。
满二叉树:一个高度为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 ) ) )
在处理这个字符串之前,我们需要将整个流程过一遍。
我们发现,这里共存在七个状态:开始、根、子树、数据、逗号、右括号、结束
这就构建起了整个生成二叉树的体系结构。
细化到每个状态,应该做什么,怎么做,可以慢慢的去优化。
在数据前面如果是左括号的话,那么,这个数据一定是上一个数据的左孩子,当遇到“,”时,后面无论如何,都会变为右孩子状态。
存储数据使用的的堆栈,遇到左括号,将左括号之前的数据入栈,遇到右括号,将栈顶元素出栈。
四、二叉树的递归
二叉树的遍历中,递归是一种很好的方法
二叉树的表示有三种:先根序 :根 (左子树) (右子树)
中跟序:(左子树) 根 (右子树)
后根序:(左子树) (右子树) 根。
上面的三种方法,充满了浓浓的递归的味道。访问顺序即是递归顺序。
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