การลบทำได้โดยแทนที่โหมดที่ถูกลบด้วยโหนดด้านล่างและขวาสุด
ให้เรากำหนดโครงสร้างที่จะเป็นตัวแทนของโหนดต้นไม้ที่มีข้อมูลและโหนดลูกของโหนดซ้ายและขวา หากนี่เป็นโหนดแรกที่สร้างขึ้น แสดงว่าเป็นโหนดรูท มิฉะนั้นจะเป็นโหนดย่อย
struct Node {
int data;
struct Node *leftChild, *rightChild;
}; ต่อไป เราสร้างฟังก์ชัน newNode(int data) ที่ใช้ค่า int และกำหนดให้กับสมาชิกข้อมูลของโหนด ฟังก์ชันจะส่งกลับตัวชี้ไปยังโหนดโครงสร้างที่สร้างขึ้น นอกจากนี้ ลูกซ้ายและขวาของโหนดที่สร้างขึ้นใหม่จะถูกตั้งค่าเป็นโมฆะ
struct Node* newNode(int data){
struct Node* newNode = new Node;
newNode->data = data;
newNode->leftChild = newNode->rightChild = NULL;
return (newNode);
} ฟังก์ชันการลบ (struct Node* root, int data) ใช้สำหรับการลบโหนดด้วยค่าข้อมูลที่กำหนด ต้องใช้โหนดรากและค่าข้อมูลเพื่อค้นหาและลบ หากไม่มีโหนดย่อยและค่าข้อมูลเท่ากับค่าข้อมูลของรูท ระบบจะคืนค่า null มิฉะนั้นระบบจะส่งคืนโหนดรูท
Node* deletion(struct Node* root, int data){
if (root == NULL)
return NULL;
if (root->leftChild == NULL && root->rightChild == NULL) {
if (root->data == data)
return NULL;
else
return root;
} ตอนนี้เราสร้างคิวประเภท struct Node * และตั้งชื่อว่า q และผลักโหนดรูทไปที่ q นอกจากนี้เรายังประกาศ temp และ data_node ซึ่งเป็นตัวชี้ไปยังโหนดและตั้งค่า data_node เป็น NULL
struct Node* temp; struct Node* data_node = NULL;
ต่อไป เราดำเนินการข้ามระดับเพื่อค้นหาโหนดที่ลึกที่สุด วนรอบในขณะที่ดำเนินการจนกว่าคิว q ไม่ว่างเปล่า คิวเป็นโครงสร้างข้อมูล FIFO ดังนั้นองค์ประกอบสุดท้ายในคิวจะเป็นโหนดที่ลึกที่สุดด้านขวาสุด เนื่องจากเรากำลังดำเนินการตามระดับการข้ามผ่าน อุณหภูมิจะชี้ไปที่ด้านหน้าของคิวเสมอและองค์ประกอบจะโผล่ขึ้นมาจากด้านหน้าเมื่อเราไปต่อ
while (!q.empty()) {
temp = q.front();
q.pop();
if (temp->data == data)
data_node = temp;
if (temp->leftChild)
q.push(temp->leftChild);
if (temp->rightChild)
q.push(temp->rightChild);
} ต่อไปถ้า data_node ไม่ใช่ NULL เราจะเก็บโหนดที่จะลบข้อมูลใน x และลบ temp ซึ่งเป็นโหนดที่ลึกที่สุด จากนั้น ค่า data_node จะถูกแทนที่ด้วยค่าโหนดที่ลึกที่สุด และโหนดที่ลึกที่สุดจะถูกลบออก โหนดใหม่ถูกส่งกลับจากฟังก์ชันหลังจากการลบและแทนที่
if (data_node != NULL) {
int x = temp->data;
deleteDeepest(root, temp);
data_node->data = x;
} ฟังก์ชัน deleteDeepest(struct Node* root,struct Node* deepestNode) จะตรวจสอบว่าโหนดที่ส่งผ่านนั้นเป็นโหนดที่ลึกที่สุดจริง ๆ หรือเป็นโหนดย่อยที่ถูกต้องหรือซ้ายเป็นโหนดที่ลึกที่สุด ซึ่งในกรณีนี้จะตั้งค่าย่อยเป็น null ก่อนลบพาเรนต์ซึ่งเป็น โหนดที่ลึกที่สุด
void deleteDeepest(struct Node* root,
struct Node* deepestNode){
queue<struct Node*> q;
q.push(root);
struct Node* temp;
while (!q.empty()) {
temp = q.front();
q.pop();
if (temp == deepestNode) {
temp = NULL;
delete (deepestNode);
return;
}
if (temp->rightChild) {
if (temp->rightChild == deepestNode) {
temp->rightChild = NULL;
delete (deepestNode);
return;
}
else
q.push(temp->rightChild);
}
if (temp->leftChild) {
if (temp->leftChild == deepestNode) {
temp->leftChild = NULL;
delete (deepestNode);
return;
}
else
q.push(temp->leftChild);
}
}
} ตัวอย่าง
ให้เราดูการใช้งานต่อไปนี้เพื่อดูการลบในไบนารีทรี -
#include <iostream>
#include <queue>
using namespace std;
struct Node {
int data;
struct Node *leftChild, *rightChild;
};
struct Node* NewNode(int data){
struct Node* temp = new Node;
temp->data = data;
temp->leftChild = temp->rightChild = NULL;
return temp;
};
void inorder(struct Node* temp){
if (!temp)
return;
inorder(temp->leftChild);
cout << temp->data << " ";
inorder(temp->rightChild);
}
void deleteDeepest(struct Node* root,
struct Node* deepestNode){
queue<struct Node*> q;
q.push(root);
struct Node* temp;
while (!q.empty()) {
temp = q.front();
q.pop();
if (temp == deepestNode) {
temp = NULL;
delete (deepestNode);
return;
}
if (temp->rightChild) {
if (temp->rightChild == deepestNode) {
temp->rightChild = NULL;
delete (deepestNode);
return;
}
else
q.push(temp->rightChild);
}
if (temp->leftChild) {
if (temp->leftChild == deepestNode) {
temp->leftChild = NULL;
delete (deepestNode);
return;
}
else
q.push(temp->leftChild);
}
}
}
Node* deletion(struct Node* root, int data){
if (root == NULL)
return NULL;
if (root->leftChild == NULL && root->rightChild == NULL) {
if (root->data == data)
return NULL;
else
return root;
}
queue<struct Node*> q;
q.push(root);
struct Node* temp;
struct Node* data_node = NULL;
while (!q.empty()) {
temp = q.front();
q.pop();
if (temp->data == data)
data_node = temp;
if (temp->leftChild)
q.push(temp->leftChild);
if (temp->rightChild)
q.push(temp->rightChild);
}
if (data_node != NULL) {
int x = temp->data;
deleteDeepest(root,temp);
data_node->data = x;
}
return root;
}
// Driver code
int main(){
struct Node* root = NewNode(12);
root->leftChild = NewNode(13);
root->leftChild->leftChild = NewNode(9);
root->leftChild->rightChild = NewNode(14);
root->rightChild = NewNode(11);
root->rightChild->leftChild = NewNode(17);
root->rightChild->rightChild = NewNode(10);
cout << "Inorder traversal before deletion : ";
inorder(root);
int data = 13;
root = deletion(root, data);
cout <<endl<< "Inorder traversal after deletion : ";
inorder(root);
return 0;
} ผลลัพธ์
รหัสข้างต้นจะสร้างผลลัพธ์ต่อไปนี้ -
Inorder traversal before deletion : 9 13 14 12 17 11 10 Inorder traversal after deletion : 9 10 14 12 17 11