当前位置:   article > 正文

树与二叉树---数据结构

树与二叉树---数据结构

 树作为一种逻辑结构,同时也是一种分层结构,具有以下两个特点:

1)树的根结点没有前驱,除根结点外的所有结点有 且只有一个前驱。

2)树中所有结点可以有零个或多个后继。

树结点数据结构

 满二叉树和完全二叉树

注意

完全二叉树,从左到右依次排,没有缺漏

二叉树的顺序存储

二叉树的层次遍历实战

项目结构

function.h文件

  1. #ifndef LEARN_FUNCTION_H
  2. #define LEARN_FUNCTION_H
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. typedef char BiElemType;
  6. typedef struct BiNode{
  7. BiElemType c;
  8. struct BiNode *lchild;
  9. struct BiNode *rchild;
  10. }BiNode, *BiTree;
  11. //tag结构体是辅助队列使用的
  12. typedef struct tag{
  13. BiTree p;//树的某一个结点的地址值
  14. struct tag *pnext;
  15. }tag_t, *ptag_t;
  16. #endif //LEARN_FUNCTION_H

main.cpp文件

calloc

  • 申请的空间大小是两个参数直接相乘,并对空间进行初始化,赋值为0,
  • 头文件#include <stdlib.h>
  1. #include "function.h"
  2. int main(){
  3. BiTree pnew;
  4. char c;
  5. BiTree tree = NULL;
  6. ptag_t phead = NULL,ptail = NULL,listpnew = NULL,pcur;
  7. while(scanf("%c",&c)){
  8. if(c == '\n'){
  9. break;//读到换行就结束
  10. }
  11. //calloc申请的空间大小是两个参数直接相乘,并对空间进行初始化,赋值为0,头文件#include <stdlib.h>
  12. pnew = (BiTree)calloc(1, sizeof(BiNode));
  13. pnew -> c = c;
  14. listpnew = (ptag_t) calloc(1,sizeof(tag_t));//给队列结点申请空间
  15. if(NULL == tree){
  16. tree = pnew;//tree指向树的根结点
  17. phead = listpnew;//第一个结点即是队列头,也是队列尾
  18. ptail = listpnew;//
  19. pcur = listpnew;//pcur要指向要进入树的父亲元素
  20. }else{
  21. //让元素先入队列
  22. ptail -> pnext = listpnew;
  23. ptail = listpnew;
  24. //接下来把b结点放入树中
  25. if(NULL == pcur -> p -> lchild){
  26. pcur -> p -> lchild = pnew;//pcur -> p左孩子为空,就放入左孩子
  27. }else if(NULL == pcur -> p -> rchild){
  28. pcur -> p -> rchild = pnew;//pcur -> p右孩子为空,就放入右孩子
  29. pcur = pcur -> pnext;//当前结点左右孩子都有了,pcur就指向下一个
  30. }
  31. }
  32. }
  33. return 0;
  34. }

二叉树的前序中序后序遍历

代码

main.cpp文件

  1. #include "function.h"
  2. //前序遍历,也叫先序遍历,也是深度优先遍历
  3. void PreOrder(BiTree p){
  4. if(p != NULL){
  5. printf("%c",p -> c);
  6. PreOrder(p -> lchild);//打印左子树
  7. PreOrder(p -> rchild);//打印右子树
  8. }
  9. }
  10. //中序遍历
  11. void InOrder(BiTree p){
  12. if(p != NULL){
  13. InOrder(p -> lchild);//打印左子树
  14. printf("%c",p -> c);
  15. InOrder(p -> rchild);//打印右子树
  16. }
  17. }
  18. //后序遍历
  19. void PostOrder(BiTree p){
  20. if(p != NULL){
  21. PostOrder(p -> lchild);//打印左子树
  22. v(p -> rchild);//打印右子树
  23. printf("%c",p -> c);
  24. }
  25. }
  26. int main(){
  27. BiTree pnew;
  28. char c;
  29. BiTree tree = NULL;
  30. ptag_t phead = NULL,ptail = NULL,listpnew = NULL,pcur;
  31. while(scanf("%c",&c)){
  32. if(c == '\n'){
  33. break;//读到换行就结束
  34. }
  35. //calloc申请的空间大小是两个参数直接相乘,并对空间进行初始化,赋值为0,头文件#include <stdlib.h>
  36. pnew = (BiTree)calloc(1, sizeof(BiNode));
  37. pnew -> c = c;
  38. listpnew = (ptag_t) calloc(1,sizeof(tag_t));//给队列结点申请空间
  39. if(NULL == tree){
  40. tree = pnew;//tree指向树的根结点
  41. phead = listpnew;//第一个结点即是队列头,也是队列尾
  42. ptail = listpnew;//
  43. pcur = listpnew;//pcur要指向要进入树的父亲元素
  44. }else{
  45. //让元素先入队列
  46. ptail -> pnext = listpnew;
  47. ptail = listpnew;
  48. //接下来把b结点放入树中
  49. if(NULL == pcur -> p -> lchild){
  50. pcur -> p -> lchild = pnew;//pcur -> p左孩子为空,就放入左孩子
  51. }else if(NULL == pcur -> p -> rchild){
  52. pcur -> p -> rchild = pnew;//pcur -> p右孩子为空,就放入右孩子
  53. pcur = pcur -> pnext;//当前结点左右孩子都有了,pcur就指向下一个
  54. }
  55. }
  56. }
  57. printf("--------PreOrder--------\n");
  58. PreOrder(tree);
  59. printf("--------InOrder--------\n");
  60. InOrder(tree);
  61. printf("--------PostOrder--------\n");
  62. PostOrder(tree);
  63. return 0;
  64. }

 二叉树的层序遍历

