当前位置:   article > 正文

二叉搜索树C语言代码实现_最优二分搜索树 用c语言实现

最优二分搜索树 用c语言实现

有些算法题里有了这个概念,因为不知道这是什么蒙圈了很久。

先序遍历: root——>left——>right

中序遍历: left—— root ——>right

后序遍历 :left ——right——>root

先弄一个只有四个节点的小型二叉树,实际上这种小型二叉树应用不大。

二叉树的真正应用是二叉搜索树,处理海量的数据。

代码很简单,两种遍历的代码也差不多

  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. typedef struct node{
  4. int data;
  5. struct node *left;
  6. struct node *right;
  7. }Node;
  8. void preorder(Node *p){//前序遍历
  9. if(p!=NULL){
  10. printf("%d\n",p->data);
  11. preorder(p->left);
  12. preorder(p->right);
  13. }
  14. }
  15. void inorder(Node *p){//中序遍历
  16. if(p!=NULL){
  17. inorder(p->left);
  18. printf("%d\n",p->data);
  19. inorder(p->right);
  20. }
  21. }
  22. int main(){
  23. Node n1;
  24. Node n2;
  25. Node n3;
  26. Node n4;
  27. n1.data=15;
  28. n2.data=32;
  29. n3.data=44;
  30. n4.data=17;
  31. n1.left=&n2;
  32. n1.right=&n3;
  33. n2.left=&n4;
  34. n2.right=NULL;
  35. n3.left=NULL;
  36. n3.right=NULL;
  37. n4.left=NULL;
  38. n4.right=NULL;
  39. preorder(&n1);
  40. puts(" ");
  41. inorder(&n1);
  42. // 15
  43. // / \
  44. // 32 44
  45. // / \ / \
  46. // 17
  47. return 0;
  48. }

[C语言教程]二叉树代码实现02_哔哩哔哩_bilibili

 讲的非常清楚。

为了构建一颗便于查找数据的树形结构,我们规定 树的节点的数据   value leftnode<value root <value rightnode

这样的一棵树叫做二叉搜索树

为了简单记忆我们就按函数中的根被访问的顺序分为前序(pre),中序(in),后序(post)

代码主要涉及前中后序遍历和求二叉搜索树的高度,和二叉搜索树的最大值的一共5中基本操作

  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. #define max(a,b) a>b?a:b
  4. typedef struct node{
  5. int data;
  6. struct node *left;
  7. struct node *right;
  8. }Node;
  9. typedef struct {
  10. Node *root;
  11. }Tree;
  12. void insert(Tree*tree,int x){
  13. Node *node;
  14. node=(Node*)malloc(sizeof (Node));
  15. node->data=x,node->left=NULL,node->right=NULL;
  16. if(tree->root==NULL){
  17. tree->root=node;
  18. }else {
  19. Node *temp=tree->root;
  20. while(temp!=NULL){
  21. if(x<temp->data){//如果左儿子的data<x ,考虑左边
  22. if(temp->left==NULL){
  23. temp->left=node;
  24. return ;
  25. } else temp=temp->left;
  26. }else { //如果右儿子的data>x ,考虑右边
  27. if(temp->right==NULL){
  28. temp->right=node;
  29. return ;
  30. }else temp=temp->right;
  31. }
  32. }
  33. }
  34. }
  35. void preorder(Node*node){//二叉树的前序遍历
  36. if(node!=NULL){
  37. printf("%d\n",node->data);
  38. preorder(node->left);
  39. preorder(node->right);
  40. }
  41. }
  42. void inorder(Node*node){
  43. if(node!=NULL){
  44. inorder(node->left);
  45. printf("%d\n",node->data);
  46. inorder(node->right);
  47. }
  48. }
  49. void postorder(Node*node){
  50. if(node!=NULL){
  51. postorder(node->left);
  52. postorder(node->right);
  53. printf("%d\n",node->data);
  54. }
  55. }
  56. int get_height(Node *node){//递归求高度h=max(Heightleftsob,Heightrightson);
  57. if(node==NULL){
  58. return 0;
  59. }else {
  60. int m1=get_height(node->left);
  61. int m2=get_height(node->right);
  62. int m=max(m1,m2);
  63. return m+1;
  64. }
  65. }
  66. int max_e(Node*node){//递归求解最大值,max_e=max{root->data,max_leftson_e,max_rightson_e};
  67. if(node==NULL){
  68. return -0x3f3f3f3f;
  69. }else {
  70. int m1=max_e(node->left);
  71. int m2=max_e(node->right);
  72. int m=node->data;
  73. return max(max(m1,m2),m);
  74. }
  75. }
  76. int main(){
  77. Tree tree;
  78. tree.root=NULL;
  79. int n;
  80. scanf("%d",&n);
  81. for(int i=1;i<=n;i++) {
  82. int t;
  83. scanf("%d",&t);
  84. insert(&tree,t);
  85. }
  86. preorder(tree.root);
  87. inorder(tree.root);
  88. postorder(tree.root);
  89. int h=get_height(tree.root);
  90. printf("h==%d\n",h);
  91. int max_ele=max_e(tree.root);
  92. printf("max_element==%d",max_ele);
  93. return 0;
  94. }

