Professional Documents
Culture Documents
1
Nội dung
2
1.Tìm kiếm tuần tự trên danh sách liên kết
Một lợi điểm: dễ làm cho danh sách liên kết có thứ tự
mà giúp cho việc tìm kiếm nhanh chóng hơn.
3
Tìm kiếm tuần tự trên một danh sách liên kết có
thứ tự.
Qui ước: z là nút giả trong danh sách liên kết.
3 4 7 21
Z
…
4
Giải thuật tìm kiếm tuần tự trên danh sách
liên kết
procedure initialize;
begin
new(z); z↑.next: = z;
new(head); head↑.next:= z
end;
6
Chứng minh:
Với sự tìm kiếm thành công, nếu giả sử rằng mỗi mẩu tin
trong danh sách liên kết có xác xuất bằng nhau (1/N) để
được tìm thấy, số lần so sánh trung bình sẽ là:
(1 + 2+ …+ N)/N = N(N+1)/(2N) = (N+1)/2.
Với sự tìm kiếm không thành công, nếu giả sử rằng mỗi mẩu
tin trong danh sách liên kết hay nút kết thúc z có xác xuất
bằng nhau (1/(N+1))để được tìm thấy ở vị trí sau cùng của
quá trình tìm kiếm, số lần so sánh trung bình sẽ là:
(1 + 2+ …+ (N+1))/(N+1) = (N+2)(N+1)/(2(N+1)) = (N+2)/2.
7
2.Cây tìm kiếm nhị phân
Trong một cây tìm kiếm nhị phân (binary search tree),
tất cả các mẩu tin với khóa nhỏ hơn khóa tại nút đang xét
thì ở cây con bên trái của nút và
các mẩu tin với khóa lớn hơn hay bằng khóa tại nút đang
xét thì ở cây con bên phải của nút.
1
0
5 1
3
2 7 1
9
8
Khởi tạo cây nhị phân
procedure tree_init;
begin
new(z); z↑.1: = z; z↑.r: = z;
new(head); head↑.key: = 0; head↑.r: = z;
end;
9
Tác vụ thêm vào
Thêm một nút vào trong cây, ta thực hiện một sự tìm
kiếm (không thành công) nút ấy trên cây, rồi gắn nút
ấy vào vị trí ứng với nút giả z tại điểm mà quá trình tìm
kiếm kết thúc.
A
C H
10
Tác vụ thêm vào (tt.)
procedure tree_insert (v: integer; x: link): link;
var p: link;
;
begin
repeat
p: = x;
if v < x↑.key then x: = x↑.1 else x: = x↑.r
until x = z;
new(x); x↑.key: = v;
x↑.1: = z; x↑.r: = z; /* create a new node */
if v < p↑. key then p↑.1: = x /* p denotes the parent of
the new node */
else p↑.r: = x;
tree p↑.r: = x
end
11
In ra cây nhị phân
procedure treeprint(x: kink)
begin
if x <> z then
begin
treeprint (x↑.1);
printnode (x);
treeprint (x↑.r)
end
end;
Vì một cây nhị phân diễn tả một tập tin có thứ tự, việc in ra
các trị khóa trong cây theo một cách đúng đắn sẽ đem lại
một danh sách các khóa có thứ tự.
12
Tác vụ tìm kiếm
type link = ↑ node;
node = record key, info: integer;
l, r: link end;
var t, head, z: link;
function treesearch (v: integer, x: link): link; /* search the node with
the key v in the binary search tree x */
begin
while v <> x↑. key and x <> z do
begin
if v < x↑.key then x: = x↑.1
else x: = x↑.r
end;
treesearch: = x
end;
13
Tính chất của sự tìm kiếm trên cây nhị phân
Tính chất: Một tác vụ thêm vào hay tìm kiếm trên một cây nhị
phân đòi hỏi chừng 2lnN so sánh trên một cây được tạo ra từ N
trị khóa ngẫu nhiên.
Chứng minh:
Chiều dài lối đi của 1 nút: là số cạnh cần duyệt qua để từ nút
ấy về nút rễ +1.
Đối với mỗi nút trên cây nhị phân, số so sánh được dùng
cho một sự tìm kiếm nút ấy thành công chính là chiều dài
lối đi của nút ấy.
Tổng tất cả chiều dài lối đi của mọi nút trên cây nhị phân
được gọi là chiều dài lối đi của cây nhị phân.
14
Chứng minh (tt.)
Khi chia chiều dài lối đi toàn cây với N, ta sẽ được số so sánh
trung bình đối với một sự tìm kiếm thành công trên cây.
Nhưng nếu CN biểu thị chiều dài lối đi trung bình của toàn
cây, ta có một hệ thức truy hồi sau đây, với C1 = 1
N
CN = N + ∑
1
(Ck-1 + CN-k)
15
Chứng minh (tt.)
k
k-1
N-k
Hệ thức truy hồi này rất giống hệ thức truy hồi khi phân
tích Quicksort, và nó đã được giải cùng một cách để đưa
lại cùng một kết quả.
Do đó chiều dài trung bình của cây N nút là
CN ≈ 2N lnN.
Suy ra chiều dài trung bình của một nút trong cây là
2lnN.
⇒ Một tác vụ tìm kiếm hay thêm vào đòi hỏi trung bình
2lnN so sánh trên một cây gồm N nút.
16
Độ phức tạp trong trưòng hợp xấu nhất
Tính chất: Trong trường hợp xấu nhất, một tác vụ tìm
kiếm trên cây nhị phân gồm N khóa có thể cần N so
sánh.
Trường hợp xấu nhất xảy ra khi cây nhị phân bị suy biến
thành một danh sách liên kết.
Tác vụ xóa
Việc xoá một nút rất dễ nếu nút ấy không có nút con hay chỉ
có một nút con.
Để xóa một nút có đủ hai con thì khá phức tạp: ta phải thay
thế nó với nút có trị khóa cao nhất kế tiếp (tức nút tận cùng
trái của cây con bên phải).
17
E
A R
C H
N
M F
xoá A R
C N
M P
18
The following procedure is to delete the node t from the binary
tree x.
procedure treedelete (t, x: link);
var p, c: link;
begin
repeat /* search for the node t in the tree */
p: = x;
if t↑.key < z↑. key then x: = x↑.1
else x: = x↑.r
until x = t;
if t↑.r = z then /* the node t has no right child */
x: = x↑.1 /* replace the deleted node with the left child of
t */
else if t↑.r↑.1 = then /* the right chile of t has no left child */
begin x: = x↑.r; x↑.1: = t↑.1 end /* replace the deleted node
with its right child */
19
else
begin
e: = x↑.r;
while c↑.1↑.1 <> z do c: = x↑.1; /* find the leftmost node
of the right subtree */
x: = c↑.1; /* x denotes the node that will replace the
deleted one */
c↑.1 = x↑.r; /* connect c, the parent of x to the right
child of x */
x↑.1: = t↑.1; x↑.r: = t↑.r /* connect x: the children of the
deleted node t */
end;
if t↑.key < p↑.key then p↑.1: = x /* connect x to the parent
of the deleted node */
else p↑.r: = x;
end;
20
3. Hàng đợi có độ ưu tiên và giải thuật sắp
thứ tự HEAPSORT
21
Hàng đợi có độ ưu tiên (tt.)
Chúng ta muốn xây dựng và duy trì một cấu trúc dữ liệu chứa những
mẩu tin có trị khóa số (độ ưu tiên) và có hỗ trợ một số trong những
tác vụ sau:
- tạo một hàng đợi có thứ tự ưu tiên gồm N phần tử.
- thêm (insert ) một phần tử mới vào.
- xóa bỏ phần tử lớn nhất ra khỏi hàng đợi.
- thay thể phần tử lớn nhất với một phần tử mới
- thay đổi độ ưu tiên của một phần tử.
- Xóa bỏ một phần tử bất kỳ nào đó.
- Ghép hai hàng đợi có độ ưu tiên thành một hàng đợi có độ ưu tiên
lớn hơn.
22
Thi công hàng đợi có độ ưu tiên
23
Cấu trúc dữ liệu heap
Cấu trúc dữ liệu mà có thể hỗ trợ cho các tác vụ làm việc với
hàng đợi có độ ưu tiên sẽ chứa các mẩu tin trong một mảng
sao cho:
mỗi khóa phải lớn hơn khóa ở hai vị trí khác trong mảng.
Tương tự mỗi khóa trong hai khóa này phải lớn hơn hai trị
khóa khác và cứ như thế..
Thứ tự này sẽ dễ thấy hơn khi ta diễn tả mảng như một cấu
trúc cây với những đường nối mỗi khóa xuống hai khóa
nhỏ hơn.
Các trị khóa trong cấu trúc cây thỏa điều kiện heap như sau:
Khóa tại mỗi nút cần phải lớn hơn (hay bằng) các khóa ở
hai con của nó (nếu có). Điều này hàm ý rằng trị khóa lớn
nhất ở nút rễ.
24
Thí dụ: Heap dưới dạng cây nhị phân
T O
G S
M N
A E R A I
25
Heap dưới dạng một mảng
Ta có thể diễn tả dạng cây của heap thành một mảng bằng
cách đặt nút rễ tại vị trí 1 của mảng, các con của nó tại vị trí
2 và 3, các nút ở các mức kế tiếp ở các vị trí 4, 5, 6 và 7, v.v..
k 1 2 3 4 5 6 7 8 9 10 11 12
a[k] X T O G S MNA E R A I
Từ một nút dễ dàng để đi tới nút cha và các nút con của nó.
26
Các lối đi trên heap
Tất cả các giải thuật làm việc trên heap đi dọc theo
một lối đi nào đó từ nút rễ xuống mức đáy (bottom)
của heap.
⇒ Trong một heap có N nút, tất cả các lối đi (path)
thường có lgN nút trên đó.
27
Các giải thuật trên Heap
Có hai tác vụ quan trọng làm việc trên heap: thêm vào
phần tử mới và xóa bỏ phần tử lớn nhất ra khỏi heap.
28
Tác vụ thêm vào
procedure upheap(k:integer)
var v: integer;
begin
v :=a[k]; a[0]:= maxint;
while a[k div 2] <= v do
begin a[k]:= a[k div 2 ]; k:=k div 2 end;
a[k]:= v
end;
procedure insert(v:integer);
begin
N:= N+1; a[N] := v ; unheap(N)
end;
29
Thêm (P) vào heap
T P
G S
O N
A E R A I M
30
Tác vụ xóa bỏ phần tử lớn nhất
Tác vụ xóa sẽ làm giảm kích thước của heap một đơn vị,
tức nó làm giảm N một đơn vị.
31
Tác vụ xóa bỏ
procedure downheap(k: integer);
label 0 ;
var j, v : integer;
begin
v:= a[k];
while k<= N div 2 do
begin
j:= 2*k;
if j < N then if a[j] < a[j+1] then function remove: integer;
j:=j+1; begin
if v >= a[j] then go to 0; remove := a[1];
a[k]:= a[j]; k:= j; a[1] := a[N]; N := N-1;
end; downheap(1);
0: a[k]: =v end;
end;
32
Thí dụ về tác vụ xóa
Trước khi xóa
T
S P
G R
O N
A E C A I
M
33
Sau khi xóa
R P
G M
O N
A E C A I
34
Tính chất của các tác vụ trên heap
Tất cả những tác vụ này phải đi dọc theo một lối đi giữa
nút rễ cho đến cuối heap mà bao gồm ít hơn lgN phần tử
với một heap gồm N phần tử.
35
Giải thuật heapsort
Ý tưởng: Giải thuật bao gồm 2 công tác (1) tạo một heap
chứa những phần tử cần sắp thứ tự và (2) lần lượt lấy
chúng ra khỏi heap theo một thứ tự.
M : kích thước của heap
N: số phần tử cần được sắp thứ tự.
N:=0;
for k:= 1 to M do
insert(a[k]); /* construct the heap */
for k:= M downto 1 do
a[k]:= remove; /*putting the element removed into the
array a */
36
Sắp thứ tự dãy số 5, 3, 1, 9, 8, 2, 11 bằng heapsort
5 9
3 1 5 1
9
9
8 1
8 2
3 5
3 5 1
11
8 9
3 5 1 2
37
9
8
8 2
5 2
3 5 1 11
3 1 9 11
5
3
3 2
1 2
1 8 9
11 8 9
5 11
2 1
1 3 2 3
8
5 9 11 5 8 9 11
38
Độ phức tạp của heap sort
39
4.Kỹ thuật băm
Kỹ thuật băm (Hashing) là một phương pháp để tìm kiếm các
mẩu tin trong một bảng bằng các biến đổi các trị khóa thành
những địa chỉ (vị trí) trong bảng.
Bước đầu là tạo một hàm băm (hash function ) mà chuyển đổi
khóa tìm kiếm thành một địa chỉ trong bảng.
Một cách lý tưởng, những trị khóa khác nhau nên ánh xạ
thành những địa chỉ khác nhau, nhưng không có hàm băm nào
là hoàn hảo và do đó hai hay nhiều khóa khác nhau có thể băm
thành cùng một vị trí bảng.
Bước kế tiếp là quá trình giải quyết đụng độ (collision-
resolution) mà đối phó với trường hợp hai hay nhiều khóa
khác nhau có thể băm thành cùng một vị trí bảng.
40
Hàm băm
Hàm băm là hàm biến thể các trị khóa thành những số
nguyên trong tầm [0 .. M-1], với M là số mục tin mà có thể
được chứa trong một số lượng ô nhớ có sẵn.
Một hàm băm lý tưởng là hàm băm mà
- dễ tính toán
- gần giống như một hàm “ngẫu nhiêm”.
Một phương pháp thông thường nhất để băm là cho M là
một số nguyên tố và với mỗi trị khóa k, ta tính
h(k): = k mod M
Đấy là một phương pháp trực tiếp mà dễ tính và rải khá
đều các trị khóa ra trên bảng băm.
41
Ví dụ
Kích thước bảng băm = 101. Giả sử mỗi trị khóa gồm 4 ký
tự. Nếu khóa (“AKEY”) được mã hóa thành một mã gồm 5
bit, ta có thể coi khóa ấy là một tràng số nhị phần như sau:
00001 01011 00101 11001
1 × 323 + 11 x 322 + 5 x 321 + 25 x 320
Mà tương đương với trị số thập phân 44217 .
Vì, 44217 mod 101 = 80, như vậy khóa “AKEY” ánh xạ
thành 80.
Tại sao kích thước M của bảng băm cần phải là số nguyên
tố? Lý do là vì chúng ta muốn tất cả mọi ký tự trong khóa
đều tham gia vào việc chuyển đổi (băm) thành vị trí.
Trong thí dụ trên, nếu M = 32, hàm băm của bất kỳ khóa
nào cũng chỉ băm mỗi ký tự sau cùng!
42
Băm một khóa dài
Nếu khóa là một dòng ký tự khá dài thì chúng ta vẫn có thể
tính bằng một hàm băm mà biến đổi khóa từng ký tự một.
Kỹ thuật đó thể hiện bằng giải thuật lặp như sau:
h:= key[1];
for j:= 2 to key_size do
begin
h:= ((h*32) + key[j]) mod M; /*25 is 32, used for
5-bit code */
end;
43
Phương pháp giải quyết đụng độ: Xâu riêng
(Separate chaining)
Trong kỹ thuật băm, chúng ta phải quyết định dùng cách
nào để giải quyết vấn để hai khóa khác nhau băm thành
cùng một giá trị địa chỉ.
Một phương pháp đơn giản nhất: tạo cho mỗi vị trí trong
bảng băm một danh sách liên kết (xâu riêng) để xâu tất cả
những trị khóa mà băm vào cùng vị trí đó.
Khi các trị khóa được xâu trên danh sách liên kết, chúng
nên được sắp cho có thứ tự.
type link = ↑ node;
node = record key, info: integer;
next: link end;
var heads: array [0..M] of link; t, x: link;
44
Xâu riêng (tt.)
Danh sách liên kết cho từng vị trí trong bảng băm được khởi
tạo như giải thuật sau:
procedure initialize;
var i: integer;
begin
new (z); z↑.next: = z;
for i: = 0 to M-1 do
begin
new (heads [i]); heads [i]↑.next: = z
end;
end;
Trong hình vẽ sau trình bày việc đưa vào bảng băm một dãy
các ký tự chữ.
45
Key: A S E A R C H I N G E X A M P L E
Hash: 1 8 5 1 7 3 8 9 3 7 5 2 1 2 5 1 5
0 1 2 3 4 5 6 7 8 9 10
A M C E G H I
A X N E R S
A E
L P
46
Độ phức tạp của kỹ thuật băm dùng xâu
riêng
Tính chất. Kỹ thuật băm dùng xâu riêng trung bình làm giảm
số lần so sánh một hệ số M so với tìm kiếm tuần tự, và cần chỗ
bộ nhớ cho M con trỏ để liên kết.
Chứng minh:
Nếu N, số khóa có trên bảng băm, lớn hơn nhiều so với M, thì
chiều dài trung bình của các xâu riêng là xấp xỉ N/M. Do đó số
lần so sánh cho việc tìm kiếm tuần tự trên xâu riêng trong
trường hợp trung bình là (N/M)/2.
47
Phương pháp giải quyết đụng độ: Dò tuyến tính
48
Dò tuyến tính (tt.)
49
Giải thuật dò tuyến tính
procedure hash_initialize;
var i: integer;
begin
for i: = 0 to M do a[i].key:= maxint; /* maxint means an empty
position */
end;
function hash_search(v: integer): integer;
var x: integer;
begin
x: = h(v);
while a[x].key <> maxit and a[x].key <> v do
x: = (x+1) mod M;
if a[x].key: = v then hash_search: = x
else hash_search: = M;
end;
50
Dò tuyến tính (tt.)
Hình vẽ sau trình bày việc đưa vào bảng băm một dãy các ký
tự chữ: A S E A R C H I N G E X A M P L E
51
Key: A S E A R C H I N G E X A M P L E
Hash: 1 0 5 1 18 3 8 9 14 7 5 5 1 13 16 12 5
E
E
52
Tính chất của dò tuyến tính
Kích thước bảng băm dùng cho kỹ thuật dò tuyến tính
thường lớn hơn bảng băm dùng xâu riêng, vì ta phải có
M > N, nhưng tổng chỗ bộ nhớ sẽ ít hơn vì không cần lưu
các con trỏ.
53