Tải bản đầy đủ (.docx) (18 trang)

DecuongOntapCTDLdoc

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (167.53 KB, 18 trang )

<span class='text_page_counter'>(1)</span><div class='page_container' data-page=1>

<b>CÂU HỎI ÔN TẬP</b>
MÔN CẤU TRÚC DỮ LIỆU


<b>Câu 1</b>



Ta có 4 đối tượng:



Điểm (pixel): bao gồm toạ độ x, tọa độ y.



Đoạn thẳng (line): được xác định bởi 2 điểm (x1, y1) là điểm bắt đầu – (x2, y2) là điểm kết thúc.



Hình chữ nhật (rectangle): được xác định bởi 2 điểm (x1, y1) là góc trên bên trái – (x2,y2) là góc dưới bên phải.


Hình trịn (circle): được xác định bởi một điểm (x, y) là tâm; và R là bán kính.



Hãy định nghĩa (bằng C/PASCAL) các kiểu dữ liệu cho 4 đối tượng trên mà anh(chị) cho là hợp lý nhất.



<i>typedef struct pixel</i>


<i>{</i>



<i>int x,y;</i>


<i>}Point;</i>



<i>Typedef struct</i>


<i>{</i>



<i>Point A;</i>


<i>Point B;</i>


<i>}Line;</i>



<i>Typedef struct</i>


<i>{</i>




<i>Point TopLeft;</i>


<i>Point BottomRight;</i>


<i>}Rectangle;</i>



<i>Typedef struct</i>


<i>{</i>



<i>Point Center;</i>


<i>Int R</i>



<i>}Circle;</i>


<b>Caâu 2</b>



a) Hãy viết 1 đoạn chương trình yêu cầu ngừơi dùng nhập vào 1 số nguyên N và tiến


hành cấp phát 1 mảng động chứa N số kiểu long.



b) Cho moät cấu trúc DEMO gồm có 3 field như sau:


struct DEMO



{


int one;



long two;


char three[10];


}



Hãy khai báo 1 biến con trỏ p với kiểu DEMO; cấp phát bộ nhớ cho con trỏ p; và gán


vào các field của p lần lượt các giá trị sau {1, 500000, “Hello”}




a)

Long *mangdong(void)


{



Int n;


Long *p;



Printf(“\n Nhap so phan tu cua mang: ”) ; scanf(“%d”,&n);


p=(long*)calloc(n, sizeof(long));



if(p==NULL)


{



Printf(“\n Khong cap phat duoc bo nho”);


Exit(1);



}



</div>
<span class='text_page_counter'>(2)</span><div class='page_container' data-page=2>

b)

Khai bao bien con tro kieu DEMO


Struct DEMO *P;


Cap phat bo nho cho con tro P



P=(Struct DEMO*)malloc(sizeof(struct DEMO));


Gan gia tri cho cac thanh phan cua P



P->one=1;


P->two=500000;



Strcpy(p->three,”Hello”);



<b>Caâu 3 </b>



Cho dãy số: 32 17 45 26 10 50 22 15


<b>a)</b> Áp dụng thuật tốn tạo cây nhị phân tìm kiếm để tạo cây từ dãy số trên.
<b>b)</b> Viết thủ tục duyệt cây để kết quả in ra dãy số tăng dần


<b>c)</b> Viết thủ tục thực hiện đảo nhánh cây


Bài giải


C) Void DaoNhanh(Nodeptr &Root)
{


Nodeptr T;
If(Root==NULL)


Return 0;
If(Root!=NULL)


{


T=Root->pLeft;


Root->pLeft=Root->pRight;
Root->pRight=T;


DaoNhanh(Root->pLeft);
DaoNhanh(Root->pRight);
}



}


<b>Câu 4</b>


Cho một danh sách liên kết đơn như sau:



a. p1 = pHead->pNext;


b. p3 = p1->pNext->pNext;


c. p3->data = p1->data;


d. pCurr = p1;



while (pCurr != NULL)


{



pCurr->data *= 5;


pCurr = pCurr->pNext;


}



Ứng với mỗi trường hợp [a] – [d], hãy vẽ lại danh sách, thể hiện rõ sự thay đổi.



Đã giải (tài liệu photo)



<b>Câu 5</b>


<b>a)</b> Cho biết sự khác nhau giữa cấu trúc ngăn xếp và hàng đợi
<b>b)</b> Cho một ngăn xếp s, hàng đợi q và đoạn chương trình như sau:


struct STACK s;
struct QUEUE q;
int x = 2, y = 5;


for (int i=1; i<=y; i++)


</div>
<span class='text_page_counter'>(3)</span><div class='page_container' data-page=3>

while (IsEmpty(q) == 0)


{ pop(q,x); push(s,x); printf(“%5d“,x);


}


while (IsEmpty(s) == 0)


{ pop(s,x); push(q,x);


}


while (IsEmpty(q) == 0)


{ pop(q,x); printf(“%5d“,x);


}


Hãy cho biết kết quả in ra màn hình khi thi hành đoạn chương trình trên là gì ?
<b>Câu 6</b>


