CHƯƠNG 4- TÌM KIẾM
Trang 2CHƯƠNG 4 TÌM KIẾM
4.1 Các phương pháp tìm kiếm trong danh sách
4.1.1 Tìm kiếm tuyến tính
4.1.2 Tìm kiếm nhị phân
4.1.1 Tìm kiếm nội suy
4.2 Cây nhị phân tìm kiếm
4.2.1 Định nghĩa
4.2.2 Các phép toán
Trang 34.1 Các phương pháp tìm kiếm
trong danh sách
Mô hình chung của bài toán tìm kiếm: Có một tập n đối tượng Mỗi đối tượng có nhiều thuộc tính, được thể hiện bằng một kiểu bản ghi gồm nhiều
trường Trong đó có 1 trường mà giá trị của nó đặc trưng cho đối tượng, cho phép xác định hoàn toàn đối tượng, thường gọi là khóa
Bài toán tìm kiếm: Có một tập các đối tượng và cho trước một đối tượng x Cần tìm xem x có mặt trong tập hợp đã cho hay không?
Trang 44.1 Các phương pháp tìm kiếm
trong danh sách
Mô hình toán học của bài toán tìm kiếm:
Có tập hợp n giá trị khóa k1, k2, kn Cho giá trị khóa x Tìm xem x có tồn tại ki=x?
Công việc tìm kiếm sẽ hoàn thành khi:
– Tìm được 1 bản ghi có giá trị khóa =x, lúc đó phép
tìm kiếm được thành công successful.
– Không tìm thấy bản ghi nào có khóa bằng x, gọi là
tìm kiếm không thành công unsuccessful Lúc này có thể xuất hiện yêu cầu bổ sung giá trị x vào tập hợp, gọi là tìm kiếm có bổ sung.
Trang 62 // Tìm khóa trong dãy
while (k[i] !=x) do i++;
3 // Tìm thấy hay không
If (i==n+1) return 0 //không tìm thấy
else return i;
SEQUEN-SEARCH(k,n,x)
1 //Khởi đầu
i=1; k[i+1]=x
2 // Tìm khóa trong dãy
while (k[i] !=x) do i++;
3 // Tìm thấy hay không
If (i==n+1) return 0 //không tìm thấy
else return i;
Trang 74.1.1 Tìm kiếm tuần tự (sequential
searching)
Giải thuật 2 (giải thuật đệ quy-tìm trong
danh sách liên kết):
Node *timdequy(struct node *first, element_type e)
Trang 84.1.1 Tìm kiếm tuần tự (sequential
searching)
Đánh giá giải thuật:
Trường hợp tốt nhất: Tmin = 1;
Trường hợp xấu nhất: Tmax = O(n);
Trung bình Ttb= O(n)
Trang 9– Dãy khóa đã được sắp xếp theo thứ tự (tăng dần
hoặc giảm dần).
– Giả sử dãy khóa đang xét là kl và kr thì khóa ở giữa
dãy sẽ là ki với i = (l+r)/2.
– Tìm kiếm sẽ kết thúc nếu x=ki Ngược lại, nếu x<ki,
phép tìm kiếm sẽ được thực hiện tiếp với kl, ki-1, nếu x>ki, phép tìm kiếm sẽ được thực hiện tiếp với ki+1 với kr.
– Quá trình tìm kiếm sẽ dừng khi tìm thấy khóa hoặc
dãy đang xét trở nên rỗng.
Trang 10else return m;
}b3 return 0; // tìm không thấy
else return m;
}b3 return 0; // tìm không thấy
Trang 11then loc=0// loc chứa chỉ số tương ứng của
//khóa cần tìm
then loc=0// loc chứa chỉ số tương ứng của
//khóa cần tìm
Trang 124.1.2 Tìm kiếm nhị phân (Binary
Serching)
Đánh giá giải thuật:
– Trường hợp tốt nhất Tmin =1, tìm được ngay
lần đầu tiên
– Trường hợp xấu nhất Tmax = k+w[n/2k)
– Chứng minh được Ttb = O(log2n).
Trong tất cả các giải thuật tìm kiếm, tìm kiếm nhị phân là nhanh nhất, nhưng nó có nhược điểm là dãy phải được sắp xếp.
Trang 13Bài tập về nhà
B1 Viết chương trình thực hiện các việc sau:
a Nhập các giá trị nguyên dương từ bàn phím
(tổ chức theo kiểu danh sách liên kết)
b In ra màn hình dãy số đã nhập
c Nhập một giá trị X từ bàn phím, kiểm tra X
có trong danh sách hay không Nếu có thì trả về vị trí của X, nếu không chèn X vào vị trí cuối của danh sách.(Viết cả 2 giải thuật Tìm kiếm tuần tự và tìm kiếm nhị phân)
Trang 144.2 Cây nhị phân tìm kiếm
Việc tổ chức tập hợp khóa theo cấu trúc
danh sách thì phép tìm kiếm nói chung là chi phí cao, nếu khóa đã sắp xếp thì phép tìm kiếm nhị phân hiệu quả hơn nhưng bất tiện trong việc thêm, bớt phần tử.
Cấu trúc cây nhị phân tìm kiếm được xây
dựng để khắc phục các nhược điểm trên.
Trang 154.2.1 Định nghĩa
Định nghĩa: Cây nhị phân tìm kiếm là cây nhị phân mà tại mỗi nút có một giá trị khóa thuộc kiểu dữ liệu có thứ tự nào đó, đồng thời thỏa mãn điều kiện sau:
– Mọi khóa thuộc cây con trái đều nhỏ hơn khóa ở nút cha
– Mọi khóa thuộc cây con phải đều lớn hơn
khóa ở nút cha
Theo định nghĩa, bất kỳ cây con nào của cây nhị phân tìm kiếm đều là cây tìm kiếm.
Trang 174.2.1 Định nghĩa
Bài tập tại lớp
– Vẽ 4 cây nhị phân tìm kiếm với các giá trị sau:
3, 4, 6, 8, 9, 10, 14, 15, 17
– Vẽ cây nhị phân tìm kiếm cân đối cho các giá trị trên với số nút rỗng là ít nhất
Trang 184.2.2 Các phép toán
Phép tìm kiếm
Phép chèn thêm một nút
Phép gỡ loại bỏ một nút
Trang 194.2.2.1 Phép tìm kiếm
Mô tả các bước:
Bắt đầu từ gốc của cây, gọi nút đang xét là V.
Nếu V rỗng, kết thúc và tìm không thấy.
Ngược lại, so sánh x với khóa của nút hiện tại V:
– Nếu x< khóa của V, lặp lại bước tìm kiếm với cây con
Trang 204.2.2.1 Phép tìm kiếm
int timdequy(int x,NODE *root)
Trang 214.2.2.1 Phép tìm kiếm
int tim(int x,NODE *root)
{
int timthay =0;
while ((root !=NULL) && (!timthay))
if (root ->element==x) timthay=1;
else if (x < root->element) root= root->left;
else root= root->right;
while ((root !=NULL) && (!timthay))
if (root ->element==x) timthay=1;
else if (x < root->element) root= root->left;
else root= root->right;
return timthay;
}
Thủ tục không đêê quy
Trang 224.2.2.2 Phép thêm một nút
Đặt vấn đề: Tiến hành thêm một nút mới vào cây nhị phân tìm kiếm sao cho các khóa trên cây vẫn giữ đúng thứ tự
Ý tưởng: Thủ tục thêm một nút bắt đầu từ
việc tìm kiếm, nếu tìm thấy thì kết thúc, nếu
không tìm thấy thì tiến hành ở nhánh con bên trái hoặc bên phải để đảm bảo tính chất của
cây nhị phân tìm kiếm
Trang 234.2.2.2 Phép thêm một nút
Ví dụ: Thêm
các nút 5, 2, 4,
6, 1, 7, 3 vào
một cây rỗng
theo đúng thứ
tự
Qua từng bước
thêm, ta có cây
Trang 244.2.2.2 Phép thêm một nút
void chen(int e, NODE **root)
Trang 254.2.2.2 Phép thêm một nút
if (tam->element < (*root)->element)
if ((*root)->left) chen(e, &(*root)->left);
else (*root)->left = tam;
else
if(tam->element > (*root)->element)
if ((*root)->right) chen(e, &(*root)->right);
else (*root)->right = tam;
else cout <<"trung";}
if (tam->element < (*root)->element)
if ((*root)->left) chen(e, &(*root)->left);
else (*root)->left = tam;
else
if(tam->element > (*root)->element)
if ((*root)->right) chen(e, &(*root)->right);
else (*root)->right = tam;
else cout <<"trung";}
Trang 264.2.2.3 Phép xóa một nút
Đặt vấn đề: Sau khi xóa xong một nút,
thay đổi cây còn lại vẫn đảm bảo là cây nhị phân tìm kiếm.
Trang 27– Xảy ra 2 trường hợp:
• V là nút lá: chỉ cần gỡ bỏ V bằng cách thay nút bên
trái hoặc bên phải của nút cha V = Null
• V là nút một cành: gỡ bỏ V bằng cách sửa lại mối
nối (left hoặc right) ở nút cha của V trỏ xuống nút cháu, cây còn lại vẫn là nhị phân tìm kiếm
• Nút V có đủ cả hai cây con: trường hợp này khá
phức tạp
Trang 284.2.2.3 Phép xóa một nút
Trường hợp này khóa của nút V chen giữa các khóa của nút cực phải của cây con trái và khóa của nút cực trái của cây con phải, vậy gỡ bỏ nút V phải thay thế một nút
khác vào chỗ trống đó để đảm bảo điều
kiện cây tìm kiếm, chỉ có thể thay thế bằng một trong hai nút con trên Có thể xét
trường hợp thay bằng nút cực phải của cây con trái.
Trang 294.2.2.3 Phép xóa một nút
Giải thuật chi tiết:
Với T : cây nhị phân tìm kiếm; X là giá trị cần xóa;
V là con trỏ đến nút đang xét
Xuất phát từ cây gốc V, tìm nút chứa khóa x để loại bỏ, có các trường hợp sau:
- V=Null, không tìm thấy
- X< V.element thực hiện loại bỏ cây bên trái
- X> V.element lặp lại việc tìm để loại bỏ cây bên phải,
- X = V.element, tiến hành gỡ bỏ nút V
Trang 304.2.2.3 Phép xóa một nút
Giải thuật chi tiết:
- Gỡ bỏ nút V:
- Nếu V.right = Null, nối cây con trái của V vào nút cha
- Nếu V.left = Null, nối cây con phải của V vào nút cha
- V có đủ thì dò xuống nút cực phải của cây con trái và sửa cây để đảm bảo điều kiện của cây nhị phân tìm kiếm
Trang 31Nút E là nút cực phải của cây con trái, xóa nút V bằng cách:
-Thay nôôi dung V = E
-Sửa F thành cây con của D
-Hủy nút E
4.2.2.3 Phép xóa một nút
Ví dụ trong t/h đủ cả 2 cây con:
Trang 324.2.2.3 Phép xóa một nút
int xoacuctrai (tree *root )
Trang 334.2.2.3 Phép xóa một nút
void xoa(int x,tree *root)
else
Thủ tục xóa
Trang 344.2.2.3 Phép xóa một nút
if ((*root)->left == NULL) (*root) = (*root)->right;else
if ((*root)->right==NULL) (*root) = (*root)->left;else (*root)->element = xoacuctrai(&(*root)->right);}
if ((*root)->left == NULL) (*root) = (*root)->right;else
if ((*root)->right==NULL) (*root) = (*root)->left;else (*root)->element = xoacuctrai(&(*root)->right);}
Thủ tục xóa
Trang 354.3 Cây nhị phân cân đối (AVL)
Định nghĩa: Cây nhị phân tìm kiếm được gọi là cân đối nếu như đối với mọi nút của nó chiều cao của hai cây con tương ứng
chỉ lệnh nhau một đơn vị.
Trang 374.3 Cây nhị phân cân đối (AVL)
Cấu trúc của một nút sẽ như sau:
typedef int element_type;
Trang 384.3 Cây nhị phân cân đối (AVL)
Các phép toán trên cây nhị phân
(sinh viên tự nghiên cứu thêm)
Trang 39Bài tập
Bài 1.Vẽ cây nhị phân tìm kiếm bằng cách
thêm dần các khóa : 10, 7, 19, 11, 3, 16,
13, 4, 22, 1.
Bài 2: Cài đặt chương trình thực hiện:
– Nhập một cây nhị phân tìm kiếm với các giá trị được nhập vào bàn phím như trên, thực
hiện các phép duyệt cây để in ra các giá trị
trên
– Nhập giá trị x từ bàn phím, kiểm tra x có trong cây không?
Trang 40Bài tập
Bài 3: Viết các thủ tục thêm, xoá một nút có khoá
x trên cây tìm kiếm nhị phân bằng cách không đệ qui
Bài 4: a- Vẽ hình cây tìm kiếm nhị phân tạo ra từ cây rỗng bằng cách lần lượt thêm vào các khoá là các số nguyên: 54, 31, 43, 29, 65, 10, 20, 36, 78, 59
b- Vẽ lại hình cây tìm kiếm nhị phân ở câu a/ sau khi lần lượt xen thêm các nút 15, 45, 55
c- Vẽ lại hình cây tìm kiếm nhị phân ở câu a/ sau khi lần lượt xoá các nút 10, 20, 43, 65, 54