数据结构-树的总结
1 : 定义:树是包含n(n>=0)个结点的有穷集,其中:
(1):每个元素称为结点(node);
(2):有一个特定的节点被称为根结点或树根(root);
(3):除根结点以外的其余数据元素被分为m(m>=0)个互不相交的集合T1,T2…Tm-1 ,其中每一个集合mi(1=<i<=m)本身也是一棵树,被称为原树的子树。
单个结点也是一棵树,树根就是该结点本身;
空集合也是树,被称为空树,空树种没有结点;
2:相关名词:
- 结点的度:一个结点含有子树的个数称为该结点的度;
- 叶子结点或终端结点:度为0的结点称为叶子结点;
- 分支结点:度不为0的结点;
- 双亲结点或父节点:若一个结点含有子结点,则该结点成为其子结点的父结点;
- 子结点:一个结点含有的子树的根结点被称为该节点的自结点;
- 兄弟结点:具有相同父结点的结点互为兄弟结点;
- 树的度:一棵树中,最大的结点的度称为树的度;
- 结点的层次:从根节点开始定义,根为第一层,根的子结点为第二层,一次类推;
- 树的高度或深度:树中结点的最大层次;
3:树的种类
- 无序树:树中任意结点的子结点之间没有任何顺序关系,这种树被称为无序树也叫自由树
- 有序树:树中任意结点的子结点之间有关系,这种树被称为有序树;
- 二叉树:每个结点最多含有两个子树的树称为二叉树;
- 完全二叉树:若设二叉树的深度为h,除第h层外,其余各层的结点树都达到了最大个数,第h层所有的结点都集中在了最左边,这就是完全二叉树;
- 满二叉树:除最后一层无任何子结点外,其余各层的所有结点都有两个结点的二叉树;
- 哈夫曼树;带权路径最短的树称为哈夫曼树;
4:树的表示方法:
1):图像法
2):符号表示法
用括号先将根结点放在圆括号中,然后把他们的子树由左到右放到括号中,而对子树也采取同样的方法处理,同层子树与它的根结点用括号括起来,同层子树之间用逗号隔开,最后用闭括号括起来。
3):遍历表达法
遍历表示法有三种:前序遍历,中序遍历,后序遍历
如上图所示:
前序遍历:根->左子树->右子树(ABDECF)
中序遍历:左子树->根->右子树(DBEAFC)
后序遍历:左子树->右子树->根(DEBFCA)
5:二叉树基本操作
1):定义结构体
#include<stdio.h>
#include<stdlib.h>
//定义二叉树左右指针结构体
typedef struct Node {
char value;
struct Node* left;
struct Node* right;
};
//定义二叉树根结点结构体
typedef struct Tree {
int count;
struct Tree* root;
};
2):二叉树的创建
//创建二叉树
Node* Treecreat(ch) {
Node* node = (Node*)malloc(sizeof(Node));
node->value = ch;
node->left = node->right = NULL;
return node;
}
3)销毁二叉树
//销毁二叉树
Node* Tree_Destroy(Node* root) {
free(root);
}
4)拷贝二叉树
//拷贝二叉树
Node* copyTree(Node* root) {
Node* newroot = NULL;
Node* newleft = NULL;
Node* newright = NULL;
if (root == NULL) {
return;
}
if (root->left == NULL) {
newleft == NULL;
}
else {
newleft = copyTree(root->left);//拷贝左子树
}
if (root->right == NULL) {
newright == NULL;
}
else {
newright = copyTree(root->right);//拷贝右子树
}
Node* newroot = (Node*)malloc(sizeof(Node));//为新的根结点分配内存
newroot->left = newleft;
newroot->right = newright;
newroot->value = root->value;
}
5)二叉树的前,中,后序遍历
递归遍历
//前序遍历
void preorderTraversal(Node* root) {
if (root == NULL) {
return;
}
else {
printf("%d ", root->value);
preorderTraversal(root->left);
preorderTraversal(root->right);
}
}
//中序遍历
void inorderTraversal(Node* root) {
if (root == NULL) {
return;
}
else {
inorderTraversal(root->left);
printf("%c ", root->value);
inorderTraversal(root->right);
}
}
//后序遍历
void postorderTraversal(Node* root) {
if (root == NULL) {
return;
}
else{
postorderTraversal(root->left);
postorderTraversal(root->right);
printf("%c ", root->value);
}
}
6):二叉树结点个数
int getNodecount(Node* root) {
if (root == NULL) {
return 0;
}
else {
int left = getNodecount(root->left);
int right = getNodecount(root->right);
return left + 1 + right;
}
}
7);二叉树高度
int Max(int a, int b) {
return a >=b ? a : b;
}
int getheight(Node* root) {
if (root == NULL) {
return 0;
}
else {
int left = getheight(root->left);
int right = getheight(root->right);
return Max(left, right) + 1;
}
}
8)第k层结点个数
int getkleafcount(Node* root, int k) {
if (root == NULL) {
return 0;
}
else if (k == 1) {
return 1;
}
else {
return getkleafcount(root->left, k - 1) + getkleafcount(root->right, k - 1);
}
}
9)叶子结点个数;
int getleafcount(Node* root) {
if (root == NULL) {
return 0;
}
else if (root->left==NULL&&root->right == NULL) {
return 1;
}
else {
return getleafcount(root->left) + getleafcount(root->right);
}
}