目录
一、树的概念及结构
1.1树的概念
1.2树的相关概念
1.3树的表示
1.4树在实际中的应用(目录树)
二、二叉树概念及结构
2.1概念
2.2特殊的二叉树
2.3二叉树的性质
2.4二叉树存储结构
三、二叉树的顺序结构及实现
3.1二叉树的顺序结构
3.2堆的结构及概念
四、二叉树的链式结构及实现
五、二叉树的遍历(前序、中序、后序、层序遍历)
5.1前序遍历
5.2中序遍历
5.3后序遍历
5.4层序遍历
六、求二叉树的节点个数、叶子节点个数、高度、查找节点等功能
6.1二叉树节点的个数
6.2二叉树叶子节点的个数
6.3二叉树的高度
6.4二叉树第K层节点的个数
6.5查找节点
6.6二叉树度为1的节点个数
七、创建二叉树、销毁二叉树
7.1创建二叉树
7.2销毁二叉树
八、判断二叉树是否为完全二叉树
九、OJ练习——二叉树部分
9.1检查两颗树是否相同
9.2单值二叉树
9.3翻转二叉树
9.4对称二叉树
9.5另一颗数的子树
9.6判断一颗二叉树是否是平衡二叉树
typedef int DataType;struct Node{struct Node* _firstChild1; // 第一个孩子结点struct Node* _pNextBrother; // 指向其下一个兄弟结点DataType _data; // 结点中的数据域};
注意:
2.链式存储:二叉树的链式存储结构是指,用链表来表示一棵二叉树,即用链来指示元素的 逻辑关系。 通常的方法是链表中每个结点由三个域组成,数据域和左右指针域 左右指针分别用来给出该结点左孩子和右孩子所在的链结点的存储地址 。
链式结构又分为二叉链和三叉链,当前我们学习中一般都是二叉链。
typedef int BTDataType;// 二叉链struct BinaryTreeNode{struct BinTreeNode* _pLeft; // 指向当前节点左孩子struct BinTreeNode* _pRight; // 指向当前节点右孩子BTDataType _data; // 当前节点值域}// 三叉链struct BinaryTreeNode{struct BinTreeNode* _pParent; // 指向当前节点的双亲struct BinTreeNode* _pLeft; // 指向当前节点左孩子struct BinTreeNode* _pRight; // 指向当前节点右孩子BTDataType _data; // 当前节点值域};
有关堆的结构及概念,堆的实现和应用,请看上一篇:http://t.csdn.cn/Dbj44
树的简单的创建:
typedef int BTDataType;typedef struct BinaryTreeNode{BTDataType _data;struct BinaryTreeNode* _left;struct BinaryTreeNode* _right;}BTNode;BTNode* CreatBinaryTree(){BTNode* node1 = BuyNode(1);BTNode* node2 = BuyNode(2);BTNode* node3 = BuyNode(3);BTNode* node4 = BuyNode(4);BTNode* node5 = BuyNode(5);BTNode* node6 = BuyNode(6);node1->_left = node2;node1->_right = node4;node2->_left = node3;node4->_left = node5;node4->_right = node6;return node1;}
前序遍历——访问根结点的操作发生在遍历其左右子树之前。
代码:
void PrevOrder(TNode* root)
{
if (root == NULL)
{
printf("N ");
return;
}
printf("%d ", root->data);
PrevOrder(root->lchild);
PrevOrder(root->rchild);
}
递归展开图:
中序遍历——访问根结点的操作发生在遍历其左右子树之中(间)。
代码:
void InOrder(TNode* root)
{
if (root == NULL)
{
printf("N ");
return;
}
InOrder(root->lchild);
printf("%d ", root->data);
InOrder(root->rchild);
}
递归展开图:
后序遍历——访问根结点的操作发生在遍历其左右子树之后。
代码:
void PostOrder(TNode* root)
{
if (root == NULL)
{
printf("N ");
return;
}
PostOrder(root->lchild);
PostOrder(root->rchild);
printf("%d ", root->data);
}
递归展开图:
层序遍历——设二叉树的根节点所在 层数为1,层序遍历就是从所在二叉树的根节点出发,首先访问第一层的树根节点,然后从左到右访问第2层 上的节点,接着是第三层的节点,以此类推,自上而下,自左至右逐层访问树的结点的过程就是层序遍历。
层序遍历思想:要借助队列来完成,将根节点入队列,然后开始循环,若队列为空就循环结束,每次出来队头的数据,在队头的数据出去之后要立即将出去的那个节点的孩子入队列(孩子为空就不入队列)
代码:
void LevelOrder(TNode* root)
{
if (root == NULL)
{
return;
}
Queue q;
QueueInit(&q);
//进队列
QueuePush(&q, root);
while (!QueueEmpty(&q))
{
TNode* node = QueueFront(&q);
QueuePop(&q);
printf("%d ", node->data);
if (node->lchild)
QueuePush(&q, node->lchild);
if (node->rchild)
QueuePush(&q, node->rchild);
}
printf("\n");
}
int BTreeSize(TNode* root)
{
if (root == NULL)
{
return 0;
}
return BTreeSize(root->lchild) + BTreeSize(root->rchild) + 1;
}
int BTreeLeafSize(TNode* root)
{
if (root == NULL)
{
return 0;
}
if (root->lchild == NULL && root->rchild == NULL)
{
return 1;
}
return BTreeLeafSize(root->lchild) + BTreeLeafSize(root->rchild);
}
int BTreeHeight(TNode* root)
{
if (root == NULL)
{
return 0;
}
int leftHeight = BTreeHeight(root->lchild);
int rightHeight = BTreeHeight(root->rchild);
return leftHeight > rightHeight ? leftHeight + 1 : rightHeight + 1;
}
int BTreeLevelKSize(TNode* root, int k)
{
if (root == NULL)
{
return 0;
}
if (k == 1)
{
return 1;
}
return BTreeLevelKSize(root->lchild, k - 1) + BTreeLevelKSize(root->rchild, k - 1);
}
TNode* BTreeFind(TNode* root, BTDataType x)
{
if (root == NULL)
{
return NULL;
}
if (root->data == x)
{
return root;
}
TNode* left = BTreeFind(root->lchild, x);
if (left)
return left;
TNode* right = BTreeFind(root->rchild, x);
if (right)
return right;
return NULL;
}
int BTreeDeg1Size(TNode* root)
{
if (root == NULL)
{
return 0;
}
int left = BTreeDeg1Size(root->lchild);
int right = BTreeDeg1Size(root->rchild);
if ((root->lchild == NULL && root->rchild != NULL)
|| (root->lchild != NULL && root->rchild == NULL))
{
return left + right + 1;
}
else
{
return left + right;
}
}
TNode* TCreateTree(char* tree, int* pi)
{
if (tree[*pi] == '#')
{
(*pi)++;
return NULL;
}
TNode* root = (TNode*)malloc(sizeof(TNode));
root->data = tree[*pi];
(*pi)++;
root->lchild = TCreateTree(tree, pi);
root->rchild = TCreateTree(tree, pi);
return root;
}
void DestoryTree(TNode* root)
{
if (root == NULL)
{
return;
}
DestoryTree(root->lchild);
DestoryTree(root->rchild);
free(root);
}
借助队列,将一个二叉树层序遍历进入队列,遇到NULL也进入队列,直到出队列时遇到NULL停止,判断此时队列中是否存在非NULL元素,如果存在,不是完全二叉树,如果全为NULL,是完全二叉树。
bool BTreeComplete(TNode* root)
{
Queue q;
QueueInit(&q);
if (root)
QueuePush(&q, root);
while (!QueueEmpty(&q))
{
TNode* front = QueueFront(&q);
QueuePop(&q);
if (front != NULL)
{
QueuePush(&q, front->lchild);
QueuePush(&q, front->rchild);
}
else
{
break;
}
}
while (!QueueEmpty(&q))
{
TNode* front = QueueFront(&q);
QueuePop(&q);
if (front != NULL)
{
QueueDestory(&q);
return false;
}
}
QueueDestory(&q);
return true;
}
bool isSameTree(struct TreeNode* p, struct TreeNode* q){
if(p == NULL && q == NULL)
{
return true;
}
if(p == NULL || q == NULL)
{
return false;
}
if(p->val != q->val)
{
return false;
}
return isSameTree(p->left, q->left) && isSameTree(p->right, q->right);
}
bool isUnivalTree(struct TreeNode* root){
if(root == NULL)
{
return true;
}
if(root->left!= NULL && root->val != root->left->val)
{
return false;
}
if(root->right!= NULL && root->val != root->right->val)
{
return false;
}
return isUnivalTree(root->left) && isUnivalTree(root->right);
}
struct TreeNode* invertTree(struct TreeNode* root){
if(root == NULL)
{
return NULL;
}
//保存一下原来的左孩子
struct TreeNode* left = root->left;
root->left = invertTree(root->right);
root->right = invertTree(left);
return root;
}
bool _isSymmetric(struct TreeNode* r1, struct TreeNode* r2)
{
if(r1 == NULL && r2 == NULL)
{
return true;
}
if(r1 == NULL || r2 == NULL)
{
return false;
}
if(r1->val != r2->val)
{
return false;
}
return _isSymmetric(r1->left, r2->right) && _isSymmetric(r1->right, r2->left);
}
bool isSymmetric(struct TreeNode* root){
return _isSymmetric(root->left, root->right);
}
bool isSameTree(struct TreeNode* p, struct TreeNode* q){
if(p == NULL && q == NULL)
{
return true;
}
if(p == NULL || q == NULL)
{
return false;
}
if(p->val != q->val)
{
return false;
}
return isSameTree(p->left, q->left) && isSameTree(p->right, q->right);
}
bool isSubtree(struct TreeNode* root, struct TreeNode* subRoot){
if(root == NULL && subRoot == NULL)
{
return true;
}
if(root == NULL || subRoot == NULL)
{
return false;
}
if(isSameTree(root, subRoot))
{
return true;
}
return isSubtree(root->left, subRoot) || isSubtree(root->right, subRoot);
}
int BTreeHeight(struct TreeNode* root)
{
if (root == NULL)
{
return 0;
}
int leftHeight = BTreeHeight(root->left);
int rightHeight = BTreeHeight(root->right);
return leftHeight > rightHeight ? leftHeight + 1 : rightHeight + 1;
}
bool isBalanced(struct TreeNode* root){
if(root == NULL)
{
return true;
}
int left = BTreeHeight(root->left);
int right = BTreeHeight(root->right);
int sub = abs(left - right);
if(sub > 1)
{
return false;
}
return isBalanced(root->left) && isBalanced(root->right);
}