二叉树层次建树,前序(递归与非递归)遍历--中序遍历(递归与非递归)-后序遍历-层次遍历

忘是亡心i 2023-09-29 11:26 117阅读 0赞

创建一个二叉树

创建项目为创建C++项目

1.导包

开始前需要写一些导包

  1. #define _CRT_SECURE_NO_WARNINGS
  2. #include<stdio.h>
  3. #include<stdlib.h>

_CRT_SECURE_NO_WARNINGS这一串写或者不写跟你使用的编译器有关,此处是为了解决scanf()的正常run——此处我用的是visual Studio 2022

2.类型别名设定

  1. #define MaxSize 50
  2. typedef int ElemType;
  3. typedef char BiElemType;

3.结构引入

二叉树的结构

  1. typedef struct BiTNode {
  2. //二叉树的树节点
  3. BiElemType c;//c就是书籍上的data
  4. struct BiTNode* lchild;
  5. struct BiTNode* rchild;
  6. }BiTNode,*BiTree;

储存树节点的队列节点

  1. typedef struct tag {
  2. //储存树节点的队列节点
  3. BiTree p;//树
  4. struct tag* pnext;
  5. }tag_t,*ptag_t;

递归实现 前序遍历(先序遍历)

(先打印当前节点,再打印左孩子,再打印右孩子)

  1. //递归实现 前序遍历(先序遍历)(先打印当前节点,再打印左孩子,再打印右孩子)
  2. void preOrder(BiTree p) {
  3. if (p != NULL) {
  4. putchar(p->c);//等价于visit函数
  5. preOrder(p->lchild);
  6. preOrder(p->rchild);
  7. }
  8. }

中序遍历

  1. //中序遍历
  2. void InOrder(BiTree p) {
  3. if (p!=NULL) {
  4. InOrder(p->lchild);
  5. putchar(p->c);
  6. InOrder(p->rchild);
  7. }
  8. }

后序遍历

  1. void PostOrder(BiTree p) {
  2. if (p != NULL) {
  3. PostOrder(p->lchild);
  4. PostOrder(p->rchild);
  5. putchar(p->c);
  6. }
  7. }

中序遍历非递归,

非递归执行效率更高,需要借助来进行
因此先创建栈的结构

  1. //typedef BiTree ElemType
  2. //上行代码 当与写在一个页面的时候感觉会与之前设定的产生不必要的混淆
  3. //因此,将所有的原本的 ElemType 修改为 BiTree
  4. //如果你单独使用 上行代码时,也可以将BiTree 修改为ElemType
  5. typedef struct {
  6. //栈
  7. BiTree data[MaxSize];
  8. int top;
  9. }SqStack;
  10. //初始化栈
  11. void InitStack(SqStack& S) {
  12. S.top = -1;
  13. }
  14. bool StackEmpty(SqStack& S) {
  15. if (S.top==-1) {
  16. return true;
  17. }
  18. else {
  19. return false;
  20. }
  21. }
  22. //入栈
  23. bool Push(SqStack& S, BiTree x) {
  24. if (S.top==MaxSize-1) {
  25. return false;
  26. }
  27. S.data[++S.top] = x;
  28. return true;
  29. }
  30. //出栈
  31. bool Pop(SqStack& S, BiTree&x) {
  32. if (-1==S.top) {
  33. return false;
  34. }
  35. x = S.data[S.top--];
  36. return true;
  37. }
  38. //获取栈顶元素
  39. bool GetTop(SqStack& S, BiTree& x) {
  40. if (-1 == S.top) {
  41. return false;
  42. }
  43. x = S.data[S.top];
  44. return true;
  45. }
  46. //中序遍历非递归,非递归执行效率更高,
  47. //中序遍历非递归
  48. void InOrder2(BiTree T) {
  49. SqStack S;
  50. InitStack(S);//初始化栈
  51. BiTree p = T;
  52. while (p || !StackEmpty(S)) {
  53. //逻辑 或者 ||
  54. if (p) {
  55. Push(S,p);
  56. p = p->lchild;
  57. }
  58. else {
  59. Pop(S, p);
  60. putchar(p->c);
  61. p = p->rchild;
  62. }
  63. }
  64. }

层次遍历(广度优先遍历)

  1. //初始化队列 带头节点的队列
  2. void InitQueue(LinkQueue& Q) {
  3. Q.front = Q.rear = (LinkNode*)malloc(sizeof(LinkNode));
  4. Q.front->next = NULL;
  5. }
  6. bool IsEmpty(LinkQueue Q) {
  7. if (Q.front==Q.rear)
  8. {
  9. return true;
  10. }
  11. else {
  12. return false;
  13. }
  14. }
  15. //入队
  16. void EnQueue(LinkQueue& Q, BiTree x){
  17. LinkNode* s = (LinkNode*)malloc(sizeof(LinkNode));
  18. s->data = x;
  19. s->next = NULL;
  20. Q.rear->next = s;
  21. Q.rear = s;
  22. }
  23. //出队
  24. bool DeQueue(LinkQueue &Q,BiTree &x) {
  25. if (Q.front == Q.rear) {
  26. return false;
  27. }
  28. LinkNode* p = Q.front->next;//头结点什么都没存,所以头结点的下一个结点才有数据
  29. x = p->data;
  30. Q.front->next = p->next;
  31. if (Q.rear == p) {
  32. Q.rear = Q.front;
  33. }
  34. free(p);
  35. return true;
  36. }
  37. //层次遍历 (广度优先遍历) 运用到辅助队列
  38. void LevelOrder(BiTree T) {
  39. LinkQueue Q;//辅助队列
  40. InitQueue (Q);//初始化队列
  41. BiTree p;
  42. EnQueue(Q,T);//树根入队
  43. while (!IsEmpty(Q)) {
  44. DeQueue(Q,p);
  45. putchar(p->c);
  46. if (p->lchild!=NULL)
  47. {
  48. EnQueue(Q, p->lchild);
  49. };
  50. if (p->rchild!=NULL)
  51. {
  52. EnQueue(Q, p->rchild);
  53. }
  54. }
  55. }