Cho cây nhị phân tìm kiếm chứa các số ngun. Viết thủ tục tính giá trị trung bình của các nút chứa số nguyên tố trên cây
<b>Câu 7</b>


Ta có 100.000 từ tiếng Anh, mỗi từ dài khơng q 10 ký tự. Giả sử máy tính của bạn có 1MB bộ nhớ còn trống.


Hãy cho biết cấu trúc dữ liệu nào có thể dùng để lưu tồn bộ dữ liệu nói trên ? Lý giải sự lựa chọn của bạn (ngắn gọn). Khai báo cấu
trúc này bằng C/PASCAL (Lưu ý: kích thước mảng khơng được vượt q 65535 bytes)



<b>Câu 8</b>


Cho dãy số: 32 17 15 26 30 50


<b>a)</b> Hãy xây dựng cây AVL bằng cách thêm lần lượt từng số từ dãy số trên vào cây, nêu các bước thực hiện và vẽ cây trong
từng trường hợp.


<b>b)</b> Viết thủ tục so sánh cấu trúc hai cây AVL.
<b>Câu 9</b>


Cho một danh sách liên kết đơn


<b>a)</b> Viết thủ tục loại bỏ các phần tử trùng nhau (giữ lại duy nhất 1 phần tử) trong danh sách.
<b>b)</b> Viết thủ tục đảo ngược một xâu liên kết.


<b>Câu 10</b>


Cho một cây nhị phân tìm kiếm như hình vẽ. Hãy cho biết thứ tự của các phần tử khi thêm vào cây ra sao để có được cấu
trúc này ? (Giả sử lúc đầu cây rỗng)


Nếu kết quả phép duyệt cây trên là: 3, 7, 9, 5, 12, 20, 18, 15, 10. Hãy cho biết người ta đã áp dụng phép duyệt nào ?
<b>Câu 11</b>


Viết thủ tục tách một danh sách chứa các số nguyên thành hai danh sách: một danh sách gồm các số chẳn còn cái kia chứa
các số lẻ.


//khai bao cau truc
typedef struct Node
{



int Data;


struct Node *Next;//khai bao mot node bang de qui
}NodeType;


typedef Nodetype *Nodeptr;


nodeptr Head,Even,Odd,Result; // Even: chẵn; Odd: lẻ
void InsertListOrder(nodeptr P,nodeptr &Head)
{


nodeptr a,b;
a=b=Head;


if (Head==NULL) Head=P;
while (a!=NULL && a->Data< P->Data)


{


</div>
<span class='text_page_counter'>(4)</span><div class='page_container' data-page=4>

a=a->Next;
}


if (a==Head)
{


P->Next=a;
Head=P;
}



else
{


P->Next=a;
b->Next=P;
}


}


void SpitList(Nodeptr &Head,Nodeptr &Even,nodeptr &Odd) //ham tach danh sach
{


Nodeptr P;
Even=Odd=NULL;
//P=Head;
while(Head!=NULL)
{


P=Head;
Head=P->Next;
P->Next=NULL;


if (P->Data%2==0) InsertListOrder(P,Even);
else InsertListOrder(P,Odd);


//p=p->next;
}


}



<b>Câu 12</b>


Cho đa thức P(x)= anXn<sub> + an-1X</sub>n-1<sub> +... + a1X + a0 </sub>
D) Hãy cài đặt cấu trúc dữ liệu để lưu trữ đa thức này.
E) Viết thủ tục cộng hai đa thức


F) Viết thủ tục lấy đạo hàm của đa thức.


<b>Đã giải (Tài liệu photo)</b>


<b>Câu 13</b>


Cho các khoá : 18 320 46 13 27


Giả sử bảng có kích thước m=7, hàm băm là h(k) = k mod 7
Hãy dùng hình vẽ minh hoạ tình trạng bảng băm sau khi mỗi khố được đưa vào và nói rõ cách giải quyết đụng độ địa chỉ
bằng phương pháp dò tuyến tính.


<b>Câu 14</b>


Viết thủ tục chuyển một danh sách liên kết kép thành một cây nhị phân tìm kiếm, khơng cấp phát thêm bộ nhớ, chỉ thay đổi
các liên kết.


<b>Câu 15</b>


Viết thủ tục dùng ngăn xếp để đổi một số thập phân sang số thập lục phân và ngược lại.
<b>Câu 16</b>


Hãy chọn cấu trúc dữ liệu thích hợp để biểu diễn trong bộ nhớ chính một từ điển tần số gồm tối đa 1000 từ, mỗi từ có độ dài
10 ký tự, đi kèm với mỗi từ là số lần xuất hiện của từ đó (đã được thu thập từ một số văn bản nào đó).



Cấu trúc dữ liệu phải thoả yêu cầu :


 Thời gian truy cập đến một từ là tối thiểu
 Bộ nhớ được dùng là tối thiểu


<b>Câu 17</b>


Cho hai cây nhị phân tìm kiếm được trỏ bởi con trỏ T1 và T2


</div>
<span class='text_page_counter'>(5)</span><div class='page_container' data-page=5>

