You are on page 1of 9

Cây nhị phân trong C++_Tóm tắt

Contents
Cây nhị phân trong C++...........................................................................................................................1
Cây nhị phân: cài đặt node, node* = tree, phương thức tạo tree, duyệt tree theo 3 cách
và hủy tree............................................................................................................................................3
Cấu trúc node....................................................................................................................................3
Cấu trúc cây (Optional)....................................................................................................................4
Duyệt cây nhị phân...........................................................................................................................4
Hủy cây nhị phân..............................................................................................................................6
Thêm node.........................................................................................................................................7
Tìm một phần tử trong cây nhị phân tìm kiếm..............................................................................7
Hủy node trên cây nhị phân tìm kiếm.............................................................................................8
Source code.......................................................................................................................................10
Cây nhị phân: cài đặt node, node* = tree,
phương thức tạo tree, duyệt tree theo 3 cách và
hủy tree

Cấu trúc node


struct node
{
int data;
node *left;
node *right;
};
Typedef Node node* Node;

Node CreateNode(int init)


{
Node p = new node;
p->data = init;
p->left = NULL;
p->right = NULL;
return p;
}

Cấu trúc cây


typedef Node Tree;

Tree myTree;
void CreateTree(Tree &root)
{
root = NULL;
}

// Khi tạo cây


CreateTree(myTree);

Duyệt cây nhị phân


Có 3 cách duyệt cây nhị phân:
Ví dụ:

Cây nhị phân

 Duyệt tiền tự (NLR): A B D H I E K L C F M N G O P


 Duyệt trung tự (LNR): H D I B K E L A M F N C O G P
 Duyệt hậu tự (LRN): H I D K L E B M N F O P G C A

Duyệt tiền tự (PreOrder):


void NLR(Tree root)
{
if (root)
{
// Xử lý node gốc (root)
NLR(root->left);
NLR(root->right);
}
}

Duyệt trung tự (InOrder):Thứ tự tăng dần


void LNR(Tree root)
{
if (root)
{
LNR(root->left);
// Xử lý node gốc (root)
LNR(root->right);
}
}

Duyệt hậu tự (PostOrder)


void LRN(Tree root)
{
if (root)
{
LRN(root->left);
LRN(root->right);
// Xử lý node gốc (root)
}
}

Hủy cây nhị phân


Bắt buộc dùng hậu tự:

void DestroyTree(Tree &root)


{
if (root)
{
DestroyTree(root->left);
DestroyTree(root->right);
delete root;
}
}

Cây nhị phân tìm kiếm


Thêm node
void AddNode(Tree& root, Node* node)
{
if (root)
{
if (root->data == node->data) // Nếu bị trùng giá trị thì không thêm
return;
if (node->data < root->data) // Thêm vào cây con bên trái (nhỏ hơn node hiện tại)
AddNode(root->left, node);
else
AddNode(root->right, node); // Thêm vào cây con bên phải (lớn hơn node hiện tại)
}
else
{
root = node; // Đã tìm thấy vị trí thích hợp, thêm node vào
}
}

Tìm một phần tử trong cây nhị phân tìm kiếm


Node *FindNode(Tree root, int x)
{
if (root)
{
if (root->data == x) // Tìm thấy
return root;
if (x < root->data)
return FindNode(root->left, x); // Tìm cây con bên trái
return FindNode(root->right, x); // Tìm cây con bên phải
}
return NULL; // Không tìm thấy
}

Hủy node trên cây nhị phân tìm kiếm

Trường hợp 1
// node p là node cần thay thế, tree là cây đang xét (cây bên phải)
void FindAndReplace1(Tree &p, Tree &tree)
{
if (tree->left) // check thử nó có con trái hay không, khi false thì dừng lại tại điểm nhỏ nhất (node
lá trái nhất nên không có con)
FindAndReplace1(p, tree->left); // tiếp tục tìm
else // tree là node trái nhất
{
p->data = tree->data; // copy data
p = tree; // trỏ node p vào node tree sẽ làm thế mạng bị xóa
tree = tree->right; // node trái không còn tuy nhiên node phải có thể còn nên ta phải nối chúng
lại
}
}