看起来很长但是实际上原理很简单,这是工程代码的特点,用数组模拟虽然会简单很多,但是无奈,两种都要会呀……

数组模拟版本:

  1. const int N=2e5+10;
  2. int cnt[N];// 结点x的值val出现的次数;
  3. int lc[N],rc[N],sz[N];//结点x的左子结点和右子结点以及以x为节点的子树大小
  4. int val[N];//结点x存储的数值
  5. int n;
  6. void print(int o){
  7. if(!o) return ;
  8. print(lc[o]);
  9. for(int i=1;i<=cnt[o];i++) printf("%d\n",val[o]);
  10. print(rc[o]);
  11. }
  12. int findmin(int o){
  13. if(!lc[o]) return o;
  14. return findmin(lc[o]);
  15. }
  16. int findmax(int o){
  17. if(!rc[o]) return o;
  18. return findmax(rc[o]);
  19. }
  20. void insert(int &o,int v){
  21. if(!o) {
  22. val[o=++n]=v;
  23. cnt[o]=sz[o]=1;
  24. lc[o]=rc[o]=0;
  25. return ;
  26. }
  27. sz[o]++;
  28. if(val[o]==v) {//如果节点o对应的值就是v 退出循环
  29. cnt[o]++;
  30. return ;
  31. }
  32. if(val[o]>v) insert(lc[o],v);
  33. if(val[o]<v) insert(rc[o],v);
  34. }
  35. int deletemin(int &o){
  36. if(!lc[o]){
  37. int u=0;
  38. o=rc[o];
  39. return u;//递归终点
  40. }else {
  41. int u=deletemin(lc[o]);//用左子树的最大值替换他,然后将它删除
  42. sz[o]-=cnt[u];
  43. return u;
  44. }
  45. }
  46. void del(int &o,int v){
  47. sz[o]--;
  48. if(val[o]==v){
  49. if(cnt[o]>1) {//结点多于一个元素,--cnt
  50. cnt[o]--;
  51. return ;
  52. }
  53. if(lc[o]&&rc[o]) o=deletemin(rc[o]);
  54. else o=lc[o]+rc[o];
  55. return ;
  56. }
  57. if(val[o]>v) del(lc[o],v);
  58. if(val[o]<v) del(rc[o],v);
  59. }
  60. //时间复杂度O(h) h为树的高度
  61. //1.查找元素的排名
  62. // 查找一个元素的排名,首先从根节点跳到这个元素,若向右跳,答案加上
  63. //左儿子结点的个数加上当前结点的个数,最后答案加上终点的左子树的大小加1
  64. int query(int o,int v){
  65. if(val[o]==v) return sz[lc[o]]+1;
  66. if(val[o]>v) return query(lc[o],v);
  67. if(val[o]<v) return query(rc[o],v)+sz[lc[o]]+cnt[o];
  68. }
  69. //2.查找排名为k的元素
  70. //根节点的排名取决于其左子树的大小
  71. //若其左子树的大小大于等于k,则该元素在左子树,若其左子树大小在[k-cnt,k-1]则该元素为子树的根节点。
  72. //若其左子树的大小小于k-cnt,则称该元素在右子树中
  73. int querykth(int o,int k){
  74. if(sz[lc[o]>=k] ) return querykth(lc[o],k);
  75. if(sz[lc[o]]<k-cnt[o]) return querykth(rc[o],k-lc[o]-cnt[o]);
  76. return val[o];
  77. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Li_阴宅/article/detail/910094
推荐阅读
相关标签
  

闽ICP备14008679号