<b>b)</b> viết thủ tục tính giá trị trung bình các nút trên cây.
<b>c)</b> Viết thủ tục so sánh cấu trúc 2 cây nhị phân tìm kiếm.
<b>Câu 18</b>


<b>a)</b> Hãy nêu các ưu điểm và khuyết điểm mà theo bạn là tiêu biểu nhất của một hàm khi cài đặt bằng đệ qui.
<b>b)</b> Hãy nêu những điểm khác biệt cơ bản của cấu trúc danh sách liên kết đơn so với cấu trúc mảng động.
<b>Câu 19</b>


Cho một danh sách liên kết đơn chứa các giá trị tăng dần


<b>a)</b> Hãy viết thủ tục thực hiện thao tác lưu trữ các phần tử trong danh sách vào một bảng băm với hàm băm tự chọn.
<b>b)</b> Nêu nhận xét về thao tác tìm kiếm một phần tử bất kỳ trên danh sách và trên bảng băm.


<b>Câu 20</b>


Giả sử A là một mảng các số nguyên có thứ tự tăng.


<b>a)</b> Hãy viết thủ tục tạo cây nhị phân tìm kiếm có chiều cao thấp nhất từ các phần tử của A.
<b>b)</b> Viết thủ tục duyệt cây nhị phân tìm kiếm để in ra các giá trị giảm dần.



<b>Câu 21</b>


Hãy so sánh (ngắn gọn) sự giống và khác nhau giữa hai cấu trúc Cây nhị phân tìm kiếm và Danh sách liên kết đơn. Bạn có
nhận xét gì khi thực hiện thao tác tìm kiếm trên hai cấu trúc này.


<b>Câu 22</b>


Cho dãy số: 23 12 72 14 21


Hãy lần lượt thêm các giá trị trên vào bảng băm có kích thước m=7, sử dụng hàm băm H(k)= k mod 7, theo phương pháp dị
tuyến tính. Giải thích rõ từng bước thực hiện.


<b>Câu 23</b>


Cho một mảng a gồm n phần tử kiểu Integer. Ta có thể sắp xếp mảng a bằng cách :


 Từ mảng a, tạo một cây nhị phân tìm kiếm T.
 Duyệt cây T và đưa các nút trở lại mảng a.


a) Cho biết phương pháp duyệt cây T để đưa giá trị các nút vào mảng sao cho mảng được sắp tăng dần.
b) Cài đặt cấu trúc cây T (bằng C/PASCAL).


c) Xây dựng các thủ tục (bằng C/PASCAL):


 Tạo cây nhị phân T từ mảng a.


 Thủ tục duyệt cây để đưa các phần tử trở lại mảng sao cho mảng được sắp tăng dần.


<b>Câu 24</b>



Giữa cấu trúc cây nhị phân tìm kiếm và cấu trúc mảng các phần tử được sắp thứ tự tăng dần, có những điểm giống và khác
nhau như thế nào ?


<b>Câu 25</b>


Cho dãy số: 35 16 42 27 10 58 24 25


<b>a)</b> Áp dụng thuật tốn tạo cây nhị phân tìm kiếm để tạo cây từ dãy số trên.
<b>b)</b> Viết thủ tục duyệt cây để kết quả in ra dãy số giảm dần


<b>c)</b> Viết thủ tục tính chiều cao cây
<b>Câu 26</b>


Hãy viết một thủ tục/hàm tạo một danh sách liên kết đơn từ cây nhị phân tìm kiếm sao cho giá trị các phần tử trong danh
sách có thứ tự tăng dần. Biết gốc của cây là ROOT.


<b>Câu 27</b>


Cho một mảng chứa các số ngun.


a) Viết thuật tốn tìm tần số xuất hiện của từng giá trị trong mảng
b) Cho giá trị x, viết thuật tốn tìm tần số xuất hiện của x trong mảng


<b>Giải câu a:</b>


int MainArray[100]; //mảng ban đầu


int N=0; // Số phần tử trong mảng
int SubArray[100]; //Mảng phụ



void ScanArray(); //Nhập mảng
void PrintArray(); //Xuất mảng


void CheckSimilar(); //Kiểm tra phần tử trùng với nhau
void PrintSubArray(); //In mảng phụ


</div>
<span class='text_page_counter'>(6)</span><div class='page_container' data-page=6>

{


ScanArray();
PrintArray();
CheckSimilar();
PrintSubArray();
getch();
return 0;
}


void ScanArray()
{


printf("Nhap vao so phan tu cua mang: "); scanf("%d",&N);
for(int i=0;i<N;i++)


{


printf("Nhap vao phan tu thu %d: ",i+1);
scanf("%d",&MainArray[i]);


SubArray[i]=0;
}



}


void ScanArray()
{


printf("\n");
for(int i=0;i<N;i++)
{


printf("%d ",MainArray[i]);
}


}


void CheckSimilar()
{


printf("\n");
for(int i=0;i<N;i++)
{


int Count=0;


for(int j=i+1;j<N;j++)
{


if(MainArray[i] == MainArray[j] && SubArray[i]==0)
{


SubArray[j]=-1;


Count++;
}


}


if(SubArray[i]>-1)
SubArray[i]=count+1;
}


}


