0x01数据结构——C语言实现(二叉树)
0x01数据结构——C语言实现(二叉树)
二叉树(binary tree)是一棵树,其中每个节点都不能有多于两个的儿子。
二叉树的一个性质是平均二叉树的深度要比N小得多,这个性质有时很重要。分析表明,这个平均深度为,而对于特殊类型的二叉树,即二叉查找树(binary search tree),其深度的平均值是。
二叉树的C语言实现如下:
binary_tree.h
/* 二叉树(binary Btree): 二叉树是一颗树,其中每个节点都不能有多余两个的儿子。 root / \ left right 二叉树的一个性质是平均二叉树的深度要比N小得多。这个平均深度为O(\sqrt(n)),最大深度为N-1。 而对于特殊类型的二叉树,即二叉查找树(binary search Btree),其深度的平均值是O(log n)。 */ #ifndef BINARY_Btree_H #define BINARY_Btree_H /* 二叉树的节点用左右孩子表示法来存储。 */ typedef enum { false = 0, true } BOOL; struct node; typedef struct node node; typedef node *Btree; typedef node *pos; //根据先序遍历数组来创建树(先序遍历数组中用'#'来表示空节点) Btree create_Btree_preorder(int v[], int begin, int end); Btree create_Btree(int v[], int *begin, int end); //将一颗树置空 Btree make_empty(Btree T); //判断树是不是空的 BOOL is_empty(Btree T); //为节点p添加孩子节点x BOOL add_child(node *p, int x); //合并两棵树T1和T2 Btree union_btree(Btree T1, Btree T2); //先序遍历树 void preorder_traversal(Btree T); //以数组形式打印 //数组规定如下:用'#'来表示空节点 void preorder_traversal1(Btree T); //中序遍历 void inorder_traversal(Btree T); //后序遍历 void postorder_traversal(Btree T); //寻找节点x的位置 pos search(int x, Btree T); //输出二叉树的高度 int Btree_height(Btree T); //输出二叉树总结点数目 int node_sum(Btree T); //叶子结点数目 int leaves_sum(Btree T); //取出节点p的值 int retrieve_p(pos p); //以层次方式打印输出 void print_Btree(Btree T); void output(Btree T, int i); #endif
binary_tree.c
#include "binary_tree.h" #include <stdio.h> #include <stdlib.h> #include <string.h> struct node { int val; struct node *left;//left child struct node *right;//right child }; struct node; typedef struct node node; typedef node *Btree; typedef node *pos; //根据先序遍历数组来创建树(先序遍历数组中用'#'来表示空节点) Btree create_Btree_preorder(int v[], int begin, int end) { return create_Btree(v, &begin, end); } Btree create_Btree(int v[], int *begin, int end) { if((*begin)>end || v==NULL) return NULL; Btree T = NULL; if(v[*begin]!='#') { T=(node *)malloc(sizeof(node)); T->val = v[*begin]; (*begin)++; if(v[*begin] == '#') { T->left = NULL; (*begin)++; T->right = create_Btree(v, begin, end); } else { T->left = create_Btree(v, begin, end); (*begin)++; T->right = create_Btree(v, begin, end); } } return T; } //将一颗树置空 Btree make_empty(Btree T) { if(T!=NULL) { make_empty(T->left); make_empty(T->right); printf("free node with value %d\n", T->val); free(T); T = NULL; } return T; } //判断树是不是空的 BOOL is_empty(Btree T) { return (T == NULL); } //为节点p添加孩子节点x BOOL add_child(node *p, int x) { if(p->left == NULL) { p->left = (node*)malloc(sizeof(node)); p->left->val = x; p->left->left = p->left->right = NULL; return true; } else if(p->right == NULL) { p->right = (node*)malloc(sizeof(node)); p->right->val = x; p->right->left = p->right->right = NULL; return true; } else { return false; } } //合并两棵树T1和T2 Btree union_btree(Btree T1, Btree T2) { Btree T; if(T1!=NULL && T2!=NULL) { /* * 先假设合并后的树根节点是原来两棵树根节点之和 */ T = (Btree)malloc(sizeof(node)); T->val = T1->val+T2->val; T->left = T1; T->right = T2; } else if(T1 == NULL) { T = T2; } else { T = T1; } return T; } //先序遍历树 void preorder_traversal(Btree T) { if(T!=NULL) { printf("%d", T->val); preorder_traversal(T->left); preorder_traversal(T->right); } } //以先序遍历数组形式打印 //数组规定如下:用'#'来表示空节点 void preorder_traversal1(Btree T) { if(T!=NULL) { printf("%d", T->val); if(T->left == NULL) { printf("#"); if(T->right == NULL) { printf("#"); } else { preorder_traversal1(T->right); } } else { preorder_traversal1(T->left); if(T->right == NULL) { printf("#"); } else { preorder_traversal1(T->right); } } } } //中序遍历 void inorder_traversal(Btree T) { if(T!=NULL) { inorder_traversal(T->left); printf("%d", T->val); inorder_traversal(T->right); } } //后序遍历 void postorder_traversal(Btree T) { if(T!=NULL) { postorder_traversal(T->left); postorder_traversal(T->right); printf("%d", T->val); } } //寻找节点x的位置 pos search(int x, Btree T) { if(T!=NULL) { if(T->val == x) { return T; } else { pos tmp = NULL; if(search(x,T->left)==NULL) { search(x,T->right); } return tmp; } } else { return NULL; } } //输出二叉树中某个节点的高度 //对任意节点n_i,n_i的深度(depth)为从根到n_i的唯一路径的长。因此,根的深度为0。 //n_i的高(height)是从n_i到一片树叶的最长路径的长。 //因此所有树叶的高度都是0。一棵树的高等于它的根的高。 //一棵树的深度等于它的最深的树叶的深度,该深度总是等于这棵树的高。 int Btree_height(Btree T) { static int h = -1; if(T!=NULL) { if(T->left==NULL && T->right==NULL) { h=0; }else { int h1, h2; h1 = Btree_height(T->left)+1; h2 = Btree_height(T->right)+1; h = (h1>h2?h1:h2); } } return h; } //输出二叉树总结点数目 int node_sum(Btree T) { int sum = 0; if(T!=NULL) { if(T->left==NULL && T->right==NULL) { sum = 1; }else { int sum1, sum2; sum1 = node_sum(T->left); sum2 = node_sum(T->right); sum = sum1+sum2+1; } } return sum; } //叶子结点数目 int leaves_sum(Btree T) { int sum = 0; if(T!=NULL) { if(T->left==NULL && T->right==NULL) { sum = 1; }else { int sum1, sum2; sum1 = leaves_sum(T->left); sum2 = leaves_sum(T->right); sum = sum1+sum2; } } return sum; } //取出节点p的值 int retrieve_p(pos p) { return p->val; } //以层次方式打印输出 void print_Btree(Btree T) { output(T,0); } void output(Btree T, int i) { if(T != NULL) { for(int j = 0; j<i; j++) { printf("\t"); } printf("%d\n", T->val); i++; if(!(T->left == NULL && T->right == NULL)) { if(T->left == NULL) { printf("\n"); output(T->right,i);//输出右子树 } else if(T->right == NULL) { output(T->left,i);//输出左子树 printf("\n"); } else { output(T->left,i);//输出左子树 output(T->right,i);//输出右子树 } } } }
main.c
#include "binary_tree.h" #include <stdio.h> #include <string.h> #include <stdlib.h> int main() { int A[15]={1,2,4,'#','#',5,'#','#',3,6,'#','#',7,'#','#'}; int B[9] = {1,2,4,'#','#','#',3,'#','#'}; int C[7] = {5,6,'#','#',7,'#','#'}; int h = 0, sum = 0, leaves = 0; int x = 2; pos tmp = NULL; Btree T = create_Btree_preorder(A,0,14); Btree T1 = create_Btree_preorder(B,0,8); Btree T2 = create_Btree_preorder(C,0,6); print_Btree(T); preorder_traversal(T); printf("\n"); inorder_traversal(T); printf("\n"); postorder_traversal(T); printf("\n"); preorder_traversal1(T); printf("\n"); Btree pos = search(x,T); h = Btree_height(pos); printf("height of the node %d: %d\n", x,h); sum = node_sum(T); printf("this tree has %d node(s)\n", sum); leaves = leaves_sum(T); printf("this tree has %d leaves\n", leaves); tmp = make_empty(T); printf("%d\n", is_empty(tmp)); print_Btree(T1); print_Btree(T2); T = union_btree(T1,T2); print_Btree(T); return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)