二叉树线索化
线索二叉树
按照某种遍历方式对二叉树进行遍历,可以把二叉树中所有结点排序为一个线性序列。在改序列中,除第一个结点外每个结点有且仅有一个直接前驱结点;除最后一个结点外每一个结点有且仅有一个
直接后继结点。这些指向直接前驱结点和指向直接后续结点的指针被称为线索(Thread),加了线索的二叉树称为线索二叉树。
当用二叉链表作为二叉树的存储结构时,因为每个结点中只有指向其左、右儿子结点的指针,所以从任一结点出发只能直接找到该结点的左、右儿子。在一般情况下靠它无法直接找到该结点在某种
遍历序下的前驱和后继结点。如果在每个结点中增加指向其前驱和后继结点的指针,将降低存储空间的效率。
我们可以证明:在n个结点的二叉链表中含有n+1个空指针。因为含n个结点的二叉链表中含有2n个指针,除了根结点,每个结点都有一个从父结点指向该结点的指针,因此一共使用了n-1个指针,所 以在n个结点的二叉链表中含有n+1个空指针。
因此可以利用这些空指针,存放指向结点在某种遍历次序下的前驱和后继结点的指针。这种附加的指针称为线索,加上了线索的二叉链表称为线索链表,相应的二叉树称为线索二叉树(ThreadedBinaryTree)。根据线索性质的不同,线索二叉树可分为前序线索二叉树、中序线索二叉树和后序线索二叉树三种。
程序代码:
1 #include<iostream> 2 using namespace std; 3 typedef enum 4 { 5 LINK, 6 THREAD 7 }PointerTag; 8 template<class T> 9 struct BinaryTreeNodeThd 10 { 11 T _data; 12 BinaryTreeNodeThd<T>* _left; 13 BinaryTreeNodeThd<T>* _right; 14 PointerTag _leftTag; 15 PointerTag _rightTag; 16 BinaryTreeNodeThd() : _left(NULL), _right(NULL), _leftTag(LINK), _rightTag(LINK) 17 {} 18 BinaryTreeNodeThd(const T&data) 19 :_data(data), _left(NULL), _right(NULL), _leftTag(LINK), _rightTag(LINK) 20 {} 21 }; 22 23 template<class T> 24 class BinaryTreeThd 25 { 26 public: 27 BinaryTreeThd() :_root(NULL) 28 {} 29 BinaryTreeThd(const T*a, size_t size) 30 { 31 size_t index = 0; 32 _root = _CreateTree(a, size, index); 33 } 34 BinaryTreeThd(const BinaryTreeThd<T>& t) 35 { 36 _root = _Copy(t._root); 37 } 38 void InOrderThreading() 39 { 40 BinaryTreeNodeThd<T>* prev = NULL; 41 _InOrderThreading(_root, prev); 42 } 43 void PrevOrderThreading() 44 { 45 BinaryTreeNodeThd<T>* prev = NULL; 46 _PrevOrderThreading(_root, prev); 47 } 48 void PostOrderThreading() 49 { 50 BinaryTreeNodeThd<T>* prev = NULL; 51 _PostOrderThreading(_root, prev); 52 } 53 54 public: 55 void InOrderThd() 56 { 57 BinaryTreeNodeThd<T>* cur=_root; 58 while (cur) 59 { 60 while (cur->_leftTag == LINK) 61 { 62 cur = cur->_left; 63 } 64 cout<<cur->_data<<" "; 65 while(cur&&cur->_rightTag == THREAD) 66 { 67 cur = cur->_right; 68 cout << cur->_data; 69 } 70 cur = cur->_right; 71 } 72 cout << endl; 73 } 74 void PrevOrderThd() 75 { 76 BinaryTreeNodeThd<T> *cur =_root; 77 while (cur) 78 { 79 while (cur&&cur->_leftTag == LINK) 80 { 81 cout << cur->_data << " "; 82 cur = cur->_left; 83 } 84 cout << cur->_data << " "; 85 while (cur&&cur->_rightTag == THREAD) 86 { 87 cur = cur->_right; 88 cout << cur->_data << " "; 89 } 90 if (cur->_leftTag == LINK) 91 cur = cur->_left; 92 else 93 cur = cur->_right; 94 } 95 } 96 97 protected: 98 BinaryTreeNodeThd<T>* _CreateTree(const T*a, size_t size, size_t &index) 99 { 100 BinaryTreeNodeThd<T>* root = NULL; 101 if (index < size&&a[index] != '#') 102 { 103 root = new BinaryTreeNodeThd<T>(a[index]); 104 root->_left = _CreateTree(a, size, ++index); 105 root->_right = _CreateTree(a, size, ++index); 106 } 107 return root; 108 } 109 110 void _InOrderThreading(BinaryTreeNodeThd<T>* cur, BinaryTreeNodeThd<T>*& prev) 111 { 112 if (cur == NULL) 113 return; 114 _InOrderThreading(cur->_left, prev); 115 if (cur->_left == NULL) 116 { 117 cur->_leftTag = THREAD; 118 cur->_left = prev; 119 } 120 121 if (prev&&prev->_rightTag == NULL) 122 { 123 prev->_rightTag = THREAD; 124 prev->_right = cur; 125 } 126 127 prev = cur; 128 129 _InOrderThreading(cur->_right, prev); 130 131 } 132 133 void _PrevOrderThreading(BinaryTreeNodeThd<T> *cur, BinaryTreeNodeThd<T>*& prev) 134 { 135 if (cur == NULL) 136 { 137 return; 138 } 139 if (cur->_left == NULL) 140 { 141 cur->_leftTag = THREAD; 142 cur->_left = prev; 143 } 144 145 if (prev&&prev->_right== NULL) 146 147 { 148 149 prev->_rightTag = THREAD; 150 151 prev->_right = cur; 152 153 } 154 155 prev = cur; 156 157 if (cur->_leftTag == LINK) 158 159 { 160 161 _PrevOrderThreading(cur->_left, prev); 162 163 } 164 165 if (cur->_rightTag == LINK) 166 167 { 168 169 _PrevOrderThreading(cur->_right, prev); } 170 171 } 172 173 void _PostOrderThreading(BinaryTreeNodeThd<T> *cur, BinaryTreeNodeThd<T>*& prev) 174 { 175 if (cur == NULL) 176 { 177 return; 178 } 179 _PostOrderThreading(cur->_left, prev); 180 _PostOrderThreading(cur->_right, prev); 181 182 if (cur->_left == NULL) 183 { 184 cur->_leftTag = THREAD; 185 cur->_left = prev; 186 } 187 if (prev&&prev->_right == NULL) 188 { 189 prev->_rightTag = THREAD; 190 prev->_right = cur; 191 } 192 prev = cur; 193 } 194 195 BinaryTreeNodeThd<T>* _Copy(BinaryTreeNodeThd<T>* root) 196 { 197 if (root == NULL) 198 return NULL; 199 BinaryTreeNodeThd<T>* newRoot = new BinaryTreeNodeThd<T>(root->_data); 200 newRoot->_left = _Copy(root->_left); 201 newRoot->_right = _Copy(root->_right); 202 return newRoot; 203 } 204 205 206 207 /*BinaryTreeThd<T>& operator=(BinaryTreeThd<T>*& t) 208 { 209 if (this != &t) 210 { 211 this->_Destory(_root); 212 _root = _Copy(t._root); 213 } 214 return *this; 215 }*/ 216 //BinaryTreeNodeThd<T>& operator=(BinaryTreeNodeThd<T> t) 217 //{ 218 // swap(_root, t._root); 219 // return this; 220 //} 221 222 protected: 223 BinaryTreeNodeThd<T> *_root; 224 }; 225 int main() 226 { 227 int a[] = { 1, 2, 3, '#', '#', 4, '#', '#', 5, 6 }; 228 BinaryTreeThd<int> t(a, 10); 229 BinaryTreeThd<int> temp; 230 t.InOrderThd(); 231 t.InOrderThreading(); 232 //t.PrevOrderThreading(); 233 //t.PostOrderThreading(); 234 cout << endl; 235 system("pause"); 236 return 0; 237 }