void PrintSubArray()
{


printf("\n\n\n");
for(int i=0;i<N;i++)
{


if(SubArray[i]>0)


printf("So %d xuat hien %d lan\n",MainArray[i],SubArray[i]);
}


</div>
<span class='text_page_counter'>(7)</span><div class='page_container' data-page=7>

<b>Giải câu b:</b>


Int X=0 // X:gia tri can tim
Void CheckWeight()


{



Int Count=0;


Printf(“\n Nhap vao gia tri X can tim: ”); scanf(“%d”,&X);
For(int i=0;i<N;i++)


{


If(X=MainArray[i])
Count++;
}


Printf(“\n Tan suat cua X: %d”, Count);
}


<b>Câu 28</b>


Hãy so sánh hai phương pháp dùng danh sách nối kết và dị tuyến tính để giải quyết đụng độ trong bảng băm. Cho ví dụ
minh hoạ


<b>Câu 29</b>


Cho một cây nhị phân T có thứ tự duyệt các nút như sau:


 Duyệt NLR: 40 15 6 7 4 30 48 44 52 55 50


 Duyệt LNR: 6 15 4 7 40 44 48 55 52 30 50


Hãy vẽ cây nhị phân T và giải thích tại sao khi biết 2 phương pháp duyệt bất kỳ ta có thể vẽ lại cây nhị phân.


</div>
<span class='text_page_counter'>(8)</span><div class='page_container' data-page=8>

<b>Câu 30</b>



a) Hãy nêu những điểm khác nhau và giống nhau giữa cấu trúc tập tin văn bản và tập tin nhị phân.
b) Hãy viết thuật toán đảo ngược thứ tự các record trong một tập tin nhị phân


<b>Câu 31</b>


Hãy so sánh giữa mảng động và mảng không động về cấu trúc và cách sử dụng. Cho ví dụ minh hoạ


<b>Câu 32</b>


Thực hiện các thao tác sau trên cây nhị phân tìm kiếm (vẽ hình từng bước):
a) Tạo cây từ các số nguyên: 22, 14, 15, 28, 34, 1, 17, 27, 29, 21
b) Xố phần tử có giá trị 28


</div>
<span class='text_page_counter'>(9)</span><div class='page_container' data-page=9>

<b>Câu 33</b>


Sử dụng cấu trúc ngăn xếp (Stack), thực hiện:


<b>a)</b> Tính giá trị biểu thức hậu tố: 3 5 * 4 6 + - 2 *


<b>b)</b> Viết thủ tục chuyển đổi một số nguyên dương dạng thập phân sang dạng bát phân


<b>c)</b> Viết thủ tục kiểm tra chuỗi nhập vào có phải là chuỗi đối xứng hay khơng (chuỗi palindrom)?
a)

Tính giá trị biểu thức hậu tố :



Đọc Xử li Stack


3 Đẩy vào Stack 3


5 Đẩy vào Stack 3, 5



* Lấy 3 và 5 ra khỏi Stack, tính 3*5=15, đẩy 15 vào Stack 15


4 Đẩy vào Stack 15, 4


6 Đẩy vào Stack 15, 4, 6


+ Lấy 4 và 6 ra khỏi Stack, tính 4+6=10, đẩy 10 vào Stack 15, 10
- Lấy 15 và 10 ra khỏi Stack, tính 15-10=5, đẩy 5 vào Stack 5


2 Đẩy vào Stack 5, 2


* Lấy 5 và 2 ra khỏi Stack, tính 5*2=10, đầy 10 vào Stack 10


<b> Ta được kết quả bằng 10</b>


Bài giải:
c)


<b>void Push(char c)</b>


{


if(Top==Max-1)


printf("\n ngan xep day");
else Stack[++top]=c;


/* top++ ; Stack[Top]=c;*/
}



<b>char Pop()</b>


{


if(Top==-1)


{ printf("\n ngan xep rong");
return -1; }


else return Stack[top--];
}


<b>int DX (char S[])</b>


{ int i,n;n=strlen(s);
for (i=0;i<n;i++)


Push(s[i]);
for (i=0;i<n;i++)


if(s[i]!=Pop()) return 0;
return 1;
}


<b>void main()</b>


{ clrscr();
char s[80];
int kq=0;



printf("\n nhap vao mot chuoi: ");
fflush(stdin);


gets(s);
kq=DX(s);
if (kq!=0)


printf("\n chuoi doi xung");


else printf("\n chuoi khong doi xung");
getch();


</div>
<span class='text_page_counter'>(10)</span><div class='page_container' data-page=10>

<b>Câu 34</b>


Cho dãy số được định nghĩa như sau


 f(n) = 1 nếu n = 0 hay n = 1
 f(n) = f(n-1) + f(n-2) nếu n > 1


a) Hãy viết hàm đệ qui tính giá trị của f(n), với n được nhập từ bàn phím.


b) Hãy viết hàm khơng đệ qui tính giá trị của f(n), với n được nhập từ bàn phím. Sử dụng Stack để khử đệ qui.
c) Nêu nhận xét về hai thủ tục trên.


