目录
一.树
1.树的基本概念
树是一种非线性的数据结构,它是由n(n>=0)个有限结点组成一个具有层次关系的集合。
其中,A叫做根节点。
2.树与非树
上面这三种情况都不是树。
需要满足以下情况:
①.树的子树之间是不相交的;
②.除了根结点外,每个结点有且仅有一个父结点;
③.一棵N个结点的树有N-1条边
3.树的相关概念
节点的度:一个节点含有的子树的个数称为该节点的度; 如上图:A的度为3
叶节点或终端节点:度为0的节点称为叶节点; 如上图:C1,C2,C3,C4,C5,C6为叶节点
非终端节点或分支节点:度不为0的节点; 如上图:A,B1,B2,B3为分支节点
双亲节点或父节点:若一个节点含有子节点,则这个节点称为其子节点的父节点; 如上图:A是B1,B2,B3的父节点
孩子节点或子节点:一个节点含有的子树的根节点称为该节点的子节点; 如上图:B1,B2,B3是A的孩子节点
兄弟节点:具有相同父节点的节点互称为兄弟节点; 如上图:B1,B2,B3是兄弟节点
树的度:一棵树中,最大的节点的度称为树的度; 如上图:树的度为3
节点的层次:从根开始定义起,根为第1层,根的子节点为第2层,以此类推;
树的高度或深度:树中节点的最大层次; 如上图:树的高度为3
堂兄弟节点:双亲在同一层的节点互为堂兄弟;如上图:C1,C3互为堂兄弟节点
节点的祖先:从根到该节点所经分支上的所有节点;如上图:A是所有节点的祖先
子孙:以某节点为根的子树中任一节点都称为该节点的子孙。如上图:所有节点都是A的子孙
森林:由m(m>0)棵互不相交的树的集合称为森林;
4.树的结构
树的一个结点中,不仅有数据,还得有一个标记来指向它的下一个结点。这个标记就是指针。
一棵树,横着看,有他的兄弟们,竖着看,有它的孩子。所以我们用一个指针指向它的第一个孩子,用另一个指针指向它的兄弟,所有结点就被串联起来了。
typedef int datatype;
struct Node
{
datatype val;
struct Node* child; // 第一个孩子结点
struct Node* brother; // 指向其下一个兄弟结点
}
二.二叉树
1.二叉树的基本概念
二叉树是指树中结点的度不大于2的有序树
而二叉树又分完全二叉树和满二叉树
1.满二叉树:一个二叉树,如果每一个层的结点数都达到最大值,则这个二叉树就是满二叉树。
,则它就是满二叉树。
2. 完全二叉树:
完全二叉树是效率很高的数据结构,完全二叉树是由满二叉树而引出来的。对于深度为K的,有n个结点的二叉树,当且仅当其每一个结点都与深度为K的满二叉树中编号从1至n的结点一一对应时称之为完全二叉树。 要注意的是满二叉树是一种特殊的完全二叉树。
完全二叉树:

