#include <iostream>
using namespace std;
// Định nghĩa cấu trúc nút cho cây BST và DLL
struct Node
{
int val; // Giá trị của nút
Node* left; // Con trỏ trái (trong BST)
Node* right; // Con trỏ phải (trong BST)
Node(int _val)
{
val = _val;
left = nullptr;
right = nullptr;
}
};
// Hàm để chèn nút vào BST
Node* insert(Node* root, int val) {
if (root == nullptr) {
return new Node(val); // Nếu cây rỗng, tạo nút mới
}
if (val < root->val) {
root->left = insert(root->left, val); // Chèn vào cây con bên trái
} else {
root->right = insert(root->right, val); // Chèn vào cây con bên phải
}
return root; // Trả về gốc của cây
}
void printDLL(Node* head) {
Node* current = head;
while (current != nullptr) {
cout << current->val << " <=> "; // In giá trị của nút hiện tại
current = current->right; // Di chuyển đến nút tiếp theo
}
cout << endl;
}
void printBST(Node* node)
{
if (node == nullptr)
return;
cout << node->val << " ";
printBST(node->left);
printBST(node->right);
}
//============================//
// Chuyển đổi BST sang DLL
Node* prevDLL = nullptr; // Nút trước đó trong quá trình chuyển đổi BST sang DLL
Node* headDLL = nullptr; // Đầu của DLL được tạo từ BST
// Hàm đệ quy để duyệt cây BST theo thứ tự (in-order) và xây dựng DLL
void dfs(Node* root) {
if (root == nullptr) return;
// Nếu nút hiện tại là null - là gốc của cây, kết thúc đệ quy
dfs(root->left); // Duyệt cây con bên trái trước
// Xử lý nút hiện tại
if (prevDLL == nullptr) headDLL = root;
// Nếu prevDLL là null thì nút hiện tại là đầu của DLL
else {
prevDLL->right = root; // Liên kết nút trước với nút hiện tại (trong DLL)
root->left = prevDLL; // Liên kết nút hiện tại với nút trước (trong DLL)
}
prevDLL = root; // Cập nhật nút trước là nút hiện tại
dfs(root->right); // Duyệt cây con bên phải
}
// Hàm chính để chuyển đổi BST thành Doubly Linked List (DLL)
Node* BSTtoDLL(Node* rootBST)
{
if (rootBST == nullptr) return nullptr; // Nếu BST rỗng, trả về null
prevDLL = nullptr;
headDLL = nullptr;
dfs(rootBST); // Gọi hàm dfs để xây dựng DLL
return headDLL; // Trả về đầu của DLL
}
//============================//
// Chuyển đổi DLL sang BST
Node* Helper_DLLtoBST(Node*& headRef, int n) {
if (n <= 0) return nullptr; // Không còn nút để xử lý
Node* T_left = Helper_DLLtoBST(headRef, n / 2); // Xây dựng cây con bên trái
Node* root = headRef; // Nút hiện tại trong DLL sẽ là gốc của cây con hiện tại
if (headRef != nullptr) headRef = headRef->right; // Di chuyển con trỏ headRef đến nút tiếp theo trong DLL
root->left = T_left; // Gán cây con bên trái cho nút gốc
root->right = Helper_DLLtoBST(headRef, n - (n / 2) - 1); // Xây dựng cây con bên phải
return root; // Trả về gốc của cây con hiện tại
}
// Hàm để đếm số lượng nút trong DLL
int countNodesDLL(Node* head)
{
int count = 0;
Node* current = head;
while (current != nullptr)
{
count++; // Tăng bộ đếm cho mỗi nút
current = current->right; // Di chuyển đến nút tiếp theo
}
return count; // Trả về tổng số nút
}
// Hàm chính để chuyển đổi Doubly Linked List (DLL) thành BST cân bằng
Node* DLLtoBST(Node* head)
{
if (!head) return nullptr; // Nếu DLL rỗng, trả về null
int n = countNodesDLL(head); // Đếm số lượng nút trong DLL
Node* currentHead = head; // Tạo một bản sao của head để truyền vào hàm đệ quy
return Helper_DLLtoBST(currentHead, n); // Gọi hàm đệ quy để xây dựng BST
}
//=========================
int main() {
Node* rootBST = nullptr;
rootBST = insert(rootBST, 4);
rootBST = insert(rootBST, 2);
rootBST = insert(rootBST, 5);
rootBST = insert(rootBST, 1);
rootBST = insert(rootBST, 3);
rootBST = insert(rootBST, 6);
rootBST = insert(rootBST, 7);
cout << "BST (Before): ";
printBST(rootBST);
cout << endl;
Node* headDLL = BSTtoDLL(rootBST);
cout << "Doubly Linked List: ";
printDLL(headDLL);
Node* rootFromDLL = DLLtoBST(headDLL);
cout << "BST (After): ";
printBST(rootFromDLL);
cout << endl;
return 0;
}