树
树
基本定义
由n(n>0)节点构成的有限集,构成一种层次的线性结构,在任意的一颗非空树中:
-
有且只有一个根节点
-
当n>1时,其余的节点可以分为m个互不相交的有限集,每个节点都可以看为一颗树
入度 <= 1;
出度 任意
结点的度: 出度数量
结点的层次(高度): 相对与根结点的距离
特殊的树(分而治之)
- 二叉树:度 <= 2
- 二叉搜索树(BST): 左 < 根 < 右
- 满二叉树: 除最底层外,结点度均为2
- 完全二叉树:满二叉树的最底层结点从左到右连续排列
树的基本性质
-
第n层的结点的个数<=
2^i-1
-
高度为K的二叉树最多:
2^0 + 2^1 + 2^1 + .....2^{k-1} = 2^k -1
- 对于任意一颗二叉树
N0+N1+N2 = N1+2*N2+1
N0=N2+1
-
一个完全二叉树
父结点的编号:
i/2
左子结点的编号:
2*i
右子结点的编号:
2*i+1
- 判断完全二叉树的最大深度k -已知总结点数量 n
k=log{2^n+1}
已知:此树为完全二叉树;总结点为n,
目标:
- 最后一个非叶子结点的位置 - n/2
- 叶子结点的总数 - (n+1)/2
叶子结点的总数:[n/2] (n+1)/2
解题思路:
求出最后一个叶子结点-n1,
求n1的父结点
树的实现
二叉排序树的创建
规则: 左 < 根 < 右
typedef int TreeElemtype;
typedef struct NODETREE
{
TreeElemtype data; //树中数据
struct NODETREE *left; //左子树
struct NODETREE *right; //右子树
} NodeTree;
typedef struct TREE
{
NodeTree *root; //根节点
int deep; //深度
} Tree
/*
treeAddNumD:递归插入树
参数:tree-目标树,num-插入元素
返回:下层树
*/
Tree treeAddNumD(Tree *tree,TreeElemtype num);
//测试数据
treeAddNumD(tree,4);
treeAddNumD(tree,2);
treeAddNumD(tree,6);
treeAddNumD(tree,1);
treeAddNumD(tree,2);
treeAddNumD(tree,5);
treeAddNumD(tree,7);

遍历方式
先序遍历
根 - 左 - 右
递归实现:

代码实现
void nTreePerOrderD(NodeTree *root)
{
if (root)
{
printf("%d ", root->data);
nTreePerOrderD(root->left);
nTreePerOrderD(root->right);
}
}
迭代实现:

代码实现
void nTreePerOrder(NodeTree *root)
{
Stack *stack = StackInit();
for (;;)
{
for (; root; root = root->left)
{
printf("%d ", root->data);
StackPush(stack, root);
}
root = StackPop(stack);
if (!root)
break;
root = root->right;
}
StackDel(stack);
}
中序遍历
左 - 根 - 右
后序遍历
左 - 右 - 根
层次遍历
迭代方式

代码实现
void nTreeLevelOrder(NodeTree *root)
{
Queue *queue = queueInit();
NodeTree *q ;
if(!root){
return ;
}
queueIn(queue,root);
for(;;){
q = queueOut(queue);
if(q)
{
printf("%d ",q->data);
if (q->left)
{
queueIn(queue,q->left);
}
if(q->right)
{
queueIn(queue,q->right);
}
}else
{
break;
}
}
queueDel(queue);
}
递归创建

代码实现
int nTreeAddNumD(Tree *tree, TreeElemtype num)
{
if (!tree)
{
return 1;
}
NodeTree *node = nodeTreeInit();
node->data = num;
if (!tree->root)
{
tree->deep = 1 ;
tree->root = node;
return 1;
}
int deep = 0; // 记录插入深度
nTreeAddNodeD(tree->root, node,&deep);
tree->deep > deep ? tree->deep : deep;
return 0;
}
NodeTree *nTreeAddNodeD(NodeTree *root, NodeTree *node,int* deep)
{
if (!root)
{
return node;
}
else
{
*deep = *deep+1;
if (node->data >= root->data)
{
root->right = nTreeAddNodeD(root->right,node,deep);
}else
{
root->left = nTreeAddNodeD(root->left,node,deep);
}
return root;
}
}
查找上限值

代码实现
NodeTree* nTreeCeilD(NodeTree *root, TreeElemtype num)
{
if (!root)
{
return NULL;
}
if (num == root->data)
{
return root;
}else if(num < root->data)
{
NodeTree* node = nTreeCeilD(root->left,num);
if (!node)
{
return root;
}else
{
return node;
}
}else
{
return nTreeCeilD(root->right,num);
}
}
删除节点

NodeTree *nTreeDelHas(NodeTree *root, TreeElemtype num)
{
if (!root)
{
return NULL;
}
if (num < root->data)
{
root->left = nTreeDelHas(root->left, num);
return root;
}
else if (num > root->data)
{
root->right = nTreeDelHas(root->right, num);
return root;
}
//查找
if (root->right)
{
if (root->left)
{
// 都存在
// 找替死鬼
NodeTree *p = root->right;
NodeTree *pre = root;
if (!p->left)
{
root->data = p->data;
root->right = p->right;
nodeTreeDel(p);
return root;
}
for(;p->left;pre=p,p=p->left);
root->data= p->data;
pre->left = p->right;
nodeTreeDel(p);
return root;
}
else
{
// 右存在
NodeTree *node = root->right;
nodeTreeDel(root);
return node;
}
}
else
{
if (root->left)
{
//左存在
NodeTree *node = root->left;
nodeTreeDel(root);
return node;
}
else
{
// 都不存在
nodeTreeDel(root);
return NULL;
}
}
}
平衡二叉树
左右子树的高度差不超过1;
平衡因子:左子树与右子树的高度之差的绝对值
不平衡结点:左右子树高度差大于1
破坏结点:新插入,导致结点不平衡的结点
1.插入之后,需要能够判断结点是否平衡
2.平衡处理
1. 左旋
1. 破坏结点在右子树的右边
2. 右旋
1. 破坏结点在左子树的左边
3. 左右旋
1. 破坏结点在左子树的右边
4. 右左旋
1. 破坏结点在右子树的左边

浙公网安备 33010602011771号