线索化二叉树

柔光的暖阳◎ 2022-06-16 09:49 237阅读 0赞

二叉树是一种非线性结构,遍历二叉树几乎都是通过递归或者用栈辅助实现非递归的遍历。用二叉树作为存储结构时,取到一个节点,只 能获取节点的左孩子和右孩子,不能直接得到节点的任一遍历序列的前驱或者后继。
为了保存这种在遍历中需要的信息,我们利用二叉树中指向左右子树的空指针来存放节点的前驱和后继信息。
这里写图片描述

前序的线索化:也是建立在前序的递归遍历的基础之上的

  1. void _PreThread(Node*cur, Node*&prev)
  2. {
  3. if (cur == NULL)
  4. {
  5. return;
  6. }
  7. if (cur->Lchild == NULL)
  8. {
  9. cur->Lchild = prev;
  10. cur->LeftTag = THREAD;
  11. }
  12. if (prev&&prev->Rchild == NULL)
  13. {
  14. prev->Rchild = cur;
  15. prev->RightTag = THREAD;
  16. }
  17. prev = cur;
  18. if (cur->LeftTag == LINK)
  19. {
  20. _PreThread(cur->Lchild,prev);
  21. }
  22. if (cur->RightTag == LINK)
  23. {
  24. _PreThread(cur->Rchild,prev);
  25. }
  26. }

根据前序的线索化我们可以写出非递归也不用借助栈就可以实现前序的遍历操作

  1. void PrevOrderThread()
  2. {
  3. Node*cur = _root;
  4. while (cur->LeftTag == LINK)
  5. {
  6. cout << cur->data << " ";
  7. cur = cur->Lchild;
  8. }
  9. cout << cur->data << " ";
  10. cur = cur->Rchild;
  11. }

中序线索化:中序的线索化实际上是建立在中序的递归遍历的基础之上

  1. void _InThread(Node*root, Node* &prev)
  2. {
  3. if (root)
  4. {
  5. _InThread(root->Lchild, prev);
  6. if (root->Lchild == NULL)
  7. root->Lchild = prev;
  8. {
  9. root->LeftTag = THREAD;
  10. }
  11. if (prev!=NULL&&prev->Rchild == NULL)
  12. {
  13. prev->Rchild = root;
  14. prev->RightTag = THREAD;
  15. }
  16. prev = root;
  17. _InThread(root->Rchild,prev);
  18. }
  19. }

根据中序的线索化我们可以写出非递归也不用借助栈就可以实现中序的遍历操作

  1. void InOrderThread(Node *root)
  2. {
  3. if (root == NULL)
  4. {
  5. return;
  6. }
  7. Node *cur = root;
  8. while (cur!=NULL)
  9. {
  10. while (cur->LeftTag == LINK)
  11. {
  12. cur = cur->Lchild;
  13. }
  14. cout << cur->data<<" ";
  15. while (cur->RightTag == THREAD)
  16. {
  17. cur = cur->Rchild;
  18. if (cur == NULL)
  19. {
  20. return;
  21. }
  22. cout << cur->data<<" ";
  23. }
  24. cur = cur->Rchild;
  25. }
  26. }

