当前位置:   article > 正文

严蔚敏《数据结构》——二叉树_二叉树严

二叉树严

        几乎还原了严奶奶版数据结构中的代码

        二叉树是树形结构的一个重要类型。许多实际问题抽象出来的数据结构往往是二叉树形式,即使是一般的树也能简单地转换为二叉树,而且二叉树的存储结构及其算法都较为简单,因此二叉树显得特别重要。二叉树特点是每个结点最多只能有两棵子树,且有左右之分。

        二叉树是n个有限元素的集合,该集合或者为空、或者由一个称为根的元素及两个不相交的、被分别称为左子树和右子树的二叉树组成,是有序树。当集合为空时,称该二叉树为空二叉树。在二叉树中,一个元素也称作一个结点

二叉树的遍历:

1.先序遍历: 遍历顺序:ABDECF,遍历规则:先访问根节点,然后遍历左子树,最后遍历右子树。

2.中序遍历:遍历顺序:DBEAFC,遍历规则:先遍历左子树,然后访问根节点,最后遍历右子树。

3.后序遍历:遍历顺序:DEBFCA,遍历规则:先遍历左子树,再遍历右子树,最后访问根节点。

所需要的的存储空间,由于树的遍历有递归和非递归两大类,非递归遍历需要栈的内容,所以存储结构中有栈的存储结构。

  1. #include<cstdio>
  2. #include<cstdlib>
  3. #define OK 1;
  4. #define ERROR 0; //为和教材内容贴合,OK的值设为1,ERROR的值设为0
  5. #define Status int
  6. #define TElemType int
  7. #define MAX_TREE_SIZE 100//二叉树最大节点数
  8. #define MAXSIZE 1000 //链表的最大长度
  9. #define SElemType int
  10. #define STACK_INIT_SIZE 100//定义栈的最大节点数
  11. #define STACKINCREMENT 10 //存储空间分配增量
  12. using namespace std;
  13. typedef TElemType SqBiTree[MAX_TREE_SIZE];
  14. SqBiTree bt;
  15. typedef struct BiTNode {
  16. TElemType data; //数据域
  17. struct BiTNode* lchild, * rchild;//指针域(左右孩子指针)
  18. }BiTNode, *BiTree;
  19. /*------所需要的的栈的存储空间------*/
  20. typedef struct {
  21. SElemType* base;//栈底指针
  22. SElemType* top;//栈顶指针
  23. int stacksize;//栈的长度
  24. }SqStack;

所需要的栈的函数

  1. /*------所需要的的栈的函数------*/
  2. 栈的初始化
  3. Status InitStack(SqStack& S) {
  4. S.base = (SElemType*)malloc(STACK_INIT_SIZE * sizeof(SElemType));//分配存储空间
  5. if (!S.base) printf("存储分配失败!"); exit(OVERFLOW);
  6. S.top = S.base;//栈顶=栈底
  7. S.stacksize = STACK_INIT_SIZE;
  8. printf("栈初始化成功!");
  9. return OK;
  10. }
  11. //入栈
  12. Status Push(SqStack& S, SElemType e) {
  13. if (S.top - S.base > S.stacksize) {//判断栈的大小是否够用,不够用的话重新分配存储空间
  14. S.base = (SElemType*)realloc(S.base, (S.stacksize + STACKINCREMENT) * sizeof(SElemType));
  15. }
  16. if (!S.base) printf("存储分配失败!"); exit(OVERFLOW);
  17. S.top = S.base + S.stacksize;
  18. S.stacksize += STACKINCREMENT;
  19. return OK;
  20. }
  21. //出栈
  22. Status Pop(SqStack& S,SElemType &e) {
  23. if (S.top = S.base) printf("这是一个空栈!"); return 0;
  24. e = *--S.top;
  25. printf("出栈成功!");
  26. return OK;
  27. }
  28. //判断栈空
  29. bool StackEmpty(SqStack S) {
  30. if (S.top=S.base) {
  31. printf("栈空\n");
  32. return true;
  33. }
  34. else {
  35. printf("栈非空\n");
  36. return false;
  37. }
  38. }
  39. //获取栈顶元素
  40. Status GetTop(SqStack S, SElemType e) {
  41. //判断栈空
  42. if (StackEmpty(S)) {
  43. return 0;
  44. }
  45. else {
  46. e = *(S.top - 1);
  47. printf("栈顶元素为%d\n", e);
  48. return 0;
  49. }
  50. return OK;
  51. }
  52. /*--------------------------------------------------------*/