主函数

  1. int main() {
  2. // ①树根要置空 队列初始化
  3. BiTree pnew; //二叉树结构指针
  4. //int i, j, pos;
  5. char c;
  6. BiTree tree = NULL;//树根(主)
  7. ptag_t phead = NULL, ptail = NULL, listpnew = NULL, pcur=NULL;
  8. //phead队列头 ptail队列尾 不带头节点的队列 pcur始终指向要插入的节点的位置
  9. //②数据开始进入 abcdefghij ||一开始a进来
  10. while (scanf("%c",&c) != EOF) {
  11. //结束循环
  12. if (c == '\n') {
  13. //等于回车退出循环
  14. break;
  15. }
  16. //③新建一个二叉树的节点空间 用于存储进来的a
  17. //将数据放入空间 pnew二叉树结构指针内有 c lchild rchild 三个参数
  18. // ||当a刚进来时,new一个树的节点空间
  19. pnew = (BiTree)calloc(1, sizeof(BiTNode));//pnew通过calloc申请一个空间并且对空间进行初始化,赋值0
  20. pnew->c = c;//将数据放入pnew->c中 (放入树中)
  21. //④新建一个队列的节点空间 将整个二叉树节点存入队列
  22. //listpnew 队列链表 内有 p pnext 两个参数
  23. //p(树节点)中有 c lchild rchild
  24. //pnext中为p pnext
  25. listpnew = (ptag_t)calloc(1,sizeof(tag_t));//给队列节点申请一个空间,
  26. listpnew->p = pnew; //将树节点作为数据存入队列
  27. //⑤首次存a时,树还为空 需要走下边的判断
  28. if (NULL == tree) {
  29. //当主树根若为空,构建辅助队列
  30. //a放入树根
  31. tree = pnew;//树的根 此时让a作为树根
  32. //a放入队列
  33. //此时 由于队列中只有一个a,因此a既做队列头也做队列尾
  34. phead = listpnew;//队列头 队列头指针
  35. ptail = listpnew;//队列尾 队列尾指针 队列中储存的是树节点的地址
  36. pcur = listpnew; //pcur始终指向要插入的节点的位置
  37. //⑥ continue 此次循环结束
  38. continue;
  39. }
  40. //⑦ ①-④步相同 不过此时进入的是b 放入队列,通过尾插法
  41. else {
  42. //b当已经有主树的时候
  43. ptail->pnext = listpnew;// 新结点B放入队列,通过尾插法
  44. ptail = listpnew;//ptail队列尾指针 指向队列尾(新插入的b)
  45. }
  46. //⑧ 队列判断结束后,开始判断b进入树
  47. //⑨ a节点树的左孩子若为空 新节点b放在tree的lchild里
  48. if (NULL == pcur->p->lchild) {
  49. //pcur为首次存放入a的时候给的定义
  50. pcur->p->lchild = pnew; //pcur始终指向要插入的节点的位置
  51. }
  52. //⑩ 1-8相同 但9不同 a节点树的左孩子存在值 新节点c放在tree的rchild里
  53. else if(NULL == pcur->p->rchild){
  54. pcur->p->rchild = pnew; //pcur始终指向要插入的节点的位置
  55. pcur = pcur->pnext;//当左右孩子都放了后,就pcur指向下一个
  56. }
  57. }
  58. printf("答案输出\n");
  59. printf("------------前序遍历------------\n"); //(先打印当前节点,再打印左孩子,再打印右孩子)
  60. preOrder(tree);//abc a bde cfg a b dhi ej c fg
  61. printf("\n------------中序遍历------------\n");//(先打印打印左孩子,再打印当前节点,再打印右孩子)--------从上到下一脚踩扁
  62. InOrder(tree); //bac dbe a fcg hdibjeafcg
  63. printf("\n------------后序遍历------------\n");//先打印打印左孩子,再打印右孩子,再打印当前节点
  64. PostOrder(tree);//bca deb fgc a hid jeb fgc a hidjebfgca
  65. //printf("\n------------中序遍历非递归------\n");//难度比较大
  66. // InOrder2(tree);
  67. //printf("\n------------层次遍历------------\n");
  68. }

发表评论

表情:
评论列表 (有 0 条评论,117人围观)

还没有评论,来说两句吧...

相关阅读