树的数据结构
typedef struct BinaryTreeNode
{
int data;
struct BinaryTreeNode* left;
struct BinaryTreeNode* right;
}Node;
Node* createBinaryTree()
{
Node* p;
int ch;
cin >> ch;
if (ch == 0)
{
p = NULL;
}
else
{
p = (Node*)malloc(sizeof(Node));
p->data = ch;
p->left = createBinaryTree();//先序创建树
p->right = createBinaryTree();
}
return p;
}
void inOrderTraverse(Node* root)
{
if (root)
{
inOrderTraverse(root->left);
cout << root->data << ' ';
inOrderTraverse(root->right);
}
}
void preOrderTraverse(Node* root)
{
if (root)
{
cout << root->data << ' ';
preOrderTraverse(root->left);
preOrderTraverse(root->right);
}
}
void lastOrderTraverse(Node* root)
{
if (root)
{
lastOrderTraverse(root->left);
lastOrderTraverse(root->right);
cout << root->data<<' ';
}
}
int Nodenum(Node* root)
{
if (root == NULL)
{
return 0;
}
else
{
return 1 + Nodenum(root->left) + Nodenum(root->right);
}
}
int DepthofTree(Node* root)
{
if (root)
{
return DepthofTree(root->left) > DepthofTree(root->right) ? DepthofTree(root->left) + 1 : DepthofTree(root->right) + 1;
}
if (root == NULL)
{
return 0;
}
}
int Leafnum(Node* root)
{
if (!root)
{
return 0;
}
else if ((root->left == NULL) && (root->right == NULL))
{
return 1;
}
else
{
return (Leafnum(root->left) + Leafnum(root->right));
}
}
int main()
{
Node* p;
p = createBinaryTree();
preOrderTraverse(p);
//preOrderTraverse(p);
//cout << endl;
//inOrderTraverse(p);
//cout << endl;
//lastOrderTraverse(p);
//cout << endl;
//cout << Nodenum(p) << endl;
//cout << DepthofTree(p)<<endl;
//cout << Leafnum(p);
}
树的基本知识
森林:对于根节点Root,森林是根节点所有的子树。
结点的度:结点的度是其子树的个数。
树的度:树中所有结点中最大的度数。
兄弟结点:有同一个父节点的结点。
祖先结点:沿着根节点到某个结点路径上的点都是某个节点的祖先结点
子孙结点:某一结点的子树中的所有结点。
结点的层次:结点的层数,根节点为1层,往下一层加1
树的深度:结点中的最大层次
树的高度:从叶子结点从下往上计数,叶子结点高度为1
树的高度=树的深度
二叉树基本概念
二叉树定义:由根节点和其左右两棵子树Tl和TR构成
满二叉树:所有的分支结点都有左右子树,叶子结点都在同一层上。
完全二叉树:树中所有的结点号都和满二叉树的结点号相同。
性质:1.二叉树第i层的最大节点数为2^i-1
2.深度为k的二叉树最大的结点总数为(2^k)-1 k>=1
3.n0表示叶子结点个数,n1度为1的结点个数,n2表示度为2的结点个数,则有n0=n2+1
二叉树存储结构性质
在N个结点的完全二叉树中,对于下标为i的结点:
1.当i/2>=1时,i/2是它的父节点。当i/2=0时,该节点是树的根节点。
2.当2i<=N时,2i是它的左孩子。
3.当2i+1<=N时,2i+1是它的右孩子。
(以上性质i的起始下标是1)
二叉树的遍历
以此图为例
任何树的中序和先序遍历唯一(两种遍历确定一棵树)
先序遍历(中左右)
6 2 1 4 3 8
中序遍历(左中右)
1 2 3 4 6 8
后序遍历(左右中)
1 3 4 2 8 6
二叉搜索树性质
定义:
1.非空左子树的所有键值小于根节点键值
2.非空右子树的所有键值大于根节点键值
3.左右子树都是二叉搜索树
Ex:
二叉搜索树的方法
1.搜索:如果查找的值x比结点大则搜索结点的右子树,反之搜索左子树。如果相等则输出
2.搜索最小:根据二叉搜索树性质,最小值是树的最左叶子结点。迭代搜索深度最大、最靠左的叶子结点
3.搜索最大:根据二叉搜索树性质,最大值是树的最右叶子结点。迭代搜索深度最大、最靠右的叶子结点
4.删除
删除分3种情况:
4.1删除的结点是叶子结点:直接删除
4.2删除的结点有一个子结点:将删除结点的父节点指针指向删除结点的子结点
4.3删除的结点有两个子节点:有两种方法
法1:选择删除结点的左子树中最大结点替代删除结点
法2:选择删除结点的右子树中最小结点替代删除结点(以下采用法2)
法1示例:
//二叉查找指定数值
Node* Find(Node* tree, int x)
{
while (tree)
{
if (x > tree->data)
{
tree = tree->right;
}
else if (x < tree->data)
{
tree = tree->left;
}
else
break;
}
return tree;
}
//二叉查找最小
Node* FindMin(Node* tree)
{
if (!tree)return NULL;
else if (!tree->left) return tree;
else return FindMin(tree->left);
}
//二叉查找最大
Node* FindMax(Node* tree)
{
if (tree)
{
while (tree->right)
tree = tree->right;
return tree;
}
}
//二叉树插入算法
Node* Insert(Node* tree, int x)
{
if (!tree)
{
tree = (Node*)malloc(sizeof(struct BinaryTreeNode));
tree->data = x;
tree->left = tree->right = NULL;
}
else
{
if (x < tree->data)
{
tree->left = Insert(tree->left, x);
}
else if (x > tree->data)
{
tree->right = Insert(tree->right, x);
}
}
return tree;
}
//二叉树删除算法
Node* Delete(Node* tree, int x)
{
Node* tmp;
if (!tree)
{
printf_s("删除失败");
}
else
{
if (x < tree->data)
tree->left = Delete(tree->left, x);
else if (x > tree->data)
tree->right = Delete(tree->right, x);
else
{
if (tree->left && tree->right)
{
tmp = FindMin(tree->right);
tree->data = tmp->data;
tree->right = Delete(tree->right, tree->data);
}
else
{
tmp = tree;
if (!tree->left)
{
tree = tree->right;
}
else
tree = tree->left;
free(tmp);
}
}
}
return tree;
}
平衡二叉树
定义:1.任意结点的左右子树均为AVL树
2.根据点左右子树高度差的绝对值不超过1
平衡因子:任意结点的平衡因子BF(T)=hL-hR,hL,hR分别代表结点T的左右子树的高度。
平衡二叉树的调整
1.单旋转
1.1当结点A在右子树结点B插入右结点C时,A的高度为-2,不在{-1,0,1}之间。此时三个结点右斜,需要通过右单旋调整。
1.2当结点A在子树结点B插入左结点C时,A的高度为2,不在{-1,0,1}之间。此时三个结点右斜,需要通过左单旋调整。
2双旋转
当结点A在右子树结点B插入左结点C时,A的高度为-2,不在{-1,0,1}之间。此时三个结点右斜,需要通过右-左双旋调整。
当结点A在左子树结点B插入右结点C时,A的高度为2,不在{-1,0,1}之间。此时三个结点右斜,需要通过左-右双旋调整。
完整代码
#include<stdio.h>
#include<iostream>
using namespace std;
typedef struct BinaryTreeNode
{
int data;
struct BinaryTreeNode* left;
struct BinaryTreeNode* right;
}Node;
//二叉查找指定数值
Node* Find(Node* tree, int x)
{
while (tree)
{
if (x > tree->data)
{
tree = tree->right;
}
else if (x < tree->data)
{
tree = tree->left;
}
else
break;
}
return tree;
}
//二叉查找最小
Node* FindMin(Node* tree)
{
if (!tree)return NULL;
else if (!tree->left) return tree;
else return FindMin(tree->left);
}
//二叉查找最大
Node* FindMax(Node* tree)
{
if (tree)
{
while (tree->right)
tree = tree->right;
return tree;
}
}
//二叉树插入算法
Node* Insert(Node* tree, int x)
{
if (!tree)
{
tree = (Node*)malloc(sizeof(struct BinaryTreeNode));
tree->data = x;
tree->left = tree->right = NULL;
}
else
{
if (x < tree->data)
{
tree->left = Insert(tree->left, x);
}
else if (x > tree->data)
{
tree->right = Insert(tree->right, x);
}
}
return tree;
}
//二叉树删除算法
Node* Delete(Node* tree, int x)
{
Node* tmp;
if (!tree)
{
printf_s("删除失败");
}
else
{
if (x < tree->data)
tree->left = Delete(tree->left, x);
else if (x > tree->data)
tree->right = Delete(tree->right, x);
else
{
if (tree->left && tree->right)
{
tmp = FindMin(tree->right);
tree->data = tmp->data;
tree->right = Delete(tree->right, tree->data);
}
else
{
tmp = tree;
if (!tree->left)
{
tree = tree->right;
}
else
tree = tree->left;
free(tmp);
}
}
}
return tree;
}
Node* createBinaryTree()
{
Node* p;
int ch;
cin >> ch;
if (ch == 0)
{
p = NULL;
}
else
{
p = (Node*)malloc(sizeof(Node));
p->data = ch;
p->left = createBinaryTree();//先序创建树
p->right = createBinaryTree();
}
return p;
}
void inOrderTraverse(Node* root)
{
if (root)
{
inOrderTraverse(root->left);
cout << root->data << ' ';
inOrderTraverse(root->right);
}
}
void preOrderTraverse(Node* root)
{
if (root)
{
cout << root->data << ' ';
preOrderTraverse(root->left);
preOrderTraverse(root->right);
}
}
void lastOrderTraverse(Node* root)
{
if (root)
{
lastOrderTraverse(root->left);
lastOrderTraverse(root->right);
cout << root->data<<' ';
}
}
int Nodenum(Node* root)
{
if (root == NULL)
{
return 0;
}
else
{
return 1 + Nodenum(root->left) + Nodenum(root->right);
}
}
int DepthofTree(Node* root)
{
if (root)
{
return DepthofTree(root->left) > DepthofTree(root->right) ? DepthofTree(root->left) + 1 : DepthofTree(root->right) + 1;
}
if (root == NULL)
{
return 0;
}
}
int Leafnum(Node* root)
{
if (!root)
{
return 0;
}
else if ((root->left == NULL) && (root->right == NULL))
{
return 1;
}
else
{
return (Leafnum(root->left) + Leafnum(root->right));
}
}
int main()
{
Node* p;
p = createBinaryTree();
preOrderTraverse(p);
cout << endl;
inOrderTraverse(p);
cout << endl;
lastOrderTraverse(p);
//cout << endl;
//cout << Nodenum(p) << endl;
//cout << DepthofTree(p)<<endl;
//cout << Leafnum(p);
}
参考
https://blog.csdn.net/floating_fight/article/details/103016279