0.簡介
刪除平衡二叉樹的結點也需要仔細的研究一下。還有代碼上對上一篇打了些補丁
1.刪除
刪除結點後的結構一般有兩種,一類是刪除後不平衡了,一類是刪除後仍然平衡。這兩類別目前對我們來說,沒有什麼區別,因爲前面已經研究過結點平衡調整的方法,所以可以直接在這裏使用,那麼需要研究的就是如何刪除結點。
我們先從鏈表的角度來看,鏈表刪除比較容易,改變指向下一個結點的指針就好,一般來說,改變一個就可以。
二叉樹來說,刪除就麻煩了一些,要有兩個指針需要變化,鏈表只需要考慮下一個元素怎麼連接上就好,樹要考慮子節點誰來連接。
我們考慮讓子節點的任意一個來接替位置,我們就一律讓右邊的結點來接替父節點的位置,左節點保持不動,若沒有右結點,在去升左結點的位置。
結點換位就要調整指針,這裏爲了方便,可以用另一種辦法,先考慮如下問題,如何刪除單鏈表中指針正在指向的元素,不需要額外變量,只需要將當前結點的下一個結點的內容複製過來,然後刪除下一個結點即可。樹中我也這麼做。
刪除的流程如下
1.找到要刪除的結點
2.將其刪除,並且移動相關結點數據
3.查看樹是否保持平衡,不平衡則調整。
2.實現
#include<iostream>
#include <algorithm>
using namespace std;
struct TreeNode
{
TreeNode(){}
TreeNode(int n,int h):num(n),height(h) {}
int num = 0;
int height = 0;
TreeNode* left = nullptr;
TreeNode* right = nullptr;
TreeNode* parent = nullptr;
};
inline int getHeight(TreeNode* root)
{
return root ? root->height : 0;
}
//調整平衡後樹高度
void adjustHeight(TreeNode*T)
{
if (T->left != nullptr && T->right != nullptr)
T->height = max(T->left->height + 1, T->right->height + 1);
else if (T->left != nullptr)
T->height = T->left->height + 1;
else if (T->right != nullptr)
T->height = T->right->height + 1;
else
T->height = 1;
}
void condition1(TreeNode*& root)
{
/* A
/
B
/
C
*/
TreeNode* A = root;
TreeNode* B = root->left;
A->left = B->right;
B->parent = A->parent;
A->parent = B;
B->right = A;
root = B;
//重新計算平衡後,被調整結點的高度記錄
adjustHeight(A);
adjustHeight(B);
}
void condition2(TreeNode*& root)
{
/*A
\
B
\
C
*/
TreeNode* A = root;
TreeNode* B = root->right;
A->right = B->left;
B->parent = A->parent;
A->parent = B;
B->left = A;
root = B;
adjustHeight(A);
adjustHeight(B);
}
void condition3(TreeNode*& root)
{
/* A
/
B
\
C
*/
TreeNode* A = root;
TreeNode* B = root->left;
TreeNode* C = root->left->right;
A->left = C->right;
B->right = C->left;
C->left = B;
C->right = A;
C->parent = A->parent;
B->parent = C;
A->parent = A;
root = C;
adjustHeight(A);
adjustHeight(B);
adjustHeight(C);
}
void condition4(TreeNode*& root)
{
/* A
\
B
/
C
*/
TreeNode* A = root;
TreeNode* B = root->right;
TreeNode* C = root->right->left;
A->right = C->left;
B->left = C->right;
C->right = B;
C->left = A;
C->parent = A->parent;
B->parent = C;
A->parent = A;
root = C;
adjustHeight(A);
adjustHeight(B);
adjustHeight(C);
}
int addNode(TreeNode* &root,int num)
{
//如果節點的空
if (root == nullptr)
{
//創建節點
root = new TreeNode(num,1);
//返回樹高
return 1;
}
int lHeight = getHeight(root->left), rHeight = getHeight(root->right);
//左子樹
if (num < root->num)
{
//添加節點
lHeight = addNode(root->left, num);
//修改父節點
root->left->parent = root;
}
//右子樹
else
{
//添加節點
rHeight = addNode(root->right, num);
//修改父節點
root->right->parent = root;
}
//調整樹
if (abs(lHeight - rHeight) > 1)
{
if (lHeight> rHeight)
{
if (getHeight(root->left->left) > getHeight(root->left->right))
condition1(root);
else
condition3(root);
}
else
{
if (getHeight(root->right->right) > getHeight(root->right->left))
condition2(root);
else
condition4(root);
}
}
lHeight = getHeight(root->left);
rHeight = getHeight(root->right);
return root->height = max(lHeight , rHeight) + 1;
}
int moveNode(TreeNode*& root)
{
if (root == nullptr)
return 0;
TreeNode*& parent = root;
int lHeight = getHeight(root->left), rHeight = getHeight(root->right);
if (root->left != nullptr || root->right != nullptr)
{
//將右邊提上來,沒有右邊就提左邊
if (root->right != nullptr)
{
root->num = root->right->num;
rHeight = moveNode(root->right);
}
else if (root->left != nullptr)
{
root->num = root->left->num;
lHeight = moveNode(root->left);
}
return root->height = max(rHeight, lHeight) + 1;
}
else
{
//刪除parent
if (parent != nullptr)
{
delete parent;
parent = nullptr;
return 0;
}
}
}
int deleteNode(TreeNode*& root, int num)
{
if (root == nullptr)
return 0;
//刪除
TreeNode* parent = nullptr;
//獲取當前樹的高度
int lHeight = getHeight(root->left), rHeight = getHeight(root->right);
if (num > root->num)
rHeight = deleteNode(root->right,num);
else if (num < root->num)
lHeight = deleteNode(root->left, num);
else if (root->num == num)
moveNode(root);
//調整樹
if (abs(lHeight - rHeight) > 1)
{
if (lHeight > rHeight)
{
if (getHeight(root->left->left) > getHeight(root->left->right))
condition1(root);
else
condition3(root);
}
else
{
if (getHeight(root->right->right) > getHeight(root->right->left))
condition2(root);
else
condition4(root);
}
}
//重新計算樹的高度
if (root != nullptr)
{
lHeight = getHeight(root->left);
rHeight = getHeight(root->right);
return root->height = max(lHeight, rHeight) + 1;
}
else
{
lHeight = 0;
rHeight = 0;
return 0;
}
}
int main()
{
TreeNode* root = nullptr;
addNode(root,12);
addNode(root, 5);
addNode(root, 15);
addNode(root,3);
addNode(root, 8);
addNode(root, 9);
addNode(root, 6);
addNode(root, 20);
//addNode(root, 21);
deleteNode(root, 20);
deleteNode(root, 15);
deleteNode(root, 9);
deleteNode(root, 12);
deleteNode(root, 3);
return 0;
}