输出树的当前节点

  1. void visit(BiTree &T) {
  2. printf("%d", T->data);//输出树的当前节点
  3. }

二叉树的初始化

  1. //二叉树初始化
  2. void InitBiTree(BiTree &T) {
  3. T->lchild = NULL;
  4. T->rchild = NULL;
  5. }

创建二叉树

  1. //创建二叉树
  2. Status CreateBiTree(BiTree &T) {
  3. int ch;
  4. scanf_s("%d", & ch);
  5. if (ch == ' ') {//出入空格表示当前结束
  6. T = NULL;
  7. }
  8. else {
  9. if (!(T = (BiTNode * )malloc(sizeof(BiTNode)))) exit(OVERFLOW);
  10. T->data = ch;
  11. CreateBiTree(T->lchild);
  12. CreateBiTree(T->rchild);
  13. }
  14. return OK;
  15. }

先序遍历

  1. //先序遍历
  2. Status PreOrderTraverse(BiTree T) {
  3. if (T) {
  4. if (T->data) {
  5. visit(T);
  6. PreOrderTraverse(T->lchild);
  7. PreOrderTraverse(T->rchild);
  8. }
  9. return ERROR;
  10. }
  11. else return ERROR;
  12. return OK;
  13. }

中序遍历

  1. // 中序遍历
  2. Status InOrderTraverse(BiTree T) {
  3. if (T) {
  4. if (T->data) {
  5. InOrderTraverse(T->lchild);
  6. visit(T);
  7. InOrderTraverse(T->lchild);
  8. }
  9. }
  10. }

后序遍历

  1. // 后序遍历
  2. Status PostOrderTraverse(BiTree T) {
  3. if (T) {
  4. if (T->data) {
  5. PostOrderTraverse(T->lchild);
  6. PostOrderTraverse(T->rchild);
  7. visit(T);
  8. }
  9. }
  10. }

书中的一种先序遍历方法以及两种中序遍历方法 非递归法(有错误,正在调试中...)

  1. /*------书中的一种先序遍历方法以及两种中序遍历方法------*/
  2. //先序遍历
  3. Status preOrderTraverse(BiTree T, Status(*Visit)(TElemType e)) {
  4. }
  5. // 中序遍历1
  6. Status inOrderTraverse_1(BiTree T, Status(*Visit)(TElemType e)){
  7. SqStack S;//定义S为SqStack类型的值
  8. BiTNode p;
  9. InitStack(S); Push(S, T->data);//初始化栈,并且将T节点入栈
  10. while (!StackEmpty(S)) {
  11. while (GetTop(S, T->data) && T) {//取栈顶元素
  12. Push(S, p->lchild);
  13. }
  14. Pop(S, T->data);
  15. if (!StackEmpty(S)) {
  16. Pop(S, T->data);
  17. if (!Visit(T->data)) return 0;
  18. Push(S, T->lchild);
  19. }
  20. }
  21. return 1;
  22. }
  23. // 中序遍历2
  24. Status inOrderTraverse_2(BiTree T, Status(*Visit)(TElemType e)) {
  25. SqStack S;
  26. InitStack(S);
  27. BiTree p = T;
  28. while (p || !StackEmpty(S)) {
  29. if (p) {
  30. Push(S, p->data);
  31. p = p->lchild;
  32. }
  33. else {
  34. Pop(S, p->data); if (!Visit(p->data)) return 0;
  35. p = p->rchild;
  36. }
  37. }
  38. return 1;
  39. }

清空二叉树

  1. Status ClearBiTree(BiTree& T) {
  2. PreOrderTraverse(T);
  3. T->lchild = NULL;
  4. T->rchild = NULL;
  5. }