a) Hàm đệ qui tính giá trị của f(n), với n được nhập từ bàn phím.
int fibo(int n)


{



if(n==0 || n==1) return 1;
else return fibo(n-1)+fibo(n-2);
}


b) Khơng dùng đệ qui
int fibo(int n)


{ int temp1, temp2, i=2;
if(n==0 || n==1) return 1;
push(stack,1);


push(stack,1);
while(i<=n)
{


temp1=pop(stack);
temp2=pop(stack);
temp1=temp1+temp2;
i++;


push(stack,temp1);
push(stack,temp2);
}


return (pop(stack)+pop(stack));
}


<b>Câu 35</b>


Cho cây nhị phân tìm kiếm T, mỗi nút trên cây chứa một số nguyên. Hãy viết các thủ tục cho biết:


a) Có bao nhiêu đường đi từ nút gốc đến nút lá ?


b) Có bao nhiêu nút bậc 1 ?
c) Tại mức thứ i có bao nhiêu nút ?


d) Cây con trái và cây con phải của nút gốc có cùng cấu trúc hay không ?
<b>Câu 36</b>


Cho một danh sách liên kết, mỗi nút trong danh sách chứa một điểm có toạ độ (x, y). Hãy viết thủ tục liệt kê những nút có toạ độ nằm
trong đường trịn tâm A(xA,yA) bán kính R


<b>Câu 37</b>


Cho hai số nguyên lớn được lưu trữ trong hai tập tin văn bản, mỗi tập tin chứa một dãy các con số liên tục với nhau.
a) Viết thủ tục để tạo danh sách liên kết (biểu diễn số nguyên lớn) từ tập tin văn bản, mỗi nút trong danh sách chứa một


con số


b) Viết thủ tục so sánh giá trị hai số nguyên lớn
<b>Câu 38</b>


Hãy chỉ ra điểm khác biệt giữa cấu trúc dữ liệu động và cấu trúc dữ liệu khơng động. Cho ví dụ minh hoạ


1. Trong thực tế, một số đối tượng có thể được định nghĩa đệ qui, ví dụ để mơ tả đối tượng "con người" cần thể hiện các
thông tin tối thiểu như :


? Họ tên
? Số CMND


? Thông tin về cha, mẹ



Ðể biễu diễn một đối tượng có nhiều thành phần thơng tin như trên có thể sử dụng kiểu bản ghi. Tuy nhiên, cần lưu ý cha,
mẹ của một người cũng là các đối tượng kiểu NGƯỜI, do vậy về nguyên tắc cần phải có định nghĩa như sau:


</div>
<span class='text_page_counter'>(11)</span><div class='page_container' data-page=11>

char Hoten[30];
int So_CMND ;
NGUOI Cha,Me;
};


Nhưng với khai báo trên, các ngơn ngữ lập trình gặp khó khăn trong việc cài đặt không vượt qua được như xác định kích
thước của đối tượng kiểu <b>NGUOI.</b>


2. Một số đối tượng dữ liệu trong chu kỳ sống của nó có thể thay đổi về cấu trúc, độ lớn, như danh sách các học viên trong một
lớp học có thể tăng thêm, giảm đi ... Khi đó nếu cố tình dùng những cấu trúc dữ liệu tĩnh đã biết như mảng để biểu diễn
những đối tượng đó lập trình viên phải sử dụng những thao tác phức tạp, kém tự nhiên khiến chương trình trở nên khó đọc,
do đó khó bảo trì và nhất là khó có thể sử dụng bộ nhớ một cách có hiệu quả.


<b>3. </b>Một lý do nữa làm cho các kiểu dữ liệu tĩnh không thể đáp ứng được nhu cầu của thực tế là tổng kích thước vùng nhớ dành
cho tất cả các biến tĩnh chỉ là 64Kb (1 Segment bộ nhớ). Khi có nhu cầu dùng nhiều bộ nhớ hơn ta phải sử dụng các <b>cấu </b>
<b>trúc dữ liệu động. </b>


4. Cuối cùng, do bản chất của các dữ liệu tĩnh, chúng sẽ chiếm vùng nhớ đã dành cho chúng suốt quá trình hoạt động của
chương trình. Tuy nhiên, trong thực tế, có thể xảy ra trường hợp một dữ liệu nào đó chỉ tồn tại nhất thời hay không thường
xuyên trong quá trình hoạt động của chương trình. Vì vậy việc dùng các CTDL tĩnh sẽ không cho phép sử dụng hiệu quả bộ
nhớ.


<b>Câu 39</b>


Hãy chỉ ra điểm khác biệt giữa cấu trúc tập tin nhị phân và mảng các biến cấu trúc. Cho ví dụ minh hoạ
<b>Câu 40</b>



Giả sử ta xét các khoá là các từ đơn . Người ta mã hố các từ theo qui tắc: mỗi kí tự được mã hoá thành hai chữ số thập
phân ứng với thứ tự của nó trong bảng chữ cái La tinh (từ 01 đến 26). Ví dụ khố KEY được mã hoá thành 11 05 25
Cho các khoá TIN, HOC, LAC, HONG hãy dựa vào mã của chúng để tính địa chỉ băm với hàm băm dùng phương pháp chia,
biết kích thước bảng băm là m=500


