目录
树的基础
构建最小堆没补充,大家可以搜一下
树:Tree。
路径:从根到叶子,例如A->C->F。
路径长度:边的数目。
度:孩子数目。
二叉树(Binary Tree)
性质:
(1)k层的二叉树总结点最多为个。
(2)k层的二叉树总叶子节点最多个。
前两条结论基于满二叉树。
(3)任意二叉树中度为0的节点总比度为2的节点多一个。
总节点数=度0节点+度1节点+度2节点。
总节点数=度0节点*0+度1节点*1+度2节点*2+1。
度0节点=度2节点+1。
(4)n个节点的完全二叉树层。
完全二叉树:树中只允许最后一层有空缺,并且其空缺方式从右向左连续空缺。
例:完全二叉树叶子节点有124个,总结点最多有多少个:n0=124,n2=123,n1要么为0要么为1,得248。
第四条结论是得出的层数。
(5)一颗完全二叉树按照从上到下,从左到右的顺序从1开始编号,编号为i的节点如果满足2i<=n,则有左孩子,如果满足2i+1<=n,则有右孩子,父亲节点编号为1~n/2。
二叉搜索树BST
树中任意一个父亲节点都要满足,值大于整棵左子树,小于整颗右子树。
优化让BST分布均匀,就引出了平衡搜索树。
平衡搜索树
二叉平衡搜索树:AVL树,树中任意节点左右子树高度差不超过1。
红黑树:RBT,由颜色定的平衡。
B/B+树:多路平衡搜索树。
递归创建二叉树(前序)
用0来做标记,这种方法有个弊端,有一个数不能用比如这个0.
#include<iostream>
using namespace std;
typedef struct Tree
{
int val;
struct Tree* left;
struct Tree* right;
}BinaryTree;
void PreorderTraversal(BinaryTree* Ptree)
{
if (Ptree == NULL)return;
printf("%d ", Ptree->val);
PreorderTraversal(Ptree->left);
PreorderTraversal(Ptree->right);
}
void CreateBinaryTree(BinaryTree** Root)
{
int num;
cin >> num;
if (num == 0)return;
*Root= (BinaryTree*)malloc(sizeof(BinaryTree));
(*Root)->val = num;
(*Root)->left = NULL;
(*Root)->right = NULL;
CreateBinaryTree(&(*Root)->left);
CreateBinaryTree(&(*Root)->right);
}
int main()
{
BinaryTree* Root = NULL;
CreateBinaryTree(&Root);
PreorderTraversal(Root);
return 0;
}
二叉树递归遍历(深度)
前序:根 左 右
中序:左 根 右
后序: 左 右 根
前:BFAGDMCQRN
中:AFGMDBCRQN
后:AMDGFRNQCB
前序递归遍历:(1)打印当前父亲节点(2)处理左子树(3)处理右子树,终止条件树为空。
中后略。
代码里就直接创建个固定的二叉树,来看看前中后序遍历。
#include<iostream>
using namespace std;
typedef struct Tree
{
int val;
struct Tree* left;
struct Tree* right;
}BinaryTree;
BinaryTree* Create()
{
BinaryTree* Root = NULL;
Root = (BinaryTree*)malloc(sizeof(BinaryTree));
Root->val = 1;
Root->left= (BinaryTree*)malloc(sizeof(BinaryTree));
Root->left->val = 2;
Root->left->left = (BinaryTree*)malloc(sizeof(BinaryTree));
Root->left->left->val = 4;
Root->left->left->left = NULL;
Root->left->left->right = NULL;
Root->left->right = (BinaryTree*)malloc(sizeof(BinaryTree));
Root->left->right->val = 5;
Root->left->right->left = NULL;
Root->left->right->right = NULL;
Root->right = (BinaryTree*)malloc(sizeof(BinaryTree));
Root->right->val = 3;
Root->right->left = NULL;
Root->right->right = NULL;
return Root;
}
void PreorderTraversal(BinaryTree* Ptree)
{
if (Ptree == NULL)return;
printf("%d ", Ptree->val);
PreorderTraversal(Ptree->left);
PreorderTraversal(Ptree->right);
}
void InorderTraversal(BinaryTree* Ptree)
{
if (Ptree == NULL)return;
InorderTraversal(Ptree->left);
printf("%d ", Ptree->val);
InorderTraversal(Ptree->right);
}
void LastorderTraversal(BinaryTree* Ptree)
{
if (Ptree == NULL)return;
LastorderTraversal(Ptree->left);
LastorderTraversal(Ptree->right);
printf("%d ", Ptree->val);
}
int main()
{
BinaryTree* ptree = Create();
PreorderTraversal(ptree);
puts("");
InorderTraversal(ptree);
puts("");
LastorderTraversal(ptree);
puts("");
return 0;
}
创建完全二叉树(前序)
步骤:
(1)当前节点数组的申请
(2)数据向数组赋值
(3)指针关联(0~n/2)
#include<iostream>
using namespace std;
typedef struct Tree
{
int val;
struct Tree* left;
struct Tree* right;
}BinaryTree;
void PreorderTraversal(BinaryTree* Ptree)
{
if (Ptree == NULL)return;
printf("%d ", Ptree->val);
PreorderTraversal(Ptree->left);
PreorderTraversal(Ptree->right);
}
BinaryTree* CreateCBT(int arr[], int len)
{
if (arr == NULL || len <= 0)return NULL;
//节点数组申请
BinaryTree* ptree = (BinaryTree*)malloc(sizeof(BinaryTree) * len);
for (int i = 0; i < len; i++)
{
ptree[i].val = arr[i];
ptree[i].left = NULL;
ptree[i].right = NULL;
}
//左右关系关联
for (int i = 0; i < len / 2; i++)
{
if (2 * i + 1 <= len - 1)ptree[i].left = &(ptree[2 * i + 1]);
if (2 * i + 2 <= len - 1)ptree[i].right = &(ptree[2 * i + 2]);
}
return ptree;
}
int main()
{
BinaryTree* Root = NULL;
int arr[] = { 1,2,3,4,5,6,7,8,9 };
Root = CreateCBT(arr, sizeof(arr) / sizeof(arr[0]));
PreorderTraversal(Root);
return 0;
}
二叉树非递归遍历(深度)
(1)首先我们要借助栈
(2)处理:对根非空就打印保存,对左子树非空就打印保存,对左子树非空就打印保存,pop掉
(3)无节点等待处理结束
过程图:
前序:打印保存根节点,并往左找直到为空。
挨个出栈判断有没有右节点,2有右节点,右节点入栈并打印,然后往左找,直到为空重复上面操作。
3打印出栈,3往右找为空,栈空了,结束。
中序和前序一样,只不过不在如入栈时就打印,而是打印栈顶值,pop前打印。
后序:右子在跟上面标记一下,其余的和前序一样,然后需要判断一下右侧情况,右侧为空,或者处理过那就print,未处理就处理右子树。
#include<iostream>
#include<stack>
using namespace std;
typedef struct Tree
{
int val;
struct Tree* left;
struct Tree* right;
}BinaryTree;
BinaryTree* Create()
{
BinaryTree* Root = NULL;
Root = (BinaryTree*)malloc(sizeof(BinaryTree));
Root->val = 1;
Root->left = (BinaryTree*)malloc(sizeof(BinaryTree));
Root->left->val = 2;
Root->left->left = (BinaryTree*)malloc(sizeof(BinaryTree));
Root->left->left->val = 4;
Root->left->left->left = NULL;
Root->left->left->right = NULL;
Root->left->right = (BinaryTree*)malloc(sizeof(BinaryTree));
Root->left->right->val = 5;
Root->left->right->left = NULL;
Root->left->right->right = NULL;
Root->right = (BinaryTree*)malloc(sizeof(BinaryTree));
Root->right->val = 3;
Root->right->left = NULL;
Root->right->right = NULL;
return Root;
}
void Per(BinaryTree* Root)
{
stack<BinaryTree*>s;
while (1) {
while (Root)
{
cout << Root->val << " ";
s.push(Root);
Root = Root->left;
}
if (s.empty())break;
Root = s.top();
s.pop();
Root = Root->right;
}
cout << endl;
}
void Indx(BinaryTree* Root)
{
stack<BinaryTree*>s;
while (1) {
while (Root)
{
s.push(Root);
Root = Root->left;
}
if (s.empty())break;
Root = s.top();
cout << Root->val << " ";
s.pop();
Root = Root->right;
}
cout << endl;
}
void Last(BinaryTree* Root)
{
stack<BinaryTree*>s;
BinaryTree* mark = NULL;
while (1) {
while (Root)
{
s.push(Root);
Root = Root->left;
}
if (s.empty())break;
if (s.top()->right == NULL || s.top()->right == mark)
{
//不赋空一直卡再那了就
Root = NULL;
cout << s.top()->val << " ";
mark = s.top();
s.pop();
}
else
{
Root = s.top()->right;
}
}
cout << endl;
}
int main()
{
BinaryTree* Root = Create();
Per(Root);
Indx(Root);
Last(Root);
return 0;
}
二叉树的层序遍历
首先我们要借助队列来存储等待处理元素。
步骤:
(1)创建队列。
(2)根节点入队。
(3)处理:1.弹出,打印。2.非空左右节点入队等待处理。
#include<iostream>
#include<queue>
using namespace std;
typedef struct Tree
{
int val;
struct Tree* left;
struct Tree* right;
}BinaryTree;
BinaryTree* Create()
{
BinaryTree* Root = NULL;
Root = (BinaryTree*)malloc(sizeof(BinaryTree));
Root->val = 1;
Root->left = (BinaryTree*)malloc(sizeof(BinaryTree));
Root->left->val = 2;
Root->left->left = (BinaryTree*)malloc(sizeof(BinaryTree));
Root->left->left->val = 4;
Root->left->left->left = NULL;
Root->left->left->right = NULL;
Root->left->right = (BinaryTree*)malloc(sizeof(BinaryTree));
Root->left->right->val = 5;
Root->left->right->left = NULL;
Root->left->right->right = NULL;
Root->right = (BinaryTree*)malloc(sizeof(BinaryTree));
Root->right->val = 3;
Root->right->left = NULL;
Root->right->right = NULL;
return Root;
}
void leve(BinaryTree* Root)
{
if (Root == NULL)return;
queue<BinaryTree*>q;
//根入队
q.push(Root);
while (!q.empty())
{
Root = q.front();
cout << Root->val << " ";
q.pop();
//非空左右入队
if (Root->left != NULL)
{
q.push(Root->left);
}
if (Root->right != NULL)
{
q.push(Root->right);
}
}
}
int main()
{
BinaryTree* Root = NULL;
Root=Create();
leve(Root);
return 0;
}