注意:

层序遍历,又称广度优先遍历;而层次遍历中的前序遍历又称深度优先遍历。

项目结构

function.h文件

  1. #ifndef LEARN_FUNCTION_H
  2. #define LEARN_FUNCTION_H
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. typedef char BiElemType;
  6. typedef struct BiNode{
  7. BiElemType c;
  8. struct BiNode *lchild;
  9. struct BiNode *rchild;
  10. }BiNode, *BiTree;
  11. //tag结构体是辅助队列使用的
  12. typedef struct tag{
  13. BiTree p;//树的某一个结点的地址值
  14. struct tag *pnext;
  15. }tag_t, *ptag_t;
  16. //队列的结构体
  17. typedef int ElenType;
  18. typedef struct LinkNode{
  19. ElemType data;
  20. struct LinkNode *next;
  21. }LinkNode;
  22. typedef struct{
  23. LinkNode *front,*rear;//链表头,链表尾,也可以称为对头,队尾
  24. }LinkQueue;//先进先出
  25. void InitQueue(LinkQueue &Q);
  26. bool IsEmpty(LinkQueue Q);
  27. void EnQueue(LinkNode &Q,ElemType x);
  28. bool DeQueue(LinkNode &Q,E;emType &x);
  29. #endif //LEARN_FUNCTION_H

CMakeList.txt文件

里面的内容自动生成

queue.cpp文件

  1. #include "function.h"
  2. //初始化队列
  3. void InitQueue(LinkQueue &Q){
  4. Q.front = Q.rear = (LinkNode*)malloc(sizeof(LinkNode));//头和尾指向同一个结点
  5. Q.front -> next = NULL;//头结点的next指针为NULL
  6. }
  7. //判断队列是否为空
  8. bool IsEmpty(LinkNode Q){
  9. return Q.rear == Q.front;
  10. }
  11. //入队
  12. void EnQueue(LinkQueue &Q,ElemType x){
  13. LinkNode *pnew = (LinkNode*) malloc(sizeof(LinkNode));
  14. pnew -> data = x;
  15. pnew -> next =NULL;//要让next为NULL;
  16. Q.rear -> next = pnew;//尾指针的next指向pnew,因为从尾部入队
  17. Q.rear = pnew;//rear要指向新的尾部
  18. }
  19. bool DeQueue(LinkQueue &Q,ElemType &x){
  20. if(Q.rear == Q.front){//队列为空
  21. return false;
  22. }
  23. LinkNode* q = Q.front -> next;//拿到第一个结点,存入q
  24. x = q -> data;//获取要出对的元素值
  25. Q.front -> next = q->next;//让第一个结点断链
  26. if(Q.rear == q){//链表只剩余一个结点时,被删除后,要改变rear
  27. Q.rear = Q.front;
  28. }
  29. free(q);
  30. return true;
  31. }

main.cpp文件

  1. #include "function.h"
  2. //层次遍历,层序遍历,广度优先遍历
  3. void LevelOrder(BiTree T){
  4. LinkQueue Q;//辅助队列
  5. InitQueue(Q);//初始化队列
  6. BiTree p;
  7. EnQueue(Q,T);//树根入队
  8. while(!IsEmpty(Q)){
  9. DeQueue(Q,p);//出队当前结点并打印
  10. putchar(p->c);
  11. if(p->lchild!=NULL){//入队左孩子
  12. EnQueue(Q,p->lchild);
  13. }
  14. if(p->rchild!=NULL){ //入队右孩子
  15. EnQueue(Q,p->rchild);
  16. }
  17. }
  18. }
  19. //层次建树
  20. int main(){
  21. BiTree pnew;//用来指向新申请的树结点
  22. char c;
  23. BiTree tree=NULL;//树根
  24. //phead 就是队列头,ptail 就是队列尾
  25. ptag_t phead=NULL,ptail=NULL,listpnew=NULL,pcur=NULL;
  26. //输入内容为 abcdefghij
  27. while(scanf("%c",&c)){
  28. if(c=='\n'){
  29. break;
  30. }
  31. pnew=(BiTree)calloc(1,sizeof(BiTNode));//calloc 申请空间并对空间进行初始化,赋值为 0
  32. pnew->c=c;//数据放进去
  33. listpnew=(ptag_t)calloc(1,sizeof(tag_t));//给队列结点申请空间
  34. listpnew->p=pnew;
  35. if(NULL==tree){
  36. tree=pnew;//树的根
  37. phead=listpnew;//队列头
  38. ptail=listpnew;//队列尾
  39. pcur=listpnew;
  40. continue;
  41. }else{
  42. ptail->pnext=listpnew;//新结点放入链表,通过尾插法
  43. ptail=listpnew;//ptail 指向队列尾部
  44. }//pcur 始终指向要插入的结点的位置
  45. if(NULL==pcur->p->lchild)//如何把新结点放入树{
  46. pcur->p->lchild=pnew;//把新结点放到要插入结点的左边
  47. }else if(NULL==pcur->p->rchild){
  48. pcur->p->rchild=pnew;//把新结点放到要插入结点的右边
  49. pcur=pcur->pnext;//左右都放了结点后,pcur 指向队列的下一个
  50. }
  51. }
  52. PostOrder(tree);
  53. printf("\n--------层次遍历-----------\n");
  54. LevelOrder(tree);
  55. printf("\n");
  56. return 0;
  57. }
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/195140
推荐阅读
相关标签
  

闽ICP备14008679号