Trường hợp 2
// node p là node cần thay thế, tree là cây đang xét (cây bên trái)
void FindAndReplace2(Tree &p, Tree &tree)
{
if (tree->right) // chưa phải lớn nhất (phải nhất)
FindAndReplace2(p, tree->right); // tiếp tục tìm
else // tree là node trái nhất
{
p->data = tree->data; // copy data
p = tree; // trỏ node p vào node tree sẽ làm thế mạng bị xóa
tree = tree->left; // node phải không còn tuy nhiên node trái có thể còn nên ta phải nối chúng lại
}
}
Full code xóa một node ra khỏi cây nhị phân:

void DeleteNode(Tree& root, int x)


{
if (root) //khác null
{
if (x > root->data)
DeleteNode(root->right, x);
else if (x < root->data)
DeleteNode(root->left, x);
else // node hiện tại (root) là node cần xóa
{
Node *p = root; // lưu lại node cần xóa tránh bị ghi đè
if (!root->left)
root = root->right; // trường hợp 1
else if (!root->right)
root = root->left; // trường hợp 2
else
FindAndReplace1(p, root->right); // cách 1
// FindAndReplace2(p, root->left); // cách 2
delete p; // xóa node
}
}
else
{
cout << "Not found!\n"; // Không tìm thấy phần tử cần xóa
}
}

Source code
struct Node
{
int data;
Node *left;
Node *right;
};

typedef Node* Tree;

Node *CreateNode(int init)


{
Node *p = new Node;
p->data = init;
p->left = NULL;
p->right = NULL;
return p;
}

void CreateTree(Tree &root)


{
root = NULL;
}

void DestroyTree(Tree &root)


{
if (root)
{
DestroyTree(root->left);
DestroyTree(root->right);
delete root;
}
}

void AddNode(Tree &root, Node *node)


{
if (root)
{
if (root->data == node->data)
return;
if (node->data < root->data)
AddNode(root->left, node);
else
AddNode(root->right, node);
}
else
{
root = node;
}
}
void FindAndReplace1(Tree &p, Tree &tree)
{
if (tree->left)
FindAndReplace1(p, tree->left);
else
{
p->data = tree->data;
p = tree;
tree = tree->right;
}
}

void FindAndReplace2(Tree &p, Tree &tree)


{
if (tree->right)
FindAndReplace2(p, tree->right);
else
{
p->data = tree->data;
p = tree;
tree = tree->left;
}
}

void DeleteNode(Tree &root, int x)


{
if (root)
{
if (x > root->data) //nếu x lớn hơn giá trị node gốc
DeleteNode(root->right, x); //tra cây con bên phải, làm liên tục cho đến khi gặp else
else if (x < root->data) //nếu x bé hơn giá trị node gốc
DeleteNode(root->left, x); //tra cây con bên trái, làm liên tục cho đến khi gặp else
else //tìm ra được vị trí của x
{
Node *p = root; //tạo một node = node gốc hiện tại (vị trí của x) nay gọi là node x
if (!root->left) //trường hợp 1: node x không có cây con trái
root = root->right; //vì nó không có con trái, trỏ thẳng vào cây con phải, coi như node x đã
biến mất
else if (!root->right) //trường hợp 2: node x không có cây con phải
root = root->left; //vì nó không có con phải, trỏ thẳng vào cây con trái, coi như node x đã
biến mất
else //trường hợp 3: node x có cả con trái và con phải
FindAndReplace1(p, root->right); //từ node x đó, ta tra ra node trái nhất trong cây con phải
của node x đó
//FindAndReplace2(p, root->left); //từ node x đó, ta tra ra node phải nhất trong cây con trái
của node x đó
delete p;
}
}
else
{
cout << "Not found!\n";
}
}

You might also like