销毁二叉树

  1. Status DestroyBiTree(BiTree &T) {
  2. if (T->data != NULL) {
  3. DestroyBiTree(T->lchild);
  4. DestroyBiTree(T->lchild);
  5. delete T;
  6. }
  7. else {
  8. printf("这本来就是一颗空树!");
  9. }
  10. return 1;
  11. }

判空

  1. bool BiTreeEmpty(BiTree &T) {
  2. if (T->data == NULL) {
  3. printf("这是一个空的二叉树!");
  4. return true;
  5. }
  6. else {
  7. printf("这不是一个空的二叉树!");
  8. return false;
  9. }
  10. }

查询二叉树的深度

  1. Status BiTreeDepth(BiTree T) {
  2. int leftDepth, rightDepth, maxDepth;
  3. if (T != NULL) {
  4. leftDepth = BiTreeDepth(T->lchild);
  5. rightDepth = BiTreeDepth(T->rchild);
  6. maxDepth = leftDepth > rightDepth ? leftDepth : rightDepth;
  7. printf("该二叉树的深度为:%d", maxDepth + 1);
  8. return maxDepth + 1;
  9. }
  10. }

返回二叉树的根节点

  1. //返回该树的根
  2. Status Root(BiTree& T) {
  3. int root = T->data;
  4. if (!T || BiTreeEmpty(T)) {
  5. printf("该树不存在!");
  6. return ERROR;
  7. }
  8. else {
  9. int root = T->data;
  10. printf("该树的根为:%d", root);
  11. }
  12. return root;
  13. }

返回节点的父节点

  1. //返回节点的双亲
  2. BiTree Parent(BiTree T, BiTree ch) {
  3. int parent, c;
  4. parent = T->data;
  5. printf("请输入所需查找双亲的元素:");
  6. scanf_s("%d", &ch);
  7. if (T->data == NULL || T->rchild == ch || T->lchild == ch) return ch;
  8. BiTree left = Parent(T->lchild, ch);
  9. if (left != NULL) return left;
  10. BiTree right = Parent(T->lchild, ch);
  11. if (right != NULL) return right;
  12. return left;
  13. }

返回节点的左右孩子

  1. //该节点的左孩子
  2. Status LeftChild(BiTree T) {
  3. int ch;
  4. int leftchild;
  5. scanf_s("%d", &ch);
  6. if (PreOrderTraverse(T) == ch) {
  7. leftchild = T->data;
  8. }
  9. printf("结点%d的双亲是%d",leftchild);
  10. }
  11. //该节点的右孩子
  12. Status RightChild(BiTree T) {
  13. int ch;
  14. int leftchild;
  15. scanf_s("%d", &ch);
  16. if (PreOrderTraverse(T) == ch) {
  17. leftchild = T->data;
  18. }
  19. printf("结点%d的双亲是%d", leftchild);
  20. }

排除该节点的左右子树

  1. //删除该节点的左子树或右子树
  2. Status DeleteChild(BiTree T) {
  3. int ch;
  4. scanf_s("%d", &ch);
  5. if (PreOrderTraverse(T) == ch) {
  6. DestroyBiTree(T);
  7. }
  8. printf("结点%d的左右子树销毁成功!", ch);
  9. return OK;
  10. }

还差插入元素和访问该节点的左右兄弟...

 main交给各位写了,我实现了没有问题的,有问题的请联系我。

学艺不精,若有错误还请多多指教,谢谢。

p.s.在使用Visual Studio编译器的时候输入scanf()方法要用scanf_s()

更多内容请移步公众号 手撕算法。谢谢

所使用编译器为:Visual Studio2019 链接:https://pan.baidu.com/s/1eg8CNrqrP1jn7GRzHfYXxA
                                                                    提取码:1234

推荐新手使用dev cpp                        链接:https://pan.baidu.com/s       /1XZp_8lVE7X6tMLmvXRbYhw
                                                                     提取码:1234
 

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

闽ICP备14008679号