<b>Câu 41</b>


Cho mảng A chứa dãy số: 11 15 21 22 35 42 61


a) Viết thủ tục đệ quy thực hiện tìm kiếm giá trị X trong dãy số trên theo thuật tốn tìm nhị phân
b) Viết thủ tục không đệ quy thực hiện tìm kiếm giá trị X trong dãy số trên, sử dụng stack để khử đệ quy


<b>Bài giải</b>
<b>Câu a</b>


int BinarySearch_Recursion(ItemType arr[ ], int n, ItemType key)
{


if(n < 1)


return -1;
int middle = n / 2;
if(arr[middle] == key)


return middle;
if(arr[middle] > key)


return BinarySearch_Recursion(arr, middle, key);
if(arr[middle] < key)



return middle + BinarySearch_Recursion(arr + middle, n - middle, key);
}


<b>Câu b</b>


int BinarySearch_Stack(ItemType arr[ ], int n, ItemType key)
{


Stack<int> st;
st.Push(n / 2);
int middle;
int inc = 0;


while(n > 0 && st.Pop(middle))
{


if((arr + inc)[middle] == key)
return inc + middle;
else if((arr + inc)[middle] > key)


n = middle;
else if((arr + inc)[middle] < key)
{


</div>
<span class='text_page_counter'>(12)</span><div class='page_container' data-page=12>

}


st.Push(n / 2);
}



return -1;
}


<b>Câu 42</b>


Cho cây AVL


Hãy lần lượt loại bỏ các nút 13, 15, 5 và 10. Nêu rõ tình huống xảy ra với từng trường hợp và cách giải quyết, minh hoạ
bằng hình vẽ


<b>Câu 43</b>


Cho cây nhị phân tìm kiếm T với cấu trúc mỗi node như sau:
struct Node{


int data;


Node *Left, *Right;
};


typedef Node *BSNode;
Hãy viết các thủ tục:


a) Đếm số node có bậc 1 trên cây


b) Tạo mảng động a (các phần tử là các số nguyên) có số phần tử là số node lá của cây T, mỗi phần tử mang giá trị là giá
trị của các node lá


Bài giải
Câu a:



void CountNode_1(Nodeptr &Root)
{


Nodeptr P;
P=Root;


if(P==NULL) return 0;


else if((P->Left==NULL && P->Right!=NULL) || (P->Left!=NULL && P->Right==NULL))
return(1+CountNode_1(P->Left)+CountNode_1(P->Right))


else


return ( CountNode_1(P->Left)+CountNode_1(P->Right))
}


Câu b


<b>Câu 44</b>


Giả sử phải viết một chương trình cho phép tra tự điển Anh Việt. Hãy trình bày một cách tổ chức dữ liệu cho tự điển, và cho
các định nghĩa kiểu dữ liệu cần thiết.


<b>Câu 45</b>


Cho dãy số: 42 11 22 35 61 21 15


Hãy thêm lần lượt từng số trong dãy số trên vào một cây nhị phân cân bằng (cây AVL). Giải thích rõ từng bước và vẽ hình
minh hoạ



<b>Câu 46</b>


Một ma trận chứa rất ít phần tử với gía trị có nghĩa (phần tử khác 0) gọi là ma trận thưa.


a) Tìm cấu trúc dữ liệu biểu diễn ma trận thưa sao cho tiết kiệm nhất (chỉ lưu trữ các phần tử có ý nghĩa).
b) Viết các thủ tục cho phép nhập, xuất ma trận và cộng 2 ma trận thưa


Bài giải


10


0



10


5



7



9


3



5



13

10



</div>
<span class='text_page_counter'>(13)</span><div class='page_container' data-page=13>

a) Biểu diễn CTDL lưu trữ ma trận thưa


Do ma trận thưa có nhiều phần tử=0 nên ta chỉ cần quan tâm tới những phần tử !=0
Có thể dùng mảng để tổ chức lưu trữ



Struct SNode{


Int Row, Col, Value;
SNode *Link;
};


Struct Matrix{


Int SRow, SCol;
SNode *M;
};


b) Thủ tục nhập, xuất, cộng ma trận thưa.
void CreateMatrix(Matrix &A)


{


A.Srow=0;
A.Scol=0;
A.M=NULL;
}


//Thủ tục nhập


void InputMatrix(Matrix &A)
{


SNode *P,*Q;
int temp;
do{



printf("\nTong so dong cua ma tran: ");
A.SRow=InputNumber();


}while(A.SRow<=0);
do {


printf("\nTong so cot cua ma tran: ");
A.Scol=InputNumber();


} while(A.Scol<=0);


printf("\nNhap du lieu cho ma tran:\n\n");
for (int i=1;i<=A.Srow;i++)


{


printf("\t|\t");


for (int j=1;j<=A.Scol;j++)
{


temp=InputNumber();
if(temp==0) printf("0\t");
else


{


P=new SNode;



P->value=temp;
P->Row=i;
P->Col=j;


Q=A.M;


if (Q==NULL)


{


Q->Link=A.M;


</div>
<span class='text_page_counter'>(14)</span><div class='page_container' data-page=14>

}


else


{


while(Q->Link!=NULL)
Q=Q->Link;


P->Link=NULL;


Q->Link=P;


}


printf("\t");
}



}
printf("|\n");
}


printf("\n");
}


