c++ 二叉树的线索化(前中后序遍历)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c++ 二叉树的线索化(前中后序遍历)相关的知识,希望对你有一定的参考价值。
#pragma once//.hpp函数头文件 #include<iostream> using namespace std; enum BinTreeNodeChildType { Thread, Link }; template <class T> struct BinaryTreeThrNode { public: T _data; //数据域 BinaryTreeThrNode<T>* _leftChild;//做孩子 BinaryTreeThrNode<T>* _rightChild;//右孩子 BinTreeNodeChildType _leftType;//左节点类型 BinTreeNodeChildType _rightType;//右节点类型 BinaryTreeThrNode<T>* _parent;//父节点 (后续线索化 遍历 用到) public: BinaryTreeThrNode(const T& data) :_data(data) , _leftChild(NULL) , _rightChild(NULL) , _leftType(Link) , _rightType(Link) , _parent(NULL) {} ~BinaryTreeThrNode() {} }; template <class T> class BinaryTreeThread { public: BinaryTreeThrNode<T>* _root; public: BinaryTreeThread() :_root(NULL) {} BinaryTreeThread(T*a, size_t size) { size_t index = 0; _root = _CreateBiTree(a, index, size); } void InOrderThread() { BinaryTreeThrNode<T>* prev = NULL; BinaryTreeThrNode<T>* cur = _root; _InOrderThread(cur,prev ); } void PreOrderThread() { BinaryTreeThrNode<T>* prev = NULL; _PreOrderThread(_root,prev); } void InOrderThe1() //cur每次循环跳一次 { BinaryTreeThrNode<T>* cur = _root; BinaryTreeThrNode<T>*prev = _root; while (cur) { if (cur->_leftChild&&prev->_rightChild != cur&&cur->_leftType == Link) cur = cur->_leftChild; else { cout << cur->_data << ‘ ‘; if (cur->_rightType == Thread) prev = cur; cur = cur->_rightChild; } } } void InOrderThe() //cur每次循环中有循环 { BinaryTreeThrNode<T>* cur = _root; while (cur) { while (cur&&cur->_leftType == Link) { cur = cur->_leftChild; } cout << cur->_data << ‘ ‘; while (cur&&cur->_leftType== Thread) { cur = cur->_rightChild; cout << cur->_data<<‘ ‘; } cur = cur->_rightChild; } } //前序线索遍历 void PreOrderThe() { BinaryTreeThrNode<T>* cur = _root; while (cur&&cur->_rightChild) { while (cur->_leftType != Thread) { cout << cur->_data << ‘ ‘; cur = cur->_leftChild; } while (cur->_rightType == Thread) { cout << cur->_data << ‘ ‘; cur = cur->_rightChild; if (cur->_rightChild == NULL) cout << cur->_data << ‘ ‘; } } } //后续线索遍历 void PostOrderThe1()//老师的方法 { if (_root == NULL) return; BinaryTreeThrNode<T>* cur = _root->_left; BinaryTreeThrNode<T>* prev = NULL; while (cur != _root) { // 1.找最左节点 while (cur && cur->_leftTag == LINK) cur = cur->_left; while (cur && cur->_rightTag == THREAD) { cout << cur->_data << " "; prev = cur; cur = cur->_right; } // 当跳到root则遍历完成 if (cur == _root) { cout << _root->_data << " "; break; } // 一个节点的右树已经访问完成,则跳转到根节点 if (cur && cur->_rightTag == LINK && cur->_right == prev) { cout << cur->_data << " "; prev = cur; cur = cur->_parent; } // 往右树跳转 if (cur && cur->_rightTag == LINK) { cur = cur->_right; } } cout << endl; } void PosOrderThe()//后续线索遍历(借助 父节点) { BinaryTreeThrNode<T>* cur = _root; BinaryTreeThrNode<T>* prev = NULL;//防止死循环的记录指针 while (cur) { while (prev!=cur->_leftChild&&cur!=prev&&cur->_leftType != Thread)//左支不为Thread且 prev不为cur坐支且prev!=cur 循环压左 cur = cur->_leftChild; if (prev==cur&&cur->_rightType == Link)//右支不为Thread类型 压右 cur = cur->_rightChild; else { while (cur->_rightType == Thread) //右支为Thread类型 循环压右 输出 { cout << cur->_data << ‘ ‘; cur = cur->_rightChild; prev= cur; } cout << cur->_data << ‘ ‘; cur = cur->_parent; if (cur&&cur->_rightType == Link&&cur->_leftChild==prev) { prev = cur;//prev始终为右支返回的父节点 } } if (cur == _root&&prev != cur)//prev是从右支返回的并且 cur为根节点结束循环 { cout << cur->_data << ‘ ‘; break; } } } //后续线索化 void PosOrderThread() { BinaryTreeThrNode<T>* prev = NULL; _PosOrderThread(_root,prev); } BinaryTreeThrNode<T>* _CreateBiTree(const T* tmp, size_t& index, size_t size) { BinaryTreeThrNode<T>* root = NULL; BinaryTreeThrNode<T>* parent = NULL; if (index < size&&tmp[index] != ‘#‘) { root = new BinaryTreeThrNode<T>(tmp[index]); parent=_CreateBiTree(tmp, ++index, size); if (parent) { root->_leftChild = parent; parent->_parent = root; } parent = _CreateBiTree(tmp, ++index, size); } if (parent) { root->_rightChild = parent; parent->_parent = root; } return root; } //中序线索化 void _InOrderThread(BinaryTreeThrNode<T>*cur,BinaryTreeThrNode<T>* & prev) { if (cur ==NULL) return; _InOrderThread(cur->_leftChild,prev);//向左树遍历 if (cur->_leftChild==NULL) //左为空 改变左类型 左指向prev { cur->_leftType = Thread; cur->_leftChild = prev; } if (prev&&prev->_rightChild == NULL) //prev!=NULL 且prev右不空 改变右类型 让右指向当前 { prev->_rightType = Thread; prev->_rightChild = cur; } prev = cur; //prev指向递归返回前的节点 _InOrderThread(cur->_rightChild, prev); //指向右数节点 } //前序线索化 自己的笨办法 void _PreOrderThread1(BinaryTreeThrNode<T>* cur, BinaryTreeThrNode<T>* &prev) { if (cur == NULL) return; if (prev&&prev->_rightType == Thread&&prev->_rightChild==NULL)//给右为空的左节点 prev->_rightChild = cur; if (cur->_leftChild)//左不空 压左 { prev = cur; //prev=上个节点 _PreOrderThread(cur->_leftChild, prev); } else { cur->_leftType = Thread;//左空 左节点类型为线索类型 cur->_leftChild = prev;//线索指向prev } if (cur->_rightChild)//右不为空 { _PreOrderThread(cur->_rightChild, prev);//压右 } else { if (prev&&prev->_rightType==Thread&&cur->_leftType==Link&&cur->_rightChild==NULL) cur->_rightChild =prev;//判断是否该节点为只有左分支 是的话使右线索指向左分支 cur->_rightType = Thread;//右分支为线索类型 if (cur->_rightChild==NULL)//不连续压左情况 右分支为空 使prev=cur prev = cur; } } void _PreOrderThread(BinaryTreeThrNode<T>* cur, BinaryTreeThrNode<T>* &prev)//老师方法 { if (cur == NULL)//空返回 return; if (cur->_leftChild == NULL)//左植线索化 当前递归中 { cur->_leftType = Thread; cur->_leftChild = prev; } if (prev&&prev->_rightChild == NULL)//右植线索化 返回上次递归中 { prev->_rightType = Thread; prev->_rightChild = cur; } prev = cur; //prev为上次递归cur if (cur->_leftType==Link)//cur左值类型为节点类型 继续递归 _PreOrderThread(cur->_leftChild, prev); if (cur->_rightType==Link)//cur右植类型为节点类型 继续递归 _PreOrderThread(cur->_rightChild, prev); } //后续线索化 void _PosOrderThread(BinaryTreeThrNode<T>* cur,BinaryTreeThrNode<T>*& prev) { if (cur == NULL) return; if (cur->_leftChild == NULL)//作为空左支线索化=prev { cur->_leftType = Thread; cur->_leftChild = prev; } if (cur->_leftType==Link)//cur左支类型为节点类型 递归左 _PosOrderThread(cur->_leftChild,prev); if (cur->_rightType==Link)//cur右植为节点类型 递归右 _PosOrderThread(cur->_rightChild,prev); if (prev&&prev->_rightChild == NULL) //prev右植为空 prev指向当前 { prev->_rightType = Thread; prev->_rightChild = cur; } prev = cur; //子树递归结束 prev=cur } }; //测试用例 #include"bintreethread.hpp" #include"BinaryTreeThreading.h" using namespace std; void test() { int a[10] = { 1, 2, 3, ‘#‘, ‘#‘,4, ‘#‘, ‘#‘, 5, 6 }; int s[18] = { 1, 2, 3, 4, ‘#‘, ‘#‘, 5, ‘#‘, ‘#‘, 6, ‘#‘, ‘#‘, 7, 8, ‘#‘, ‘#‘, 9, 10 }; int k[14] = { 1, 2, 3, 4, ‘#‘,‘#‘,‘#‘,5,‘#‘,‘#‘, 6, 7,‘#‘,‘#‘ }; BinaryTreeThread<int> s1; BinaryTreeThread<int> s2(s,18); //BinaryTreeThread<int> s2(k, 14); //BinaryTreeThread<int> s2(a, 10); /*s2.InOrderThread(); s2.InOrderThe();*/ //s2.PreOrderThread(); s2.PosOrderThread(); s2.PosOrderThe(); } int main() { test(); return 0; }
以上是关于c++ 二叉树的线索化(前中后序遍历)的主要内容,如果未能解决你的问题,请参考以下文章
C++实现二叉树 前中后序遍历(递归与非递归)非递归实现过程最简洁版本