满二叉树:
2.二叉树的性质
1. 若规定根节点的层数为1,则一棵非空二叉树的第i层上最多有2^(i-1)个结点.
2. 若规定根节点的层数为1,则深度为h的二叉树的最大结点数是 2^h - 1
3. 对任何一棵二叉树, 如果度为0其叶结点个数为x , 度为2的分支结点个数为y ,则有 x=y+1
4. 若规定根节点的层数为1,具有n个结点的满二叉树的深度,h=log(N+1) 以2为底
5. 对于具有n个结点的完全二叉树,如果按照从上至下从左至右的数组顺序对所有节点从0开始编号,则对 于序号为i的结点有:
1. 若i>0,i位置节点的双亲序号:(i-1)/2;i=0,i为根节点编号,无双亲节点
2. 若2i+1<n,左孩子序号:2i+1,2i+1>=n否则无左孩子
3. 若2i+2<n,右孩子序号:2i+2,2i+2>=n否则无右孩子
三.二叉树的链式存储
1.存储结构
typedef struct TreeNode
{
char data; //数据域
struct TreeNode* left; //左孩子
struct TreeNode* right; //右孩子
}TreeNode;
2.二叉树的基础操作
①.二叉树的建立
TreeNode* rootBinaryTreeCreate(char* arr, int n, int* i)
{
TreeNode* node = (TreeNode*)malloc(sizeof(TreeNode) * n);
if (arr[*i] == '#')
{
(*i)++; //++和* 优先级问题
return NULL;
}
node->data = arr[(*i)++]; // ++和* 优先级问题
node->left = rootBinaryTreeCreate(arr, n, i);
node->right = rootBinaryTreeCreate(arr, n, i);
return node;
}
int main()
{
char arr[] = "ABD##E#H##CF##G##"; // 不为 # 就进入二叉树
int sz = strlen(arr);
int i = 0;
TreeNode* root=rootBinaryTreeCreate(arr,sz,&i);
}
②.前序遍历
void BinaryTreePrevOrder(TreeNode* root)
{
if (root == NULL)
{
return NULL;
}
printf("%c ", root->data);
BinaryTreePrevOrder(root->left);
BinaryTreePrevOrder(root->right);
}
③中序遍历
void BinaryTreeInOrder(TreeNode* root)
{
if (root == NULL)
{
return NULL;
}
BinaryTreeInOrder(root->left);
printf("%c ", root->data);
BinaryTreeInOrder(root->right);
}
④.后序遍历
void BinaryTreePostOrder(TreeNode* root)
{
if (root == NULL)
{
return NULL;
}
BinaryTreePostOrder(root->left);
BinaryTreePostOrder(root->right);
printf("%c ", root->data);
}
⑤.二叉树的结点数
int BinaryTreeSize(TreeNode* root)
{
if (root == NULL)
{
return 0;
}
return BinaryTreeSize(root->left) + BinaryTreeSize(root->right) + 1;
}
⑥.二叉树的叶结点数
int BinaryTreeLeafSize(TreeNode* root)
{
if (root == NULL)
{
return 0;
}
if (root->left==NULL&&root->right==NULL)
{
return 1;
}
int lefts= BinaryTreeLeafSize(root->left);
int rights=BinaryTreeLeafSize(root->right);
return lefts + rights;
}
⑦.二叉树的第K层结点数
int BinaryTreeLevelKSize(TreeNode* root,int k)
{
if (root == NULL)
{
return 0;
}
if (k == 1)
{
return 1;
}
return BinaryTreeLevelKSize(root->left, k - 1)+ BinaryTreeLevelKSize(root->right, k - 1);
}
⑧.查找树为X的结点
TreeNode* BinaryTreeFind(TreeNode* root, char x)
{
if (root == NULL)
{
return NULL;
}
if (root->data == x)
{
return root;
}
BinaryTreeFind(root->left,x);
BinaryTreeFind(root->right,x);
}
⑨二叉树的层序遍历
TreeNode* BinaryTreeLevelOrder(TreeNode* root)
{
if (root == NULL)
{
return NULL;
}
Queue q;
QueueInit(&q);
QueuePush(&q, root);
while (!QueueEmpty(&q))
{
TreeNode* front = QueueFront(&q);
QueuePop(&q);
printf("%c", front->data);
if (front->left)
QueuePush(&q, front->left);
if (front->right)
QueuePush(&q, front->right);
}
QueueDestroy(&q);
}
⑩.判断完全二叉树
bool BinaryTreeComplete(TreeNode* root)
{
Queue q;
QueueInit(&q);
//如果根存在,则进队列
if(root)
QueuePush(&q, root);
//如果队列不为空
while (!QueueEmpty(&q))
{
TreeNode* front = QueueFront(&q);
QueuePop(&q);
//如果front为空 跳出循环
if (front==NULL)
{
break; //进入二次判断
}
if (front->left)
{
QueuePush(&q, front->left);
}
if (front->right)
{
QueuePush(&q, front->right);
}
}
//二次判断
while (!QueueEmpty(&q))
{
TreeNode* front = QueueFront(&q);
QueuePop(&q);
if (front)
{
QueueDestroy(&q);
return false;
}
}
QueueDestroy(&q);
return true;
}
⑪.二叉树的销毁
void BinaryTreeDestroy(TreeNode* root)
{
if (root == NULL)
{
return NULL;
}
BinaryTreeDestroy(root->left);
BinaryTreeDestroy(root->right);
free(root);
}
四.完整代码
1.queue.h
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<assert.h>
typedef struct TreeNode* datatype;
typedef struct QNode
{
datatype data;
struct QNode* next;
}QNode;
typedef struct Queue
{
QNode* head;
QNode* tail;
int size;
}Queue;
void QueueInit(Queue* pq);
void QueuePush(Queue* pq,datatype x);
void QueuePop(Queue* pq);
datatype QueueFront(Queue* pq);
datatype QueueBack(Queue* pq);
int QueueSize(Queue* pq);
bool QueueEmpty(Queue* pq);
void QueueDestroy(Queue* pq);
2.queue.c
void QueueInit(Queue* pq)
{
assert(pq);
pq->head = pq->tail = NULL;
pq->size = 0;
}
void QueuePush(Queue* pq, datatype x)
{
assert(pq);
QNode* new = (QNode*)malloc(sizeof(QNode));
if (new==NULL)
{
perror("malloc fail\n");
return;
}
new->data = x;
new->next = NULL;
if (pq->head == NULL)
{
assert(pq->tail == NULL);
pq->head = new;
pq->tail = new;
}
else
{
pq->tail->next = new;
pq->tail = new;
}
pq->size++;
}
void QueuePop(Queue* pq)
{
assert(pq);
assert(pq->head != NULL);
if (pq->head->next == NULL)
{
free(pq->head);
pq->head = pq->tail = NULL;
}
else
{
QNode* next = pq->head->next;
free(pq->head);
pq->head = next;
}
pq->size--;
}
datatype QueueFront(Queue* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
return pq->head->data;
}
datatype QueueBack(Queue* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
return pq->tail->data;
}
int QueueSize(Queue* pq)
{
assert(pq);
return pq->size;
}
bool QueueEmpty(Queue* pq)
{
assert(pq);
if (pq->size == 0)
{
return true;
}
return false;
}
void QueueDestroy(Queue* pq)
{
assert(pq);
QNode* cur = pq->head;
while (cur)
{
QNode*next=cur->next;
free(cur);
cur = next;
}
pq->head = pq->tail = NULL;
pq->size = 0;
}
3.tree.c
typedef struct TreeNode
{
char data;
struct TreeNode* left;
struct TreeNode* right;
}TreeNode;
TreeNode* rootBinaryTreeCreate(char* arr, int n, int* i)
{
TreeNode* node = (TreeNode*)malloc(sizeof(TreeNode) * n);
if (arr[*i] == '#')
{
(*i)++; //++和* 优先级问题
return NULL;
}
node->data = arr[(*i)++]; // ++和* 优先级问题
node->left = rootBinaryTreeCreate(arr, n, i);
node->right = rootBinaryTreeCreate(arr, n, i);
return node;
}
void BinaryTreePrevOrder(TreeNode* root)
{
if (root == NULL)
{
return NULL;
}
printf("%c ", root->data);
BinaryTreePrevOrder(root->left);
BinaryTreePrevOrder(root->right);
}
void BinaryTreeInOrder(TreeNode* root)
{
if (root == NULL)
{
return NULL;
}
BinaryTreeInOrder(root->left);
printf("%c ", root->data);
BinaryTreeInOrder(root->right);
}
void BinaryTreePostOrder(TreeNode* root)
{
if (root == NULL)
{
return NULL;
}
BinaryTreePostOrder(root->left);
BinaryTreePostOrder(root->right);
printf("%c ", root->data);
}
int BinaryTreeSize(TreeNode* root)
{
if (root == NULL)
{
return 0;
}
return BinaryTreeSize(root->left) + BinaryTreeSize(root->right) + 1;
}
int BinaryTreeLeafSize(TreeNode* root)
{
if (root == NULL)
{
return 0;
}
if (root->left==NULL&&root->right==NULL)
{
return 1;
}
int lefts= BinaryTreeLeafSize(root->left);
int rights=BinaryTreeLeafSize(root->right);
return lefts + rights;
}
int BinaryTreeLevelKSize(TreeNode* root,int k)
{
if (root == NULL)
{
return 0;
}
if (k == 1)
{
return 1;
}
return BinaryTreeLevelKSize(root->left, k - 1)+ BinaryTreeLevelKSize(root->right, k - 1);
}
TreeNode* BinaryTreeFind(TreeNode* root, char x)
{
if (root == NULL)
{
return NULL;
}
if (root->data == x)
{
return root;
}
BinaryTreeFind(root->left,x);
BinaryTreeFind(root->right,x);
}
TreeNode* BinaryTreeLevelOrder(TreeNode* root)
{
if (root == NULL)
{
return NULL;
}
Queue q;
QueueInit(&q);
QueuePush(&q, root);
while (!QueueEmpty(&q))
{
TreeNode* front = QueueFront(&q);
QueuePop(&q);
printf("%c", front->data);
if (front->left)
QueuePush(&q, front->left);
if (front->right)
QueuePush(&q, front->right);
}
QueueDestroy(&q);
}
bool BinaryTreeComplete(TreeNode* root)
{
Queue q;
QueueInit(&q);
//如果根存在,则进队列
if(root)
QueuePush(&q, root);
//如果队列不为空
while (!QueueEmpty(&q))
{
TreeNode* front = QueueFront(&q);
QueuePop(&q);
//如果front为空 跳出循环
if (front==NULL)
{
break; //进入二次判断
}
if (front->left)
{
QueuePush(&q, front->left);
}
if (front->right)
{
QueuePush(&q, front->right);
}
}
//二次判断
while (!QueueEmpty(&q))
{
TreeNode* front = QueueFront(&q);
QueuePop(&q);
if (front)
{
QueueDestroy(&q);
return false;
}
}
QueueDestroy(&q);
return true;
}
void BinaryTreeDestroy(TreeNode* root)
{
if (root == NULL)
{
return NULL;
}
BinaryTreeDestroy(root->left);
BinaryTreeDestroy(root->right);
free(root);
}
int main()
{
char arr[] = "ABD##E#H##CF##G##";
int sz = strlen(arr);
int i = 0;
TreeNode* root=rootBinaryTreeCreate(arr,sz,&i);
BinaryTreePrevOrder(root); //先序遍历
printf("\n");
BinaryTreeInOrder(root); //中序遍历
printf("\n");
BinaryTreePostOrder(root); //后序遍历
printf("\n");
printf("二叉树的结点个数为:%d\n",BinaryTreeSize(root)); //二叉树的结点个数
printf("二叉树的叶子结点个数为:%d\n",BinaryTreeLeafSize(root)); //二叉树的叶子结点个数
printf("二叉树第k层结点个数为:%d\n", BinaryTreeLevelKSize(root,3)); //二叉树第k层结点个数
printf("二叉树值为K的结点地址为:%p\n",BinaryTreeFind(root, 'C')); //二叉树值为K的结点地址
printf("二叉树的层序遍历:"); BinaryTreeLevelOrder(root); //二叉树的层序遍历
printf("\n判断二叉树是否为完全二叉树:%d\n",BinaryTreeComplete(root)); //判断二叉树是否为完全二叉树
BinaryTreeDestroy(root);
root = NULL;
}