Câu 1: Giải thuật bổ sung nút mới vào trước nút Q bằng danh sách móc nối hai chiều.. * Ý tưởng: Cho con trỏ L và R lần lượt trỏ tới nút cực trái và nút cực phải của một danh sách móc n
Trang 1Câu 1: Giải thuật bổ sung nút mới vào trước nút Q bằng danh sách móc nối hai chiều
* Ý tưởng:
Cho con trỏ L và R lần lượt trỏ tới nút cực trái và nút cực phải của một danh sách móc nối kép, Q là con trỏ tới một nút trong danh sách này
Bổ sung một nút mới vào trước nút trỏ Q tức là nút cực trái của nút mới trỏ đến nút trước Q, nút cực phải của nút mới trỏ đến Q
Ta sẽ bổ sung được nút mới vào trước Q
Giải thuật: (R=pcuoi, L=pdau )
Insert_B(L,R,Q,X)
{
P=malloc();
P->DATA=X;
P->P_R=NULL;
P->P_L=NULL;
if(R==NULL) //danh sách rỗng
L=R=P;
else{
if(Q==L){
P->P_R=Q;
Q->P_L=P;
L=P;
} else{
P->P_L=Q->P_L;
P->P_R=Q;
Q->P_L=P;
(P->P_L)->P_R=P;
} }
Trang 2Câu 2: Giải thuật loại nút trỏ bởi Q bằng danh sách móc nối hai chiều
Cho L và R là hai con trỏ trái và phải của danh sách móc nối kép, Q trỏ tới một nút trong danh sách Ta sẽ loại bỏ nút trỏ bởi Q ra khỏi danh sách
DELETE(L, R,Q)
{
if (R==NULL)
Printf(“Danh sách rỗng”);
else
{
if( L==R)
L=R=NULL;
else
if ( Q=L ) { L=L->P_R;
L->P_L=NULL;
} else
if (M=R) { R=R->P_L;
R->P_R=NULL;
} else { Q->P_L->P_R=Q->P_R;
Q->P_R->P_L=Q->P_L;
} free(Q);
}
}
Trang 3Giải thuật duyệt cây sau không dùng đệ quy:
Ý tưởng: Đầu tiên ta thăm các nút cây con trái, sau đó thăm các nút cây con phải cuối cùng thăm nút gốc
Như vậy nút gốc chỉ được thăm khi đã duyệt xong 2 cây con của nó Tức
là nút gốc được duyệt khi đi từ con phải lên gặp gốc chứ không phải từ lần đi từ con trái lên gặp gốc
Dùng stack để khử đệ quy
Giải thuật:
TT_SAU_S(T) {
if(T==NULL) {
printf("Cây rỗng");
return;
} else{
TOP=-1;
P=T;
} while(1) {
while(P!=NULL) {
PUSH(S,TOP,P);
P=P->P_L;
} while(S[TOP]<0) {
P=POP(S,TOP);
printf(P->DATA);
if(TOP==-1) return;
} P=S[TOP]->P_R;
S[TOP]=S[TOP] ;
} }
Trang 4Giải thuật Quick_sort
Ý tưởng: chọn một khóa ngẫu nhiên nào đó của dãy làm chốt Mọi phần
tử nhỏ hơn chốt thì nằm trước phần tử chốt, mọi phần tử lớn hơn chốt thì nằm sau chốt Muốn vậy, các phần tử trong dãy phải được so sánh với khóa chốt và đổi vị trí cho nhau và cho chốt nếu những phần tử lớn hơn chốt nằm trước chốt hoặc những phần tử nhỏ hơn chốt nằm sau chốt Khi việc đổi chỗ này được thực hiện xong thì dãy được phân làm hai đoạn: một đoạn gồm những phần tử nhỏ hơn chốt, một đoạn gồm những phần tử lớn hơn chốt, còn khóa chốt nằm ở giữa hai đoạn nói trên và đây cũng là
vị trí thực cảu khóa chốt khi mà dãy được sắp xếp xong Đây coi như kết thúc 1 lượt sắp xếp
Áp dụng phương pháp như trên cho mỗi đoạn và tiếp tục làm như vậy cho đến khi mỗi đoạn chỉ còn 1 phần tử Khi đó toàn bộ dãy đã được sắp xếp
Giải thuật:
Quick_sort(K,t,p) {
if(t<p) { Partition(K,t,p,j);
Quick_sort(K,t,j-1);
Quick_sort(K,j+1,p);
} }
Partition(K,t,p,j) {//K[t] là chốt
i=t+1;
j=p;
do{
while(i<j&&K[i]<K[t]) i=i+1;
while(i<j&&K[j]>K[t]) j=j-1;
if(i<=j){
K[i]<->K[j];//Đổi chỗ K[i] và K[j]
i=i+1;
j=j-1;
} } while(j<=i) K[t]<->K[j];//Đổi chỗ K[t] và K[j]
}
Trang 5Đánh giá thời gian thực hiện giải thuật Quic –Sort với dãy có n phần
tử trong trường hợp tốt nhất
Gọi T(n) là thời gian thực hiện giải thuật ứng với một mảng n khoá, P(n) là thời gian để phân đoạn một mảng n khoá thành hai mảng con Ta
có thể viết:
T(n) = P(n) + T(j-t) + T(p-j)
Chú ý rằng P(n) = Cn với C là một hằng số
Trường hợp tốt nhất xảy ra khi mảng luôn luôn được chia đôi, nghĩa là:
2
p
t
=
Lúc đó:
Ttốt(n) = P(n) + 2Ttốt(n/2)
= Cn + 2Ttốt(n/2) = Cn + 2C(n/2) + 4Ttốt(n/4) = 2Cn + 22Ttốt(n/4)
= Cn + 2C(n/2) + 4C(n/4) + 8Ttốt(n/8) = 23Cn + 23Ttốt(n/8)
n log 2
2
2 Cn ) n (log
= O(nlog2n)
Trang 6Câu: Giải thuật sắp xếp Merge sort:
Ý tưởng:
Để sắp xếp bảng T:
+ Chia T thành 2 bảng độ dài bằng nhau
+ Sắp xếp mỗi bảng con này <dung đệ qquy>
+ Từ 2 bảng con đã sắp, xếp xen kẽ lại để được bảng T được sắp xếp
Giải thuật:
1 Hòa Nhập 2 đường:
MERGE (K, b, m, n, X)
{
i=t=b; j=m+1;
While(i<=m) and (j<=n) //Chừng nào cho 2 marngcon vẫn còn khóa
If (K[i] < K[j]) //So sánh để chọn khóa nhỏ hơn X[t++] = K[i++];
Else
X[t++] = K[j++];//Một trong 2 mảng con đã hết khóa trước
If (i>m) //Mảng 1 hết khóa trước
For (;j<=n;)
X[t++]=K[j++];
Else //Mảng 2 chiều hết khóa trước For (;i<=m;)
X[t++]=K[i++];
}
Trang 72 Sắp xếp trộn trực tiếp: (Bao gồm giải thuật 1 và 2 giải thuật sau):
MPASS (K, X, n, h)
{
i=0;
while (i<=n-2*h) //Hòa nhập cặp mạch có độ dài h
{
MERGE (K, I, i+h-1, i+2*h-1, X);
}
If (i+h<n) //Hòa nhập cắp mạch còn lại với tổng độ dài <2*h
MERGE (K, I, i+h-1, i+2*h-1, X);
Else // chỉ còn 1 mạch
For (; i<n; i++)
X[i]= K[j];
}
Hàm MPASS được gọi tới trong hàm sắp xếp sau:
MERGE_SORT (K, n)
{ h=1;
while (h<n-1) do {
MPASS (K, X, n, h); //Hòa nhập và chuyển các khóa vào K MPASS (K, X, n, 2* h); //Hòa nhập và chuyển các khóa vào K
h= 4+h;
} }