Thứ tự nút Nếu ta phân biệt thứ tự các nút con của cùng một nút thì cây... Duyệt cây cả các nút của cây mỗi nút đúng một lần Danh sách liệt kê các nút tên nút/ giá trị theo thứ tự đ
Trang 2Thuật ngữ cơ bản
Có một nút được phân biệt gọi là nút gốc (root)
Quan hệ cha - con (parenthood): xác định hệ thống cấu
trúc phân cấp trên các nút
Mỗi nút, trừ nút gốc, có duy nhất một nút cha
Một nút có thể có nhiều nút con hoặc không có nút con
Mối quan hệ cha con được biểu diễn theo qui ước nút cha
ở dòng trên nút con ở dòng dưới và được nối bởi một
đoạn thẳng
Trang 4thể xây dựng một cây mới bằng
cách cho nút n là cha của các
nút n1, , nk Cây mới này có nút
Trang 5Thuật ngữ
Đường đi: chuỗi các nút n1, , nk,
trong đó ni là nút cha của nút ni+1,
với i=1 k-1
Độ dài đường đi = số nút – 1
Đường đi từ một nút đến chính nó
có độ dài bằng không.
Nếu có đường đi từ nút a đến nút
b thì ta nói a là tiền bối (ancestor)
của b, còn b gọi là hậu duệ
(descendant) của nút a.
một nút vừa là tiền bối vừa là hậu
duệ của chính nó.
Tiền bối hoặc hậu duệ của một
nút khác với chính nó gọi là tiền
bối hoặc hậu duệ thực sự
Nút gốc không có tiền bối thực
Trang 6 Nút không có hậu duệ thực sự
gọi là nút lá (leaf)
Nút không phải là lá ta còn gọi
là nút trung gian (interior)
Cây con của một cây là một
nút cùng với tất cả các hậu duệ
của nó.
Chiều cao của một nút là độ
dài đường đi lớn nhất từ nút đó
Trang 7Thứ tự nút
Nếu ta phân biệt thứ tự các nút
con của cùng một nút thì cây
Trang 8Duyệt cây
cả các nút của cây mỗi nút đúng một lần
Danh sách liệt kê các nút (tên nút/ giá trị) theo thứ
tự đi qua gọi là danh sách duyệt cây
duyệt tiền tự (preorder),
duyệt trung tự (inorder),
duyệt hậu tự (posorder)
Trang 12Cây có nhãn và cây biểu thức
Ta thường lưu trữ kết hợp một
nhãn (label) hoặc còn gọi là một
giá trị (value) với một nút của
cây Như vậy nhãn của một nút
không phải là tên nút mà là giá trị
được lưu giữ tại nút đó
Trang 15cây biểu thức
Khi duyệt một cây biểu diễn
một biểu thức toán học và liệt
kê nhãn của các nút theo thứ tự
duyệt thì ta có:
Biểu thức dạng tiền tố hay biểu
thức tiền tố (prefix) tương ứng
với phép duyệt tiền tự của cây.
Biểu thức dạng trung tố hay biểu
thức trung tố (infix) tương ứng
với phép duyệt trung tự của cây
Biểu thức dạng hậu tố hay biểu
thức hậu tố (posfix) tương ứng
với phép duyệt hậu tự của cây.
*
b -
Biểu thức tiền tố - * a c b Biểu thức trung tố a * c – b Biểu thức hậu tố a c * b -
Trang 17KIỂU DỮ LIỆU TRỪU TƯỢNG
CÂY
T, nếu n là lá thì hàm cho giá trị NULL.
nếu n không có anh em ruột phải thì hàm cho giá trị NULL.
NULL.
là n được gán nhãn v và có i cây con T1, ,Ti
Nếu n= 0 thì thủ tục tạo cây mới chỉ gồm có 1 nút đơn độc là n có nhãn
v
false.
Trang 19Giải thuật duyệt tiền tự
Void PreOrder(Node n, Tree T){
Trang 20 A[i] = j với j là nút cha của nút i
Nếu i là nút gốc ta cho a[i] = Null
Nếu cây T là cây có nhãn:
Dùng thêm một mảng một chiều
thứ hai L chứa các nhãn: cho L[i]
= x với x là nhãn
Hoặc khai báo mảng a là mảng
của các struct có hai trường:
trường Parent giữ chỉ số nút cha;
trường Data giữ nhãn của nút
MaxNode giữ số nút hiện tại đang
có trên cây.
Hàm PARENT(n,T) tốn chỉ một hằng thời gian
Hàm đòi hỏi thông tin về các con không làm việc tốt
qui ước việc đặt tên cho các nút (đánh số thứ tự) như sau:
Đánh số theo thứ tự tăng dần bắt đầu tại nút gốc.
Nút cha được đánh số trước các nút con.
Các nút con cùng một nút cha được đánh số lần lượt từ trái sang phải
Trang 22G
J I
0
Trang 23Khai báo cấu trúc dữ liệu
#define MAXLENGTH /* chỉ số tối đa của mảng */
/* Lưu trữ cha của các nút trong cây theo nguyên tắc:
Cha của nút i sẽ lưu ở vị trí i trong mảng */
Trang 24Khởi tạo cây rỗng
void MAKENULL_TREE (Tree& T){
Xác định nút cha của nút trên cây
Node PARENT(Node n,Tree T){
if (EMPTY_TREE(T) || (n>T.MaxNode-1))
return NULL;
else return T.Parent[n];
}
Trang 25Xác định nhãn của nút trên cây
DataType LABEL_NODE(Node n,Tree T){
if (!EMPTY_TREE(T) && (n<=T.MaxNode-1))
Trang 26Hàm xác định con trái nhất của một nút
Node LEFTMOST_CHILD(Node n,Tree T){
Trang 27Hàm xác định anh em ruột phải của một nút
Node RIGHT_SIBLING(Node n,Tree T){
Trang 31Ví dụ
phím như tổng số nút trên cây; ứng với từng nút thì phải nhập nhãn của nút, cha của một nút Hiển thị
danh sách duyệt cây theo các phương pháp duyệt tiền
tự, trung tự, hậu tự của cây vừa nhập.
chúng ta cần phải thiết kế một số chương trình con
sau:
Nhập dữ liệu cho cây từ bàn phím READTREE(T)
Trang 32} while ((T.MaxNode<1) || (T.MaxNode>MAXLENGTH));
printf("Nhap nhan cua nut goc ");
Trang 34 Nhap du lieu cho cay tong quat
Cay co bao nhieu nut?10
Nhap nhan cua nut goc A
Nhap cha cua nut 1 0
Nhap nhan cua nut 1 B
Nhap cha cua nut 2 0
Nhap nhan cua nut 2 C
Nhap cha cua nut 3 1
Nhap nhan cua nut 3 D
Nhap cha cua nut 4 1
Nhap nhan cua nut 4 E
Nhap cha cua nut 5 4
Nhap nhan cua nut 5 F
Nhap cha cua nut 6 4
Nhap nhan cua nut 6 G
Nhap cha cua nut 7 4
Nhap nhan cua nut 7 H
Nhap cha cua nut 8 2
Nhap nhan cua nut 8 I
Nhap cha cua nut 9 2
Nhap nhan cua nut 9 J
Danh sach duyet tien tu cua cay vua nhap la
Trang 35A B C D E F G J H I
8
Trang 36Biểu diễn theo con trái nhất và anh em
ruột phải
Các cấu trúc đã dùng để mô tả cây ở trên có một số nhược
điểm: không trợ giúp phép tạo một cây lớn từ các cây nhỏ hơn, nghĩa là ta khó có thể cài đặt phép toán CREATEi
Chẳng hạn CREATE2(v,T1,T2) chúng ta phải chép hai cây
T1, T2 vào mảng thứ ba rồi thêm một nút n có nhãn v và hai nút con là gốc của T1 và T2
Ta thay thế mảng các Header bằng mảng CELLSPACE chứa các bản ghi (struct) có ba trường Data, Leftmost_Child,
Right_Sibling
Data giữ nhãn của nút,
Leftmost_Child là một con nháy chỉ đến con trái nhất của nút,
Right_Sibling là con nháy chỉ đến nút anh ruột phải
Hơn nữa mảng này giữ tất cả các nút của tất cả các cây.
Trang 37Available
Trang 40Hàm CREATE2 tạo cây mới từ hai cây con
int CREATE2(DataType v, int T1, int T2){
// T1, T2 là hai con nháy trỏ tới hai nút gốc của hai cây con
// Hàm trả ra con nháy trỏ tới nút gốc mới
//lấy ô đầu danh sách available để tạo một nút mới trên cây
int temp=Available ; //available như là một biến toàn cục
Trang 44Cài đặt cây bằng con trỏ
Các khai báo như sau
typedef Cell* Node;
typedef Node Tree;
data
Trang 49//if (left!=NULL) left->Parent = n;
//if (right!=NULL) right->Parent=NULL;
return n;
}
Trang 50CÂY NHỊ PHÂN (BINARY TREES)
Cây nhị phân là cây rỗng
hoặc là cây mà mỗi nút có tối
đa hai nút con
Các nút con của cây được
phân biệt thứ tự rõ ràng:
Con trái
Con phải
Ta qui ước vẽ nút con trái
bên trái nút cha và nút con
phải bên phải nút cha, mỗi
nút con được nối với nút cha
của nó bởi một đoạn thẳng
Trang 51Duyệt cây
Duyệt tiền tự
(Node-Left-Right): duyệt nút gốc, duyệt
tiền tự con trái rồi duyệt tiền
tự con phải.
Duyệt trung tự
(Left-Node-Right): duyệt trung tự con
trái rồi đến nút gốc sau đó là
duyệt trung tự con phải.
Duyệt hậu tự
(Left-Right-Node): duyệt hậu tự con trái
rồi duyệt hậu tự con phải sau
đó là nút gốc.
nút
Trang 52Các danh sách duyệt cây
Trang 53Nút cha
Trang 54Cài đặt cây nhị phân
typedef int DataType;
typedef struct Node{
Trang 55Xác định con trái của một nút
Tree LEFTCHILD(Tree n){ //n co
kieu Node*, tuc la Tree
if (n!=NULL) return n->left;
else return NULL;
}
Xác định con phải của một nút
Tree RIGHTCHILD(Tree n){
if (n!=NULL) return n->right;
else return NULL;
if(EMPTY_TREE(T)) return 0;
else return 1 +NB_NODES(LEFTCHILD(T)) + NB_NODES(RIGHTCHILD(T)); }
Tạo cây mới từ hai cây có sẵn Tree Create2(DataType v,Tree l,Tree r){
Tree N;
N=(Node*)malloc(sizeof(Node)); N->Data=v;
N->left=l;
N->right=r;
return N;
}
Trang 56int NB_LEAVES(Tree T){
if(EMPTY_TREE(T)) return 0;
else if ((T->left==NULL) && (T->right==NULL)) return 1;else return NB_LEAVES(T->left)+ NB_LEAVES(T->right);}
56
Trang 57Bài tập
hướng dẫn
Tạo cây như hình vẽ trên bảng
Thực hiện duyệt: tiền tự, trung
6 2 1 3 5 4Duyet LRN
6 1 2 5 4 3
Trang 58so nut cua cay : 6
tong cua tat ca cac nut cua cay : 21
so nut la cua cay : 3
chieu cao cua cay : 2
So nut cua cay la 6 Duyet NLR
3 2 6 1 4 5 Duyet LNR
6 2 1 3 5 4 Duyet LRN
6 1 2 5 4 3
Process exited with return value 0 Press any key to continue
Trang 61int Height (Tree T){
61
Trang 62Tạo cây mới từ hai cây có sẵn
Tree Create2(DataType v,Tree l,Tree r){
Trang 63Thủ tục duyệt trung tự
void InOrder(Tree T){
if (T!=NULL) {
InOrder(LEFTCHILD(T)); printf("%c ",T->Data);
}
}
Trang 65Tree T1 = Create2('D', NULL, NULL);
Tree T2 = Create2('E', NULL, NULL);
Tree T3 = Create2('F', NULL, NULL);
Trang 66Cây tìm kiếm nhị phân
binary search tree
Cây tìm kiếm nhị phân (TKNP) là
cây nhị phân mà khoá tại mỗi nút
lớn hơn khoá của tất cả các nút
thuộc cây con bên trái và nhỏ hơn
khoá của tất cả các nút thuộc cây
con bên phải
typedef <kiểu dữ liệu của khoá> KeyType;
typedef struct Node{
15
35
37
Trang 6735
37
Tree Search (KeyType x,Tree Root){
if (Root==NULL) return NULL;
else if(Root->Key==x)
return Root;
else if (Root->Key<x)
return Search(x,Root->Right); else
return Search(x,Root->Left); }
Th i gian tìm ki m 1 nút : O(h), h là chi u cao câyờ ế ề
Trang 68Thêm một khoá vào cây TKNP
void InsertNode(KeyType x,Tree& Root ){
/* thêm nút mới chứa khoá x */
15
35
37
Trang 6915
Trang 70else if (x > Root->Key) DeleteNode(x,Root->Right);
else if ((Root->Left==NULL) && (Root->Right==NULL)) Root=NULL;
else
if (Root->Left == NULL) Root = Root->Right;
else if (Root->Right==NULL) Root = Root->Left;
else Root->Key = DeleteMin(Root->Right);
}
Trang 71TỔNG KẾT CHƯƠNG
Một số khái niệm cơ bản về cây tổng quát,
Cây nhị phân,
Cách biểu diễn biểu thức toán học,
Các biểu thức duyệt cây
Cài đặt cây bằng mảng, con trỏ, danh sách các con, con trái nhất, anh
em ruột phải
Cây tìm kiếm nhị phân như một ứng dụng cây nhị phân trong tổ chức
dữ liệu phục vụ cho tìm kiếm nhanh
Bài tập chương
Thực hành: 2 buổi