//xuat du lieu cua ma tran.
void OutputMatrix(Matrix A)
{


printf("\n");


for (int i=1;i<=A.Srow;i++)


{


printf("\t|");


for (int j=1;j<=A.Scol;j++)


{


printf("%4d",OutSnode(A,i,j));


}


printf(" |\n");


}



printf("\n");
}


//Cong 2 ma tran


Matrix SumMatrix(Matrix A, Matrix B)
{


Matrix C;
CreateMatrix(C);
Snode *p=A.M, *q=B.M;
while (p!=NULL && q!=NULL)
{


if (p->row<q->row)
{


InserBottom(C,p->row,p->col,p->value);
p=p->link;


}
else


if (p->row==q->row)
{


if (p->col<q->col)
{



</div>
<span class='text_page_counter'>(15)</span><div class='page_container' data-page=15>

p=p->link;
}


else


if (p->col==q->col)
{


InserBottom(C,p->row,p->col,p->value+q->value);
p=p->link;


q=q->link;
}


else


if(p->col>q->col)
{


InserBottom(C,p->row,q->col,q->value);
q=q->link;


}
}
else


if (p->row>q->row)
{


InserBottom(C,q->row,q->col,q->value);


q=q->link;


}
}


if (p!=NULL)
while (p!=NULL)
{


InserBottom(C,p->row,p->col,p->value);
p=p->link;


}
else


if (q!=NULL)
while (q!=NULL)
{


InserBottom(C,q->row,q->col,q->value);
q=q->link;


}


C.Srow=A.Srow;
C.Scol=A.Scol;
return C;
}


<b>Câu 47</b>



Cho biểu thức ngoặc đầy đủ: P=(((a+b)/c)-(d*e))
Sử dụng cấu trúc stack, hãy thực hiện:


a) Viết thủ tục chuyển đổi biểu thức sang dạng biểu thức hậu tố
b) Viết thủ tục tính giá trị biểu thức


</div>
<span class='text_page_counter'>(16)</span><div class='page_container' data-page=16>

<b>a) Viết thủ tục chuyển đổi biểu thức sang dạng biểu thức hậu tố</b>
-Dùng Stack để chứa các toán tử, và dấu ngoặc mở.


-Dùng thủ tục Push(V) để đẩy một phần tử vào trong Stack.
-Hàm Pop dùng để lấy một phần tử từ trong Stack


-Hàm Get để đọc giá trị của phần tử nằm ở đỉnh Stack mà khơng lấy nó ra.


-Độ ưu tiên dùng hàm Priority qui ước như sau: Cao nhất là dấu “*” và “/” với Priority là 2, dấu “+” và “-” với Priority là
1, dấu ngoặc mở Priority là 0


<b>{Cài đặt thuật toán bằng Pascal}</b>
Program ConvertInfixToRPN;
Const


Opt = [‘(‘ , ’)’, ‘+’, ‘-’, ‘*’, ‘/’];
Var


T, Infix, Stack: String; {Stack dùng để chứa toán tử và dấu ngoặc mở nên dùng String}
P: Integer;


{---Các thao tác đối với Stack---}
Procedure StackInit;



Begin


Stack:= ‘ ’;
End;


Procedure Push (V: Char);
Begin


Stack:=Stack+V;
End;


Function Pop: Char;
Begin


Pop := Stack[Length(Stack)];
Dec(Stack[0]);


End;


Function Get: Char;
Begin


Get := Stack[Length(Stack)];
End;


{---}


Procedure Refine (var S:String); {Hiệu chỉnh biểu thức trung tố về khuôn dạng dễ đọc nhất}
Var



I: integer;
Begin


S:=S+ ‘ ’;


For i:=Length(S) – 1 downto 1 do {Thêm những dấu cách trước và sau toán tử và dấu ngoặc}
If (S[i] in Opt) or (S[i+1] in Opt) then Insert (‘ ’, S, i+1);


For i:=Length(S) -1 downto 1 do {xóa những dấu cách trước và sau tốn tử và dấu ngoặc}
If (S[i]= ‘ ’ ) or (S[i+1] = ‘ ’ ) then Delete (S,i+1, 1);


End;


Function Priority(Ch: Char):Integer {Hàm lấy mức độ ưu tiên}
Begin


Case ch of


