1.树的概念及结构
1.1 基本概念
树是一种非线性的数据结构,它是由n个有限结点组成一个具有层次关系的集合。
- 有一个特殊的结点,称为根结点,根结点没有前驱结点
- 每棵子树的根结点有且只有一个前驱,可以有0个或多个后继
- 树是递归定义的(根结点+子树)
1.2 树的存储表示
树有多种表示方式:如:双亲表示法,孩子表示法,孩子兄弟表示法等。常用孩子兄弟表示法
typedef int DataType;
struct Node
{
struct Node* _fristchild1; //第一个孩子结点
struct Node* _pNextBrother; //指向其下一个兄弟结点
DataType _data; //结点中的数据域
};
2.二叉树的概念及性质
2.1 概念
- 一棵二叉树是结点的一个有限集合,该集合或者为空,或者是由一个根结点加上两棵分别为左子树和右子树的二叉树组成。
- 每个结点最多有两棵子树,即二叉树不存在度大于2的结点
- 二叉树的子树有左右之分,其子树的次序不能颠倒
2.2 特殊的二叉树
1.满二叉树: 一个二叉树,如果每一层的结点数都达到最大值,则这个二叉树就是满二叉树。如果一个二叉树的层数为k,且结点总数是(2^k)-1,则它就是满二叉树。
2.完全二叉树: 对于深度为k的,有n个结点的二叉树,当且仅当其每一个结点都与深度为k的满二叉树中编号从1至n的结点一一对应时,称之为完全二叉树。(满二叉树是一种特殊的完全二叉树)
2.3 二叉树的存储结构
- 顺序存储结构:使用数组来存储,最适用于存储完全二叉树。二叉树顺序存储在物理上是一个数组,在逻辑上是一棵二叉树。
- 链式存储结构:用链表指示元素的逻辑关系。通常链表中每个结点由三个域组成,数据域和左右指针域。
2.4 二叉树的性质
1. 若规定根节点的层数为1,则一棵非空二叉树的第i层上最多有2^(i-1)个结点.
2. 若规定根节点的层数为1,则深度为h的二叉树的最大结点数是2^h - 1.
3. 对任何一棵二叉树, 如果其叶结点个数为 n0, 度为2的非叶结点个数为 n2,则有n0=n2+1
4. 具有n个结点的完全二叉树的深度h=Log2(n+1). (ps:Log2(n+1)是log以2为底,n+1为对数)
5. 对于具有n个结点的完全二叉树,如果按照从上至下从左至右的数组顺序对所有节点从0开始编号,则对
于序号为i的结点有:
若i>0,i位置节点的双亲序号:(i-1)/2;i=0,i为根节点编号,无双亲节点
若2i+1<n,左孩子序号:2i+1,2i+1>=n否则无左孩子
若2i+2<n,右孩子序号:2i+2,2i+2>=n否则无右孩子
3.二叉树链式结构的实现
3.1 二叉树链式结构的遍历
所谓遍历(Traversal)是指沿着某条搜索路线,依次对树中每个结点均做一次且仅做一次访问。访问结点所做的操作依赖于具体的应用问题.
- NLR: 前序遍历(Preorder Traversal 亦称先序遍历): 根->左子树->右子树
- LNR: 中序遍历(Inorder Traversal): 左子树->根->右子树
- LRN:后序遍历(Postorder Traversal):左子树->右子树->根
- 层序遍历:层序遍历就是从所在二叉树的根结点出发,首先访问第一层的树根结点,然后自上而下,自左至右逐层访问树的结点的过程。
3.2 二叉树的基本操作实现(递归实现)
typedef char BTDataType;
typedef struct BinaryTreeNode
{
BTDataType _data;
struct BinaryTreeNode* _left;
struct BinaryTreeNode* _right;
}BTNode;
// 二叉树的初始化
void BinaryTreeInit(BTNode** root)
{
assert(root);
if (*root == NULL)
return;
*root = NULL;
return;
}
// 通过前序遍历的数组"ABD##E#H##CF##G##"构建二叉树
BTNode* BinaryTreeCreate(BTDataType* a, int* Index)
{
BTNode* root;
if (a[*Index] == '#')
return NULL;
root = (BTNode*)malloc(sizeof(BTNode));
root->_data = a[*Index];
++(*Index);
root->_left = BinaryTreeCreate(a, Index);
++(*Index);
root->_right = BinaryTreeCreate(a, Index);
return root;
}
// 二叉树销毁
void BinaryTreeDestory(BTNode** root)
{
if (*root)
{
BinaryTreeDestory((*root)->_left);
BinaryTreeDestory((*root)->_right);
free(*root);
*root = NULL;
}
}
// 二叉树结点个数
int BinaryTreeSize(BTNode* root)
{
if (root == NULL)
return 0;
return BinaryTreeSize(root->_left) + BinaryTreeSize(root->_right) + 1;
}
// 二叉树叶子结点个数
// 二叉树叶子结点个数 = 左子树叶子结点个数 + 右子树叶子结点个数
int BinaryTreeLeafSize(BTNode* root)
{
if (root == NULL)
return 0;
if (root->_left == NULL&&root->_right == NULL)
return 1;
return BinaryTreeLeafSize(root->_left) + BinaryTreeLeafSize(root->_right);
}
// 二叉树第k层结点个数
int BinaryTreeLevelKSize(BTNode* root, int k)
{
if (root == NULL)
return 0;
if (k == 1)
return 1;
return BinaryTreeLevelKSize(root->_left, k - 1) + BinaryTreeLevelKSize(root->_right, k - 1);
}
// 二叉树的高度
int BinaryTreeHeight(BTNode* root)
{
if (root == NULL)
return 0;
int leftheight = BinaryTreeHeight(root->_left) + 1;
int rightheight = BinaryTreeHeight(root->_right) + 1;
return rightheight > leftheight ? rightheight : leftheight;
}
// 求二叉树的镜像
// 递归的交换二叉树的左右子树
void BinaryTreeMirror(BTNode* root)
{
if (root == NULL)
return;
BTNode* tmp = root->_left;
root->_left = root->_right;
root->_right = tmp;
BinaryTreeMirror(root->_left);
BinaryTreeMirror(root->_right);
return;
}
// 二叉树查找值为x的结点
BTNode* BinaryTreeFind(BTNode* root, BTDataType x)
{
BTNode* ret;
if (root == NULL)
{
return NULL;
}
//根节点
if (root->_data == x)
{
return root;
}
//找左子树
ret = BinaryTreeFind(root->_left, x);
if (ret)
{
return ret;
}
//左子树找不到, 找右子树
ret = BinaryTreeLeafSize(root->_right, x);
if (ret)
{
return ret;
}
//没找到
return NULL;
}
// 二叉树前序遍历
void BinaryTreePrevOrder(BTNode* root)
{
if (root)
{
printf("%c ", root->_data);
BinaryTreePrevOrder(root->_left);
BinaryTreePrevOrder(root->_right);
}
}
// 二叉树中序遍历
void BinaryTreeInOrder(BTNode* root)
{
if (root)
{
BinaryTreeInOrder(root->_left);
printf("%c ", root->_data);
BinaryTreeInOrder(root->_right);
}
}
// 二叉树后序遍历
void BinaryTreePostOrder(BTNode* root)
{
if (root)
{
BinaryTreePostOrder(root->_left);
BinaryTreePostOrder(root->_right);
printf("%c ", root->_data);
}
}
// 层序遍历
void BinaryTreeLevelOrder(BTNode* root)
{
Queue q;
QueueInit(&q);
if (root != NULL)
QueuePush(&q, root);
while (!QueueIsEmpty(&q))
{
BTNode* front = QueueFront(&q);
printf("%c ", front->_data);
QueuePop(&q);
if (front->_left)
QueuePush(&q, front->_left);
if (front->_right)
QueuePush(&q, front->_right);
}
printf("\n");
}
// 判断二叉树是否是完全二叉树
int BinaryTreeComplete(BTNode* root)
{
Queue q;
QueueInit(&q);
if (root != NULL)
QueuePush(&q, root);
while (!QueueIsEmpty(&q))
{
BTNode* front = QueueFront(&qu);
QueuePop(&q);
if (front == NULL)
break;
QueuePush(&q, front->_left);
QueuePush(&q, front->_right);
}
while (!QueueIsEmpty(&q))
{
BTNode* front = QueueFront(&qu);
QueuePop(&q);
if(front != NULL)
{
QueueDestroy(&q);
return -1;
}
}
return 0;
}
//测试
int main()
{
char a[] = "ABD##E#H##CF##G##";
int index = 0;
BTNode* tree = BinaryTreeCreate(a, &index);
printf("Size:%d\n", BinaryTreeSize(tree));
printf("Leaf Size:%d\n", BinaryTreeLeafSize(tree));
printf("K Level:%d\n", BinaryTreeLevelKSize(tree,3));
printf("Height:%d\n", BinaryTreeHeight(tree));
BinaryTreeLevelOrder(tree);
printf("Tree Complete: %d\n",BinaryTreeComplete(tree));
return 0;
}