二叉树的后序线索化需要使用三叉链

  1. #include<iostream>
  2. #include<stdlib.h>
  3. using namespace std;
  4. enum
  5. {
  6. LINK,
  7. THREAD
  8. };
  9. template<class T>
  10. struct BinaryTreeNode
  11. {
  12. BinaryTreeNode(const T&x)
  13. :left(NULL)
  14. ,right(NULL)
  15. , parent(NULL)
  16. , data(x)
  17. , LeftTag(LINK)
  18. , RightTag(LINK)
  19. {
  20. }
  21. BinaryTreeNode<T>*left;
  22. BinaryTreeNode<T>*right;
  23. BinaryTreeNode<T>*parent;
  24. size_t LeftTag;
  25. size_t RightTag;
  26. T data;
  27. };
  28. template<class T>
  29. class BinaryTree
  30. {
  31. typedef BinaryTreeNode<T> Node;
  32. public:
  33. BinaryTree()
  34. {
  35. _root = NULL;//空树
  36. }
  37. BinaryTree(T*arr, size_t size, size_t invalid)
  38. {
  39. size_t index = 0;
  40. Node*prev = NULL;
  41. _root = _CreateBinaryTree(arr, size, invalid, index,prev);
  42. }
  43. void PostThread()
  44. {
  45. Node*prev = NULL;
  46. Node*par = NULL;
  47. _PostThread(_root, prev);
  48. }
  49. void PostOrder() //后序遍历 后序线索化二叉树
  50. {
  51. if (_root == NULL)
  52. return;
  53. Node* cur = _root;
  54. while (cur->LeftTag == LINK || cur->RightTag == LINK)
  55. {
  56. if (cur->LeftTag == LINK)
  57. cur = cur->left;
  58. else if (cur->RightTag == LINK)
  59. cur = cur->right;
  60. }
  61. cout << cur->data << " ";
  62. Node* p = NULL;
  63. while ((p = cur->parent) != NULL)
  64. {
  65. if (p->right == cur || p->RightTag == THREAD)
  66. cur = p;
  67. else
  68. {
  69. cur = p->right;
  70. while (cur->LeftTag == LINK || cur->RightTag == LINK)
  71. {
  72. if (cur->LeftTag == LINK)
  73. cur = cur->left;
  74. else if (cur->RightTag == LINK)
  75. cur = cur->right;
  76. }
  77. }
  78. cout << cur->data << " ";
  79. }
  80. cout << endl;
  81. }
  82. protected:
  83. Node*_CreateBinaryTree(T*arr, size_t size, size_t invalid, size_t &index,Node*&prev)
  84. {
  85. Node*root = NULL;
  86. if (index < size&&arr[index] != invalid)
  87. {
  88. root = new Node(arr[index]);
  89. root->parent = prev;
  90. prev = root;
  91. root->left = _CreateBinaryTree(arr, size, invalid, ++index,prev);
  92. prev = root;
  93. root->right = _CreateBinaryTree(arr, size, invalid,++index,prev);
  94. }
  95. return root;
  96. }
  97. void _PostThread(Node*cur,Node*&prev)
  98. {
  99. if (cur == NULL)
  100. {
  101. return;
  102. }
  103. _PostThread(cur->left, prev);
  104. _PostThread(cur->right, prev);
  105. if (cur->left == NULL)
  106. {
  107. cur->left = prev;
  108. cur->LeftTag = THREAD;
  109. }
  110. if (prev&&prev->right == NULL)
  111. {
  112. prev->right = cur;
  113. prev->RightTag = THREAD;
  114. }
  115. prev = cur;
  116. }
  117. Node* _root;
  118. };
  119. void PostFunTest()
  120. {
  121. int arr[] = { 1, 2, 3, '#', '#', 4, '#', '#', 5, 6 };
  122. int array[15] = { 1, 2, '#', 3, '#', '#', 4, 5, '#', 6, '#', 7, '#', '#', 8 };
  123. BinaryTree<int> t1(arr, (sizeof(arr) / sizeof(arr[0])), '#');
  124. BinaryTree<int> t2(array, (sizeof(array) / sizeof(array[0])), '#');
  125. t1.PostThread();
  126. t1.PostOrder();
  127. cout << endl;
  128. t2.PostThread();
  129. t2.PostOrder();
  130. }
  131. int main()
  132. {
  133. PostFunTest();
  134. system("pause");
  135. return 0;
  136. }

发表评论

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

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

相关阅读

    相关 线索

    1,线索化二叉树基本介绍 线索化二叉树是对普通二叉树的扩展,对于普通二叉树而言,一个节点会包含一个数据域以及指向左右子节点的位置索引;但是对于叶子节点来讲,左右子节

    相关 线索算法

    二叉树线索化 简述 为什么需要线索二叉树? 1. 对于普通的二叉树来说,如果随便给出二叉树中的一个结点,让你从这个结点遍历整个二叉树,这是做不到的(其实对于普通

    相关 线索

    二叉树是一种非线性结构,遍历二叉树几乎都是通过递归或者用栈辅助实现非递归的遍历。用二叉树作为存储结构时,取到一个节点,只 能获取节点的左孩子和右孩子,不能直接得到节点的任一遍历