第四次作業——04樹
第四次作業——樹
一.學習總結
樹的思維結構圖
2.對於樹學習總結
⑴.樹結構認識:樹是一種非線性結構,每個節點有0個或多個後繼節點,有且僅有一個前驅節點(根節點除外)。在樹中,遞歸方法可以放在考慮的首要位置
⑵.學習這個結構遇到的困難:遞歸調用不會很清晰,代碼量大,較難記憶。
⑶.樹結構可以解決的問題:並查集問題 哈夫曼編碼的問題。
二.6-1 二叉樹操作集
1.設計思路
void CreateBTree(BTree &BT,string str)
{
創建一個樹T
定義一個i來計數
創建一個隊列Q
if str[i]!=‘\0‘
{
BT申請空間
BT->data = str[i]
初始化BT的左右孩子
push(BT)
}
else BT為空樹
while 隊列不為空
{
T=front()
pop()
i++
if str[i]為‘#‘
令T的左孩子為NULL
else
{
T的左孩子申請空間
T->lchild->data = str[i]
初始化T->lchild的左右孩子
push(T->lchild)
}
i++
if str[i]為‘#‘
令T的右孩子為NULL
else
{
T的右孩子申請空間
T->rchild->data = str[i]
初始化T->rchild的左右孩子
push(T->rchild)
}
}
}
2.代碼截圖
3.提交代碼結果
三.6-2求二叉樹高度
1.代碼截圖
2.提交代碼結果
四.6-4 jmu-ds-表達式樹
1.設計思路
2.代碼截圖
3.提交代碼結果
4.遇到的問題
⑴.沒有考慮遍歷完字符串後運算符棧中還存在運算符的可能。
⑵.粗心大意把a*b
打成了a-b
五.分數總結
1.PTA排名情況
2.我的總分:1.5分
3.閱讀代碼
題目:平衡二叉樹詳解
1 #include <iostream> 2 #include <algorithm> 3 using namespace std;4 #pragma once 5 6 //平衡二叉樹結點 7 template <typename T> 8 struct AvlNode 9 { 10 T data; 11 int height; //結點所在高度 12 AvlNode<T> *left; 13 AvlNode<T> *right; 14 AvlNode<T>(const T theData) : data(theData), left(NULL), right(NULL), height(0){} 15 };16 17 //AvlTree 18 template <typename T> 19 class AvlTree 20 { 21 public: 22 AvlTree<T>(){} 23 ~AvlTree<T>(){} 24 AvlNode<T> *root; 25 //插入結點 26 void Insert(AvlNode<T> *&t, T x); 27 //刪除結點 28 bool Delete(AvlNode<T> *&t, T x); 29 //查找是否存在給定值的結點 30 bool Contains(AvlNode<T> *t, const T x) const; 31 //中序遍歷 32 void InorderTraversal(AvlNode<T> *t); 33 //前序遍歷 34 void PreorderTraversal(AvlNode<T> *t); 35 //最小值結點 36 AvlNode<T> *FindMin(AvlNode<T> *t) const; 37 //最大值結點 38 AvlNode<T> *FindMax(AvlNode<T> *t) const; 39 private: 40 //求樹的高度 41 int GetHeight(AvlNode<T> *t); 42 //單旋轉 左 43 AvlNode<T> *LL(AvlNode<T> *t); 44 //單旋轉 右 45 AvlNode<T> *RR(AvlNode<T> *t); 46 //雙旋轉 右左 47 AvlNode<T> *LR(AvlNode<T> *t); 48 //雙旋轉 左右 49 AvlNode<T> *RL(AvlNode<T> *t); 50 }; 51 52 template <typename T> 53 AvlNode<T> * AvlTree<T>::FindMax(AvlNode<T> *t) const 54 { 55 if (t == NULL) 56 return NULL; 57 if (t->right == NULL) 58 return t; 59 return FindMax(t->right); 60 } 61 62 template <typename T> 63 AvlNode<T> * AvlTree<T>::FindMin(AvlNode<T> *t) const 64 { 65 if (t == NULL) 66 return NULL; 67 if (t->left == NULL) 68 return t; 69 return FindMin(t->left); 70 } 71 72 73 template <typename T> 74 int AvlTree<T>::GetHeight(AvlNode<T> *t) 75 { 76 if (t == NULL) 77 return -1; 78 else 79 return t->height; 80 } 81 82 83 //單旋轉 84 //左左插入導致的不平衡 85 template <typename T> 86 AvlNode<T> * AvlTree<T>::LL(AvlNode<T> *t) 87 { 88 AvlNode<T> *q = t->left; 89 t->left = q->right; 90 q->right = t; 91 t = q; 92 t->height = max(GetHeight(t->left), GetHeight(t->right)) + 1; 93 q->height = max(GetHeight(q->left), GetHeight(q->right)) + 1; 94 return q; 95 } 96 97 //單旋轉 98 //右右插入導致的不平衡 99 template <typename T> 100 AvlNode<T> * AvlTree<T>::RR(AvlNode<T> *t) 101 { 102 AvlNode<T> *q = t->right; 103 t->right = q->left; 104 q->left = t; 105 t = q; 106 t->height = max(GetHeight(t->left), GetHeight(t->right)) + 1; 107 q->height = max(GetHeight(q->left), GetHeight(q->right)) + 1; 108 return q; 109 } 110 111 //雙旋轉 112 //插入點位於t的左兒子的右子樹 113 template <typename T> 114 AvlNode<T> * AvlTree<T>::LR(AvlNode<T> *t) 115 { 116 //雙旋轉可以通過兩次單旋轉實現 117 //對t的左結點進行RR旋轉,再對根節點進行LL旋轉 118 RR(t->left); 119 return LL(t); 120 } 121 122 //雙旋轉 123 //插入點位於t的右兒子的左子樹 124 template <typename T> 125 AvlNode<T> * AvlTree<T>::RL(AvlNode<T> *t) 126 { 127 LL(t->right); 128 return RR(t); 129 } 130 131 132 template <typename T> 133 void AvlTree<T>::Insert(AvlNode<T> *&t, T x) 134 { 135 if (t == NULL) 136 t = new AvlNode<T>(x); 137 else if (x < t->data) 138 { 139 Insert(t->left, x); 140 //判斷平衡情況 141 if (GetHeight(t->left) - GetHeight(t->right) > 1) 142 { 143 //分兩種情況 左左或左右 144 145 if (x < t->left->data)//左左 146 t = LL(t); 147 else //左右 148 t = LR(t); 149 } 150 } 151 else if (x > t->data) 152 { 153 Insert(t->right, x); 154 if (GetHeight(t->right) - GetHeight(t->left) > 1) 155 { 156 if (x > t->right->data) 157 t = RR(t); 158 else 159 t = RL(t); 160 } 161 } 162 else 163 ;//數據重復 164 t->height = max(GetHeight(t->left), GetHeight(t->right)) + 1; 165 } 166 167 template <typename T> 168 bool AvlTree<T>::Delete(AvlNode<T> *&t, T x) 169 { 170 //t為空 未找到要刪除的結點 171 if (t == NULL) 172 return false; 173 //找到了要刪除的結點 174 else if (t->data == x) 175 { 176 //左右子樹都非空 177 if (t->left != NULL && t->right != NULL) 178 {//在高度更大的那個子樹上進行刪除操作 179 180 //左子樹高度大,刪除左子樹中值最大的結點,將其賦給根結點 181 if (GetHeight(t->left) > GetHeight(t->right)) 182 { 183 t->data = FindMax(t->left)->data; 184 Delete(t->left, t->data); 185 } 186 else//右子樹高度更大,刪除右子樹中值最小的結點,將其賦給根結點 187 { 188 t->data = FindMin(t->right)->data; 189 Delete(t->right, t->data); 190 } 191 } 192 else 193 {//左右子樹有一個不為空,直接用需要刪除的結點的子結點替換即可 194 AvlNode<T> *old = t; 195 t = t->left ? t->left: t->right;//t賦值為不空的子結點 196 delete old; 197 } 198 } 199 else if (x < t->data)//要刪除的結點在左子樹上 200 { 201 //遞歸刪除左子樹上的結點 202 Delete(t->left, x); 203 //判斷是否仍然滿足平衡條件 204 if (GetHeight(t->right) - GetHeight(t->left) > 1) 205 { 206 if (GetHeight(t->right->left) > GetHeight(t->right->right)) 207 { 208 //RL雙旋轉 209 t = RL(t); 210 } 211 else 212 {//RR單旋轉 213 t = RR(t); 214 } 215 } 216 else//滿足平衡條件 調整高度信息 217 { 218 t->height = max(GetHeight(t->left), GetHeight(t->right)) + 1; 219 } 220 } 221 else//要刪除的結點在右子樹上 222 { 223 //遞歸刪除右子樹結點 224 Delete(t->right, x); 225 //判斷平衡情況 226 if (GetHeight(t->left) - GetHeight(t->right) > 1) 227 { 228 if (GetHeight(t->left->right) > GetHeight(t->left->left)) 229 { 230 //LR雙旋轉 231 t = LR(t); 232 } 233 else 234 { 235 //LL單旋轉 236 t = LL(t); 237 } 238 } 239 else//滿足平衡性 調整高度 240 { 241 t->height = max(GetHeight(t->left), GetHeight(t->right)) + 1; 242 } 243 } 244 245 return true; 246 } 247 248 //查找結點 249 template <typename T> 250 bool AvlTree<T>::Contains(AvlNode<T> *t, const T x) const 251 { 252 if (t == NULL) 253 return false; 254 if (x < t->data) 255 return Contains(t->left, x); 256 else if (x > t->data) 257 return Contains(t->right, x); 258 else 259 return true; 260 } 261 262 //中序遍歷 263 template <typename T> 264 void AvlTree<T>::InorderTraversal(AvlNode<T> *t) 265 { 266 if (t) 267 { 268 InorderTraversal(t->left); 269 cout << t->data << ‘ ‘; 270 InorderTraversal(t->right); 271 } 272 } 273 274 //前序遍歷 275 template <typename T> 276 void AvlTree<T>::PreorderTraversal(AvlNode<T> *t) 277 { 278 if (t) 279 { 280 cout << t->data << ‘ ‘; 281 PreorderTraversal(t->left); 282 PreorderTraversal(t->right); 283 } 284 }
功能:平衡二叉樹大部分操作和二叉查找樹類似,主要不同在於插入刪除的時候平衡二叉樹的平衡可能被改變,並且只有從那些插入點到根結點的路徑上的結點的平衡性可能被改變,因為只有這些結點的子樹可能變化。
第四次作業——04樹