• 使用C语言实现前,中,后序线索化二叉树


    目录

    1.线索二叉树

    2.线索化二叉树相关操作

    (1)数据结构定义

    (2)创建二叉树和销毁

    (3)前序,中序和后序线索化二叉树

    (4)二叉树的高度

    (5)统计叶子节点数,所有节点数和第k层节点数

    (6)主函数


    1.线索二叉树

    使用C语言实现二叉树的存储

    由于二叉树的根节点只有后继节点没有前驱节点,非叶子节点的前驱节点为双亲节点,叶子节点只有前驱节点,没有后继节点,可是我们这里的二叉树线索化的前驱和后继指的是前,中和后序遍历之后的节点前驱和后继节点:如下面的中序遍历结果中的D没有前驱,只有后继,其后继节点为G;而节点C只有前驱没有后继,其前驱节点为F。如果节点的数量不是很大的情况下的话,可以从根节点进行中序遍历访问即可得到中序遍历之后结果的前驱和后继,但是如果二叉树很庞大呢,那么可以使用到二叉树线索化了。

     

    由于之前提到在使用二叉树存储节点的时候会出现n+1个指针域的浪费,我们可以使用这个(n+1)个空指针指向前,中和后序遍历之后的前驱和后继。

    规定:若结点有左子树,则其lchild域指示其左孩子,否则让lchild域指示其前驱;若结点有右子树,则其rchild域指示其右子树,否则让rchild域指示其后继。

     Ltag=0:表示lchild域指示结点的左孩子;

     Ltag=1:表示lchild域指示结点的前驱;

     Rtag=0:表示rchild域指示结点的右孩子;

     Rtag=1:表示rchild域指示结点的后继。

    如下图的中序二叉树线索化:

     

    2.线索化二叉树相关操作

    (1)数据结构定义

    1. #include
    2. #include
    3. #include
    4. #include
    5. #define MAXSIZE 10
    6. #define maxn 100
    7. typedef char ElemType;
    8. typedef struct ThreadNode{
    9. ElemType data;//节点中的数据元素
    10. struct ThreadNode*lchild,*rchild;
    11. int ltag,rtag;
    12. }ThreadNode,*ThreadTree;
    13. int depth=0;
    14. void InitBitree(){
    15. printf("--------------1.创建二叉树------------\n");
    16. printf("--------------2.二叉树的前序遍历线索化\n");
    17. printf("--------------3.二叉树的中序遍历线索化\n");
    18. printf("--------------4.二叉树的后序遍历线索化\n");
    19. printf("--------------5.二叉树的高度----------\n");
    20. printf("--------------6.二叉树的叶子节点数----\n");
    21. printf("--------------7.二叉树的节点数--------\n");
    22. printf("--------------8.第k层节点数----------\n");
    23. printf("--------------9.重新初始化节点-------\n");
    24. printf("--------------10.二叉树的销毁操作-----\n");
    25. printf("--------------11.结束操作-------------\n");
    26. }

    (2)创建二叉树和销毁

    1. void DestryBitree(ThreadTree&T){
    2. if(T==NULL){
    3. return;
    4. }
    5. DestryBitree(T->lchild);
    6. DestryBitree(T->rchild);
    7. free(T);
    8. }
    9. //创建二叉树
    10. void createBitree(ThreadTree&T,char list[maxn],int k,int mask,int length){
    11. if(list[k]=='\0')mask=0;
    12. if(k>=length)return;
    13. if(mask==1){
    14. T=(ThreadNode*)malloc(sizeof(ThreadNode));
    15. T->data=list[k];
    16. T->lchild=NULL;
    17. T->rchild=NULL;
    18. T->ltag=0;
    19. T->rtag=0;
    20. createBitree(T->lchild,list,2*k+1,mask,length);
    21. createBitree(T->rchild,list,2*k+2,mask,length);
    22. }
    23. return;
    24. }

    (3)前序,中序和后序线索化二叉树

    1. ThreadNode*p;//指向目标节点
    2. ThreadNode*pre=NULL;//指向当前访问的节点前驱
    3. ThreadNode*final=NULL;//用于记录最终结果
    4. void visit(ThreadNode*q){
    5. // if(q==p){//当前访问节点刚好是节点p
    6. // final=pre;//指向当前节点的前驱
    7. // }else{
    8. // pre=q;//pre指向当前访问的节点
    9. // }
    10. if(q->lchild==NULL){
    11. q->lchild=pre;//前驱线索化
    12. q->ltag=1;
    13. }
    14. if(pre!=NULL&&pre->rchild==NULL){
    15. pre->rchild=q;//后继线索化
    16. pre->rtag=1;
    17. }
    18. pre=q;//前驱指针移到当前指针q
    19. }
    20. //中序遍历的同时进行线索化
    21. void InThread(ThreadTree T){
    22. if(T==NULL)return;
    23. InThread(T->lchild);
    24. visit(T);
    25. InThread(T->rchild);
    26. }
    27. void CreateInThread(ThreadTree T){
    28. pre=NULL;
    29. if(T!=NULL){
    30. InThread(T);
    31. //处理最后一个节点
    32. if(pre->rchild==NULL){
    33. pre->rtag=1;
    34. }
    35. }
    36. }
    37. //前序遍历的同时进行线索化
    38. void PreThread(ThreadTree T){
    39. if(T==NULL)return;
    40. visit(T);
    41. //防止出现一直循环
    42. if(T->ltag==0){
    43. PreThread(T->lchild);
    44. }
    45. PreThread(T->rchild);
    46. }
    47. void CreatePreThread(ThreadTree T){
    48. pre=NULL;
    49. if(T!=NULL){
    50. PreThread(T);
    51. //处理最后一个节点
    52. if(pre->rchild==NULL){
    53. pre->rtag=1;
    54. }
    55. }
    56. }
    57. //后序遍历的同时进行线索化
    58. void PostThread(ThreadTree T){
    59. if(T==NULL)return;
    60. PostThread(T->lchild);
    61. PostThread(T->rchild);
    62. visit(T);
    63. }
    64. void CreatePostThread(ThreadTree T){
    65. pre=NULL;
    66. if(T!=NULL){
    67. PostThread(T);
    68. //处理最后一个节点
    69. if(pre->rchild==NULL){
    70. pre->rtag=1;
    71. }
    72. }
    73. }

    (4)二叉树的高度

    1. //二叉树的高度
    2. int HeightBitree(ThreadTree T){
    3. if(T==NULL){
    4. return 0;
    5. }else{
    6. int Lheight=HeightBitree(T->lchild);
    7. int Rheight=HeightBitree(T->rchild);
    8. depth=Lheight>Rheight?Lheight+1:Rheight+1;
    9. }
    10. return depth;
    11. }

    (5)统计叶子节点数,所有节点数和第k层节点数

    1. //统计叶子节点数
    2. int CountLeaf(ThreadTree T){
    3. if(T==NULL)return 0;
    4. if(T&&T->lchild==NULL&&T->rchild==NULL){
    5. return 1;
    6. }
    7. return (CountLeaf(T->lchild)+CountLeaf(T->rchild));
    8. }
    9. //二叉树的节点数
    10. int count=0;
    11. void CountNode(ThreadTree T){
    12. if(T==NULL)return ;
    13. if(T){
    14. count++;
    15. }
    16. CountNode(T->lchild);
    17. CountNode(T->rchild);
    18. }
    19. //二叉树第k层节点数
    20. int KLayerNode(ThreadTree T,int k){
    21. int a,b;
    22. if(T==NULL)return 0;
    23. if(k==1)return 1;
    24. a=KLayerNode(T,k-1);
    25. b=KLayerNode(T,k-1);
    26. return a+b;
    27. }

    (6)主函数

    1. int main(){
    2. //根节点初始化为NULL
    3. ThreadTree T=NULL;
    4. ElemType list[maxn];
    5. int flag=0;
    6. while(1){
    7. InitBitree();
    8. printf("请输入操作: ");
    9. scanf("%d",&flag);
    10. int k=0;
    11. int mask=1;
    12. int depth=0;
    13. int length=0;
    14. count=0;
    15. switch(flag){
    16. case 1:
    17. printf("请输入字符序列: ");
    18. scanf("%s",&list);
    19. length=strlen(list);
    20. createBitree(T,list,k,mask,length);
    21. break;
    22. case 2:
    23. CreatePreThread(T);
    24. printf("\n");
    25. break;
    26. case 3:
    27. CreateInThread(T);
    28. printf("\n");
    29. break;
    30. case 4:
    31. CreatePostThread(T);
    32. printf("\n");
    33. break;
    34. case 5:
    35. //二叉树的高度
    36. depth=HeightBitree(T);
    37. printf("二叉树的高度为 = %d\n",depth);
    38. break;
    39. case 6:
    40. //叶子节点数
    41. count=CountLeaf(T);
    42. printf("叶子节点数 = %d\n",count);
    43. break;
    44. case 7:
    45. //节点数
    46. CountNode(T);
    47. printf("节点数 = %d\n",count);
    48. break;
    49. case 8:
    50. //第k层节点数
    51. printf("请输入查找节点的第k层: ");
    52. scanf("%d",&k);
    53. depth=HeightBitree(T);
    54. if(k>depth){
    55. printf("输入的不合法!\n");
    56. }else{
    57. count=KLayerNode(T,k);
    58. printf("第k层节点数 = %d\n",count);
    59. }
    60. break;
    61. case 9:
    62. //重新初始化
    63. DestryBitree(T);
    64. T=NULL;
    65. break;
    66. case 10:
    67. DestryBitree(T);
    68. break;
    69. default:
    70. if(T!=NULL){
    71. DestryBitree(T);
    72. }
    73. printf("结束操作!");
    74. break;
    75. }
    76. if(flag==11){
    77. break;
    78. }
    79. }
    80. return 0;
    81. }

  • 相关阅读:
    apache部署
    linux之权限管理和组
    VUE -----组件传参
    5分钟搞懂布隆过滤器,掌握亿级数据过滤算法
    从初级软件测试,到高级软件测试的必经之路
    Java中如何判断字符串输入[hello,world]是不是字符串数组参数
    11 场面试无一被拒 Alibaba 金九银十面试参考指南(Java 版)真香
    SPI协议
    如何解决找不到msvcr100.dll问题,msvcr100.dll丢失的多种修复方案
    原生JavaScript实现video视频控制栏
  • 原文地址:https://blog.csdn.net/Keep_Trying_Go/article/details/126411148