‘ * ’, ‘ / ’ : Priority:=2;
‘ + ’, ’ - ‘ :Priority:=1;
‘( ‘ : Priority :=0;
End;


End;


Procedure Process (T: String); {Xử lí phần tử đọc được từ biểu thức trung tố}
Var


C,X :Char;


Begin


C:=T[1];


If not (C in Opt) then Write(T, ‘ ’)
Else


Case C if


‘ ( ’ : Push (C) ;
‘ ) ’ : Repeat


X:=Pop;


If X<> ‘ ( ’ then Write (X, ‘ ’);
Until X= ‘ ( ’;


‘ + ’, ‘ - ’, ‘ * ’, ‘ / ’:
Begin


</div>
<span class='text_page_counter'>(17)</span><div class='page_container' data-page=17>

Write (Pop, ‘ ’);
Push (C);


End;
End;


Begin


Write (‘Infix = ’); Readln(Infix);
Refine(Infix);



Writeln (‘Refined: ’, Infix);
Write (‘RPN: ’);


T := ‘ ’;


For p:=1 to Length (Infix) do


If Infix[p] <> ‘ ’ then T:=T+Infix[p]
Else


Begin


Process (T);
T := ‘ ’;
End;


While Stack <> ‘ ’ do Write (Pop, ‘ ’);
Writeln ;


End.


<b>b) Viết thủ tục tính giá trị biểu thức</b>
Program CalculateRPNExpression;
Const


Opt = [‘+’, ‘-’, ‘*’, ‘/’];
Var


T, RPN : String;



Stack: Array[1..255] of Extended;
P, Last : Integer;


{---Các thao tác đối với Stack---}
Procedure StackInit;


Begin
Last :=0;
End;


Procedure Push (V : Extended);
Begin


Inc(Last); Stack [Last]:=V;
End;


Function Pop: Extended;
Begin


Pop:=Stack[Last]; Dec(Last);
End;


{---}


Procedure Refine (var S:String); {Hiệu chỉnh biểu thức trung tố về khuôn dạng dễ đọc nhất}
Var


I: integer;
Begin



S:=S+ ‘ ’;


For i:=Length(S) – 1 downto 1 do {Thêm những dấu cách trước và sau toán tử và dấu ngoặc}
If (S[i] in Opt) or (S[i+1] in Opt) then Insert (‘ ’, S, i+1);


For i:=Length(S) -1 downto 1 do {xóa những dấu cách trước và sau toán tử và dấu ngoặc}
If (S[i]= ‘ ’ ) or (S[i+1] = ‘ ’ ) then Delete (S,i+1, 1);


End;


Procedure Process (T: String); {Xử lí phần tử T đọc được từ biểu thức RPN}
Var


X, Y :Extended;
E: Integer;
Begin


If not (T[1] in Opt ) then {T là toán hạng}
Begin


Val(T,X,E) ; Push(X); {Đổi T thành số và đẩy giá trị đó vào Stack}
End;


Else {T là tốn hạng}


Begin


Y:= Pop; X:=Pop; {Ra hai}
Case T[1] of



‘+’ : X :=X+Y;
‘-’ : X :=X-Y;
‘*’ : X :=X*Y;
‘/’ : X :=X/Y;
End;


Push(X); {Vào một}


</div>
<span class='text_page_counter'>(18)</span><div class='page_container' data-page=18>

Begin


Write (‘Enter RPN Expression: ’); Readln(RPN);
Refine(RPN);


StackInit;
T:= ‘ ’;


For p:=1 to Length(RPN) do {Xét các kí tự của biểu thức RPN từ trái sang phải}
If RPN[p] <> ‘ ’ then T:=T+RPN[p] {Nếu khơng phải dấu cách thì nối nó vào xâu T}


Else {Nếu gặp dấu cách}


Begin


Process(T); {Xử lí phần vừa đọc xong}


T:= ‘ ’; {Đặt lại T để chuẩn bị đọc phần tử mới}
End;


Writeln(RPN, ‘ = ’, Pop:0:4) {In giá trị biểu thức RPN được lưu trog Stack}


End.


<b>Câu 48</b>


Cho mảng A chứa dãy số: 11 15 21 22 35 42 61


c) Viết thủ tục đệ quy thực hiện tìm kiếm giá trị X trong dãy số trên theo thuật tốn tìm nhị phân
d) Viết thủ tục khơng đệ quy thực hiện tìm kiếm giá trị X trong dãy số trên, sử dụng stack để khử đệ quy


<b>Giống câu 41</b>


<b>Câu 49</b>


Cho các khoá : 1 , 8 , 27 , 125 , 216 , 343


Giả sử bảng có kích thước m=7, hàm băm là h(k)= k mod 7


Hãy dùng hình vẽ minh hoạ tình trạng bảng băm sau khi mỗi khoá được đưa vào và nói rõ cách giải quyết đụng độ địa chỉ
bằng phương pháp dị tuyến tính


<b>Câu 50</b>


Cho cây AVL


a) Lần lượt thêm vào cây các khoá 7, 2, 1, 3, 6. Hãy nêu rõ các tình huống xảy ra ứng với từng trường hợp và cách giải
quyết. Minh họa bằng hình vẽ


b) Hãy nêu tình huống xảy ra và cách giải quyết khi xoá phần tử 4


Đã giải(Xem tài liệu viết tay)



4



</div>

<!--links-->

Tài liệu bạn tìm kiếm đã sẵn sàng tải về

Tải bản đầy đủ ngay
×