Tải bản đầy đủ (.ppt) (120 trang)

thi liên thông information technology

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 (260.43 KB, 120 trang )

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

2


<b>NỘI DUNG CHƯƠNG 4</b>



1. Khái niệm danh sách


2. Các phép toán trên danh sách
3. Danh sách đặc


 Định nghĩa


 Biểu diễn danh sách đặc


 Các thao tác trên danh sách đặc
 Ưu nhược điểm và ứng dụng


4. Danh sách liên kết


 Định nghĩa


 Danh sách liên kết đơn
 Danh sách liên kết kép


 Ưu nhược điểm của danh sách liên kết


5. Danh sách hạn chế


 Hàng đợi
 Ngăn xếp


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

<b>1. </b>

<b>Khái niệm danh sách</b>




Danh sách a



1

, a

2

, ….a

N

là tập hợp các phần tử có



kiểu dữ liệu xác định và giữa chúng có 1 mối quan



hệ nào đó. Nếu biết phần tử a

i

vị trí của phần tử



a

i+1


Số phần tử trong một danh sách là chiều dài của 1



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

4

<b>2. Các phép toán trên danh sách</b>



Tùy theo loại của từng danh sách sẽ có các phép tốn khác nhau,
các phép tốn thơng thường như sau:


<i><b>2.1. Tạo mới 1 danh sách</b></i>


 Đưa vào danh sách nội dung các phần tử.
 Chiều dài của danh sách là xác định.


<i><b>2.2. Thêm 1 phần tử vào danh sách</b></i>


 Khi thêm 1 phần tử chiều dài danh sách tăng lên.


 Có thao tác thêm vào đầu, cuối hay tại 1 vị trí xác định của
danh sách.



<i><b>2.3. Tìm kiếm 1 phần tử trong danh sách</b></i>


 Tìm 1 phần tử trong danh sách thỏa mãn điều kiện nào đó
 Dùng các thuật tốn tìm kiếm trong chương “Tìm kiếm”


<i><b>2.4. Loại bớt 1 phần tử trong danh sách</b></i>


 Chiều dài danh sách giảm xuống 1 phần tử


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

<b>2. Các phép toán trên danh sách (tt)</b>



<i><b>2.5. Sửa đổi giá trị 1 phần tử trong danh sách</b></i>


 Thay đổi thông tin của 1 phần tử trong danh sách


 Công việc cập nhật phần tử cũng bao gồm thao tác tìm kiếm


ra phần tử cần hủy trong danh sách.


<i><b>2.6. Sắp xếp danh sách</b></i>


 Dùng các thuật toán trong chương sắp xếp.


<i><b>2.7. Tách danh sách thành nhiều danh sách con</b></i>


 Tách danh sách thành các DS con theo 1 quy luật chia nào đó
 Tổng chiều dài các danh sách được chia bằng chiều dài danh


sách ban đầu



<i><b>2.8. Nhập nhiều danh sách thành 1 danh sách</b></i>


 Nhập các danh sách thành 1 danh sách


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

6

<b>3. Danh sách đặc (Condensed List)</b>



<i><b>3.1. Định nghĩa</b></i>


 Danh sách đặc là danh sách mà không gian bộ nhớ lưu trữ


các phần tử nằm kề cận nhau trong bộ nhớ.


<i><b>3.2. Biểu diễn danh sách đặc</b></i>


 Biểu diễn danh sách đặc dùng <i>1mảng </i> các phần tử có kiểu dử


liệu là kiểu dữ liệu của các phần tử trong danh sách


 Cần biết <i>chiều dài tối đa</i> của một danh sách đặc thông qua 1


biến.


 Cần biết <i>chiều dài thực</i> của một danh sách đặc thông qua 1


biến.


VD:#define MaxLength 1000
int RealLength;



T CD_List[MaxLength]


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

<b>3. Danh sách đặc (tt)</b>



<i><b>3.3. Các thao tác trên danh sách đặc</b></i>


Một số thao tác trên danh sách đặc được thống kê tóm tắt:
3.3.1. Khởi tạo danh sách


Khởi tạo danh sách cho chiều dài danh sách trở về 0.
void Khoitao(int &Len)


{


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

8

<b>3. Danh sách đặc (tt)</b>



<i><b>3.3. Các thao tác trên danh sách đặc (tt)</b></i>


3.3.2. Tạo danh sách mới & nhập danh sách


Tạo danh sách mới có chiều dài tối đa MaxLen, hàm trả về giá trị thực
của danh sách mới được tạo.


int TaoDanhSach(int M[], int &Len)
{


if (Len > MaxLen)
Len = MaxLen;



for (int I = 0; i< Len;I++)
M[I] = Nhapphantu();
return (Len);


}


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

<b>3. Danh sách đặc (tt)</b>


<i><b>3.3. Các thao tác trên danh sách đặc (tt)</b></i>


3.3.3. Thêm 1 phần tử vào danh sách


Thêm 1 phần tử có giá trị NewValue vào trong danh sách có chiều dài
Length tại vị trí InsPos


B1: IF (Length = MaxLen)
Thực hiện BKT


B2: Pos = Length+1
B3: IF(Pos = InsPos)


Thực hiện B7


B4: M[Pos] = M[Pos -1]
B5:


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

10

<b>3. Danh sách đặc (tt)</b>



<i><b>3.3. Các thao tác trên danh sách đặc (tt)</b></i>



3.3.3. Thêm 1 phần tử vào danh sách (tt)


int Themphantu(int M[], int &Len, int x, int InsPos)
{


if (Len == MaxLen)
return (-1);


for (int I = Len; I >InsPos; I++)
M[I] = M[I-1];


M[InsPos] = x;
Len++;


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

<b>3. Danh sách đặc (tt)</b>



<i><b>3.3. Các thao tác trên danh sách đặc (tt)</b></i>


3.3.4. Tìm kiếm 1 phần tử trong danh sách


Dùng các thuật tốn tìm kiếm tìm phần tử thỏa mãn điều kiện
trong danh sách


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

12

<b>3. Danh sách đặc (tt)</b>



<i><b>3.3. Các thao tác trên danh sách đặc (tt)</b></i>


3.3.5. Hủy 1 phần tử trong danh sách



 Loại bỏ phần tử có vị trí DelPos trong danh sách M có chiều dài


Length (có thể có thao tác tìm kiếm xác định vị trí xóa phần tử)
Thuật tốn:


B1: IF(Length =0 OR DelPos > Len) Thực hiện BKT
B2: Pos = DelPos


B3: IF(Pos = Length)
Thực hiện B7


B4: M[Pos] = M[Pos+1]
B5: Pos++


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

<b>3. Danh sách đặc (tt)</b>



<i><b>3.3. Các thao tác trên danh sách đặc (tt)</b></i>


3.3.5. Hủy 1 phần tử trong danh sách (tt)
int Xoaphantu(int M[], int &Len, int DelPos)
{


int (Len ==0 || DelPos >=Len)
return (-1);


for (int I =DelPos; i<Len; i++)
M[i] = M[i+1];


Len --;



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

14

<b>3. Danh sách đặc (tt)</b>



<i><b>3.3. Các thao tác trên danh sách đặc (tt)</b></i>


3.3.6. Sửa đổi giá trị cho 1 phần tử trong danh sách


 Giả sử phần tử trong danh sách được thay đổi ở tại vị trí


Position trong danh sách M có chiều dài Length.


 Thao tác sửa đổi là thao tác <i>tìm kiếm</i> phần tử cần có vị trí


(hay giá trị) và <i>gán giá trị</i> mới


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

<b>3. Danh sách đặc (tt)</b>



<i><b>3.3. Các thao tác trên danh sách đặc (tt)</b></i>


3.3.7. Sắp xếp thứ tự phần tử trong danh sách
Dùng các thuật toán sắp xếp nội


 Giải thuật sắp xếp nổi bọt (Bubble Sort)


 Giải thuật s<i>ắp xếp dựa trên phân hoạch (Quick Sort)</i>


 Giải thuật sắp xếp chọn trực tiếp (Straight Selection Sort)
 Giải thuật sắp xếp chèn trực tiếp (Straight Insertion Sort)
 Giải thuật sắp xếp trộn trực tiếp (Straight Merge Sort)



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

16

<b>3. Danh sách đặc (tt)</b>



<i><b>3.3. Các thao tác trên danh sách đặc (tt)</b></i>


3.3.8. Tách 1 danh sách thành nhiều danh sách


Có nhiều thao tác tách 1 danh sách thành nhiều danh sách:


 Phân phối luân phiên theo đường chạy (distribute)


 Phân phối từng phần của danh sách thành các danh sách con
 Tách các phần tử thỏa mãn điều kiện cho trước thành các


danh sách con.


Giả sử cần tách danh sách M có chiều dài Length thành các danh
sách con SM1, SM2 có chiều dài tương ứng là Slen1 và


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

<b>3. Danh sách đặc (tt)</b>



<i><b>3.3. Các thao tác trên danh sách đặc (tt)</b></i>


3.3.8. Tách 1 danh sách thành nhiều danh sách (tt)
B1: IF(SLen1 >= Len)


SLen1 = Len
SLen2 = 0



B2:IF(SLen2 >= Len)
SLen2 = Len
SLen1 = 0


B3: IF(SLen1 + SLen2 <> Len) SLen2 = Len – SLen1
B4: IF (SLen1 < 0) SLen1 = 0


B5: IF (SLen2 < 0) SLen2 = 0
B6: I =1, SI = 1


B7: IF (I > SLen1) Thực hiện B11
B8: SM[SI] = M[I]


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

18

<b>3. Danh sách đặc (tt)</b>



<i><b>3.3. Các thao tác trên danh sách đặc (tt)</b></i>


3.3.8. Tách 1 danh sách thành nhiều danh sách (tt)


void CS_Split(T M[], int Len, T SM1[], int &SLen1, T SM2[], int &SLen2)
{ if (Slen1 >=Len)


{ SLen1 = Len;
Slen2 = 0;
}


if (Slen2 >=Len)
{ SLen2 = Len;



SLen1 = 0;
}


if (SLen1 < 0) SLen1 = 0;
if (SLen2 < 0) SLen2 = 0;


if (SLen1 + SLen2 != Len) SLen2 = Len - SLen1;
for (int i=0; i<SLen1; i++) SM1[i] = M[i];


for (int j=0; j<SLen2; i++, j++) SM2[j] = M[i];
return;


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

<b>3. Danh sách đặc (tt)</b>



<i><b>3.3. Các thao tác trên danh sách đặc (tt)</b></i>


3.3.9. Nhập nhiều danh sách thành 1 danh sách
Các cách nhập danh sách:


 Ghép nối đi các danh sách thành danh sách mới có chiều


dài là tổng chiều dài các danh sách.


 Trộn xen kẽ các phần tử trong danh sách con theo 1 quy luật


nào đó thành 1 danh sách mới (dùng thuật toán merge trong
merge sort)


Giả sử cần ghép danh sách SM1, SM2 có chiều dài SLen1,



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

20

<b>3. Danh sách đặc (tt)</b>



<i><b>3.3. Các thao tác trên danh sách đặc (tt)</b></i>


3.3.9. Nhập nhiều danh sách thành 1 danh sách(tt)
Thuật tốn:


B1: IF (Slen1+SLen2 > MaxLen) // M khơng đủ khả năng chứa


Thực hiện BKT


B2: I = 1 // Chép từ SM1[] vào M[]


B3: IF (I > SLen1)
Thực hiện B7
B4: M[I] = SM[I]
B5: I++


B6: Lặp lại B3


B7: SI = 1 // Chép từ SM2[] vào M[]


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

<b>3. Danh sách đặc (tt)</b>



<i><b>3.3. Các thao tác trên danh sách đặc (tt)</b></i>


3.3.9. Nhập nhiều danh sách thành 1 danh sách(tt)


int CD_Concat(T SM1[], int SLen1, T SM2[], int SLen2, T M [], int


&Len)


{


if (SLen1+SLen2 > MaxLen)
return (-1);


for (int I = 0; I < SLen1; I++)
M[I] = SM1[I];


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

22

<b>3. Danh sách đặc (tt)</b>



<i><b>3.3. Các thao tác trên danh sách đặc (tt)</b></i>


3.3.10. Sao chép 1 danh sách: Sao chép nội dung danh sách thành 1
danh sách khác có cùng chiều dài


Thuật toán
B1: I = 1


B2: IF (I > Length) // Length là chiều dài của dãy


B3: CM[I] = M[I]
B4: I++


B5: Lặp lại B2
BKT: Kết thúc


int CD_Copy(T M[], int Len, T CM[]) // Hàm trả về chiều dài của DS



{ for (int i=0; i< Len; i++)
CM[i] = M[i];


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

<b>3. Danh sách đặc (tt)</b>



<i><b>3.3. Các thao tác trên danh sách đặc (tt)</b></i>


3.3.11. Hủy danh sách


 Nếu danh sách được cấp phát động <sub></sub> dùng toán tử delete để


hủy.


 Nếu danh sách được cấp phát tĩnh, việc hủy bỏ chỉ có tác


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

24

<b>3. Danh sách đặc (tt)</b>



<i><b>3.4. Ưu nhược điểm và ứng dụng</b></i>


 Do phần tử được lưu trữ kề cập với nhau trong bộ nhớ, danh


sách đặc có các ưu điểm:


 Mật độ sử dụng danh sách là tối ưu tuyệt đối.


 Truy cập, tìm kiếm các phần tử là dễ dàng vì vị trí các phần
tử liền kề với nhau trong bộ nhớ.



 Nhược điểm của danh sách là khi thêm hay hủy 1 phần tử


trong danh sách cần dịch chuyển các phần tử cịn lại qua vị trí
khác.


 Được ứng dụng nhiều trong cấu trúc dữ liệu mảng (mảng 1


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

<b>4. </b>

<b>Danh sách liên kết (Linked List)</b>


<i><b>4.1. Định nghĩa</b></i>


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

26


<b>4. </b>

<b>Danh sách liên kết (tt)</b>


<i><b>4.1. Định nghĩa</b></i>


 Danh sách liên kết là tập hợp các phần tử mà giữa chúng có


một sự nối kết với nhau thông qua vùng liên kết của chúng.


 Tùy cách kết nối ràng buộc giữa những phần tử này và phần


tử khác, danh sách liên kết chia thành các loại khác nhau:
 Danh sách liên kết đơn


 Danh sách liên kết đôi/kép
 Danh sách đa liên kết


 Danh sách liên kết vòng (vòng đơn, vòng đơi)


 Mỗi loại danh sách có cách biểu diễn theo các cấu trúc dữ liệu



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

<i><b>4.2. Danh sách liên kết đơn (SLL)</b></i>



<i><b>4.2.1. Cấu trúc dữ liệu</b></i>


 Nội dung mỗi phần tử (nút) trong danh sách liên kết gồm 2


vùng <i><b>Vùng dữ liệu </b></i>và<i><b> Vùng liên kết</b></i>


struct Node
{ int info;


Node *pNext; // liên kết đến vùng của phần tử kế tiếp


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

28

<i><b>4.2. Danh sách liên kết đơn (tt)</b></i>



<i><b>4.2.1. Cấu trúc dữ liệu (tt)</b></i>


 Để quản lý danh sách liên kết có thể dùng <i>nhiều phương pháp </i>


khác nhau, mỗi phương pháp sẽ có cấu trúc dữ liệu cụ thể.
 <i>Quản lý địa chỉ phần đầu và cuối danh sách</i>


struct List
{


Node *pHead;
Node *pTail;
};



info pNext pTail


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

<i><b>4.2. Danh sách liên kết đơn (tt)</b></i>



<i><b>4.2.2. Các thao tác trên danh sách liên kết đơn</b></i>


a. Khởi tạo danh sách SLL


b. Tạo mới 1 phần tử (nút) trong danh sách SLL
c. Thêm 1 phần tử vào danh sách SLL


 Thêm vào đầu | cuối | giữa danh sách liên kết đơn


d. Duyệt qua các nút trong danh sách
e. Tìm kiếm phần tử trong danh sách
f. Hủy bỏ 1 phần tử trong danh sách
g. Hủy danh sách


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

30

<i><b>4.2. Danh sách liên kết đơn (tt)</b></i>



<i><b>4.2.2.</b></i>a. Khởi tạo danh sách SLL


 Thao tác khởi tạo danh sách liên kết đơn là cho giá trị con trỏ


quản lý địa chỉ đầu của danh sách về con trỏ NULL.


 Hàm khởi tạo danh sách liên kết đơn:



void <b>Khoitao</b>(Node *pHead)
{


pHead = NULL;
return;


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

<i><b>4.2. Danh sách liên kết đơn (tt)</b></i>



<i><b>4.2.2. </b></i>

b. Tạo mới 1 phần tử (nút) trong danh sách SLL



Giả sử tạo mới 1 phần tử có thành phần dữ liệu

=x


Thuật toán



B1: p = new Node //c

ấp phát bộ nhớ cho con trỏ p


B2: IF(p == NULL) // c

ấp phát không thành công


Thực hiện BKT


B3: p->info=x;



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

32

<i><b>4.2. Danh sách liên kết đơn (tt)</b></i>



<i><b>4.2.2. </b></i>b. Tạo mới 1 phần tử (nút) trong danh sách SLL (tt)
Cài đặt


Node* TaoPT(int x)
{ Node *p;



p=new Node;
if (p==NULL)


{ cout<<"Khong du bo nho";
exit(1);


}


cout<<"\nMoi nhap vao so x = ";
cin>>x;


p->Info=x;


p->pNext=NULL;
return p;


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

<i><b>4.2. Danh sách liên kết đơn (tt)</b></i>



<i><b>4.2.2.</b></i>c. Thêm 1 phần tử vào danh sách SLL (Thêm đầu DS)
Thuật toán


Gỉa sử ta muốn thêm phần tử p vào đầu DS:


Nếu DS rỗng thì:



pHead=p;



pTail=pHead; //

pTail=new_element



Ngược lại:




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

34

<i><b>4.2. Danh sách liên kết đơn (tt)</b></i>



<i><b>4.2.2.</b></i>c. Thêm 1 phần tử vào danh sách SLL (Thêm đầu DS) (tt)
Cài đặt


void Themdau(List &l, Node *p)
{


if (l.pHead==NULL)
{


l.pHead=p;
l.pTail=p;
}


else


{ p->pNext=l.pHead;
l.pHead=p;


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

<i><b>4.2. Danh sách liên kết đơn (tt)</b></i>



<i><b>4.2.2.</b></i>c. Thêm 1 phần tử vào danh sách SLL (Thêm đầu DS) (tt)


x


pHead


pTail


2


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

36

<i><b>4.2. Danh sách liên kết đơn (tt)</b></i>



<i><b>4.2.2.</b></i>

c. Thêm 1 phần tử vào danh sách SLL (tt) (Thêm


giữa DS)



Thêm phần tử mới vào ngay sau phần tử q



Thuật toán



Nếu q!=NULL;



B1: p->pNext=q->pNext;


B2: q->pNext=p



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

<i><b>4.2. Danh sách liên kết đơn (tt)</b></i>



<i><b>4.2.2.</b></i>c. Thêm 1 phần tử vào danh sách SLL (Thêm giữa DS) (tt)
Cài đặt:


void Themgiua(List &l, Node *q, int x)
{


Node *p=GetNode(x);


if (p==NULL) exit(1);
if (q!=NULL)



{


p->pNext=q->pNext;
q->pNext=p;


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

38

<i><b>4.2. Danh sách liên kết đơn (tt)</b></i>



<i><b>4.2.2.</b></i>c. Thêm 1 phần tử vào danh sách SLL (Thêm cuối DS)
Thuật toán:


Nếu DS rỗng thì:
B1: pHead=p;


B2: pTail=pHead;
Ngược lại:


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

<i><b>4.2. Danh sách liên kết đơn (tt)</b></i>



<i><b>4.2.2.</b></i>c. Thêm 1 phần tử vào danh sách SLL (Thêm cuối DS) (tt)
Cài đặt


void InsertTail(List &l, Node *p)
{


if (l.pHead==NULL)
{ l.pHead=p;


l.pTail=p;
}



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

40

<i><b>4.2. Danh sách liên kết đơn (tt)</b></i>



<i><b>4.2.2.</b></i>d. Duyệt qua các nút trong danh sách liên kết đơn


 Là thao tác thường dùng trong các loại danh sách.


 Tùy theo từng trường hợp cụ thể để xử lý trong khi duyệt DS.


Thuật toán:
B1: p = pHead


B2: IF (p == NULL)
Thực hiện BKT


B3: OutputData(p->info)
B4: p = p->pNext


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

<i><b>4.2. Danh sách liên kết đơn (tt)</b></i>



<i><b>4.2.2.</b></i>d. Duyệt qua các nút trong danh sách liên kết đơn (tt)
Cài đặt:


void DuyetDS(List l)



{

Node *p;



p = l.pHead;




while (p!=NULL)


{



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

42

<i><b>4.2. Danh sách liên kết đơn (tt)</b></i>



<i><b>4.2.2.</b></i>e. Tìm kiếm phần tử trong danh sách


 Giả sử cần tìm kiếm trong danh sách liên kết đơn phần tử có


phần dữ liệu X.


 Dùng thuật tốn tìm tuyến tính.


Thuật tốn
B1: p=pHead


B2: IF(p== NULL OR p->info == X)
Thực hiện BKT


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

<i><b>4.2. Danh sách liên kết đơn (tt)</b></i>



<i><b>4.2.2.</b></i>e. Tìm kiếm phần tử trong danh sách (tt)
Cài đặt


Node* Timkiem(List l, int x)



{

Node *p;



p=l.pHead;




while ((p!=NULL) && (p->Info!=x))


p=p->pNext;



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

44

<i><b>4.2. Danh sách liên kết đơn (tt)</b></i>



<i><b>4.2.2.</b></i>

f. Xoá 1 phần tử trong danh sách



Xoá đầu DS



Thuật tốn:



Nếu (PHead !=NULL) thì:


B1: p=pHead;



B2: pHead=pHead->pNext


free(p);



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

<i><b>4.2. Danh sách liên kết đơn (tt)</b></i>



<i><b>4.2.2.</b></i>f. Xoá1 phần tử trong danh sách
Xoá đầu DS


 Cài đặt:


void Xoadau(List &l) // xoa phan tu
{


p=new Node;


p=l.pHead;
if (p!=NULL)


{


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

46

<i><b>4.2. Danh sách liên kết đơn (tt)</b></i>



<i><b>4.2.2.</b></i>

f. Xoá1 phần tử trong danh sách



Xoá phần tử ngay sau phần tử q:



Thuật toán:



nếu q!=NULL thì



B1: p=q->pNext; //p là phần tử cần huỷ



B2: nếu (p!=NULL) thì //q khơng phải cuối DS


B21: q->pNext=p->pNext;



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

<i><b>4.2. Danh sách liên kết đơn (tt)</b></i>



<i><b>4.2.2.</b></i>f. Xoá1 phần tử trong danh sách


Xoá phần tử ngay sau phần tử q:


void XoaPT(List &l, Node *q)
{



if (q!=NULL)
{


p=q->pNext;// p la phan tu can xoa
if (p!=NULL)


if(p==l.pTail)


{ l.pTail=q;
free(p);
}


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

48

<i><b>4.2. Danh sách liên kết đơn (tt)</b></i>



<i><b>4.2.2.</b></i>

f. Xoá1 phần tử trong danh sách



Xoá phần tử có khố k:



Thuật tốn:



B1: Tìm phần tử p có khố k và phần tử q đứng trước




B2: Nếu (p!=NULL) thì //tìm thấy k


Xố p ra khỏi DS



Ngược lại:



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

<i><b>4.2. Danh sách liên kết đơn (tt)</b></i>




<i><b>4.2.2.</b></i>f. Xố1 phần tử trong danh sách


Xố phần tử có khoá k:


Cài đặt:


int XoaptK(List &l,int k) // xoa phan tu
{


Node *p=l.pHead;
Node *q=NULL;
while (p!=NULL)


{ if(p->info==k) break;
q=p; p=p->pNext;
}


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

50

<i><b>4.2. Danh sách liên kết đơn (tt)</b></i>



<i><b>4.2.2.</b></i>f. Xoá1 phần tử trong danh sách
Xố phần tử có khố k:


Cài đặt: (tt)
else


{


l.pHead=p->pNext;


if(l.pHead==NULL)
l.pTail=NULL;


}


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

<i><b>4.2. Danh sách liên kết đơn (tt)</b></i>



<i><b>4.2.2.</b></i>

g. Hủy danh sách



Việc hủy danh sách thực chất là thực hiện nhiều lần



hủy 1 nút



Thuật toán:



B1: Trong khi DS chưa hết


p=pHead;



pHead=pHead->pNext;


B2: Huỷ p



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

52

<i><b>4.2. Danh sách liên kết đơn (tt)</b></i>



<i><b>4.2.2.</b></i>g. Hủy danh sách (tt)
Cài đặt thuật toán:


void XoaDs (List &l)
{



while (l.pHead!= NULL)
{


p = l.pHead;


l.pHead = p->pNext;
delete (p);


}


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

<i><b>4.2. Danh sách liên kết đơn (tt)</b></i>



<i><b>4.2.2.</b></i>h. Tạo mới danh sách/Nhập danh sách


 Tạo mới 1 danh sách thực chất là liên tục thêm 1 phần tử vào


danh sách mà danh sách ban đầu là rỗng.


 Tạo DS bằng cách thêm vào đầu DS


void TaoDSdau(List &l, int x)
{


for (int i=0;i<8;i++) // nen dung vong lap do while de viet
{


TaoPT(x);


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

54

<i><b>4.2. Danh sách liên kết đơn (tt)</b></i>




Tạo DS bằng cách thêm vào cuối DS



void TaoDScuoi(List &l, int x)


{



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


{



TaoPT(x);



Themcuoi(l,p);


}



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

<i><b>4.2. Danh sách liên kết đơn (tt)</b></i>



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

56

<i><b>4.2. Danh sách liên kết đơn (tt)</b></i>



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

<i><b>4.2. Danh sách liên kết đơn (tt)</b></i>



<i><b>4.2.2.</b></i>k. Sắp xếp thứ tự các phần tử trong danh sách
Thuật toán sắp xếp trộn tự nhiên:


B1: IF (SLLSplit(SLList, TempList) == NULL) Thực hiện BKT
B2: SLLMerge(SLList, TempList, SLList)


B3: Lặp lại B1
BKT: Kết thúc



void SLLNaturalMergeSort(SLLType &SList)
{ SLLType TempList = NULL, List = NULL;


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

58

<i><b>4.2. Danh sách liên kết đơn (tt)</b></i>



<i><b>4.2.2.</b></i>h. Sao chép 1 danh sách


 Sao chép 1 danh sách thực chất là tạo mới danh sách


NewList bằng cách duyệt qua các nút của SLList để lấy thành
phần dữ liệu để tạo thành 1 nút mới & <i>bổ sung</i> nút mới này
vào danh sách NewList.


Thuật toán


B1: NewList = NULL
B2: CurrNode = SLList


B3: IF (CurNode = NULL) Thực hiện BKT
B4: SLLAddLast(NewList, CurrNode->Key)
B5: CurrNode = CurrNode->NextNode


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

<i><b>4.2. Danh sách liên kết đơn (tt)</b></i>



<i><b>4.2.2.</b></i>h. Sao chép 1 danh sách (tt)
Cài đặt thuật toán:


SLLType SLLCopy(SLLType SList, SLLType &NewList)
{ NewList = NULL;



SLLType CurrNode = SList;
while (CurrNode != NULL)


{ SLLType NewNode=SLLAddLast(NewList,CurrNode->Key);
if (NewNode == NULL)


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

60

<b>4.3. Danh sách liên kết đôi (DLL)</b>



 Các phần tử của danh sách liên kết đơi có 2 mối liên kết với


các phần tử khác trong danh sách.


 Cấu trúc dữ liệu của danh sách liên kết đôi:


typedef struct DLLNode
{ T Key;


InfoType Info;


DLLNode * NextNode;
DLLNode * PreNode;
} DLLOneNode;


typedef struct DLLNode
{ T Key;


DLLNode * NextNode;
DLLNode * PreNode;


} DLLOneNode;


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

<b>4.3. Danh sách liên kết đôi (tt)</b>


4.3.1. Quản lý danh sách liên kết liên kết đôi:


 Quản lý địa chỉ phần tử đầu của danh sách


DLLType DLList1


 Quản lý địa chỉ phần tử đầu và phần tử cuối của danh sách


typedef struct DLLPairNode
{ DLLType DLLFirst;


DLLType DLLLast;
} DLLPType;


DLLPType DLList2;


 Quản lý địa chỉ phần tử đầu, phần tử cuối và số phần tử của


danh sách


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

62

<b>4.3. Danh sách liên kết đôi (tt)</b>



4.3.2. Thao tác trên danh sách liên kết đôi


a. Khởi tạo danh sách liên kết đôi
b. Tạo mới 1 phần tử



c. Thêm 1 phần tử vào danh sách


d. Duyệt qua các nút trong 1 danh sách
e. Tìm kiếm 1 phần tử trong danh sách
f. Loại bỏ 1 phần tử trong danh sách
g. Hủy toàn bộ danh sách


h. Tạo 1 danh sách mới/Nhập danh sách
i. Tách 1 danh sách thành nhiều danh sách
j. Nhập nhiều danh sách thành 1 danh sách


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

<b>4.3. Danh sách liên kết đôi (tt)</b>


4.3.2.a. Khởi tạo danh sách liên kết đôi


Cho giá trị các con trỏ quản lý địa chỉ 2 nút đầu và cuối danh sách
liên kết đôi về NULL


DLLPType DLLInitialize(DLLPType &DList)
{


DList.DLLFirst = NULL;
DList.DLLast = NULL;
return (DList);


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

64

<b>4.3. Danh sách liên kết đôi (tt)</b>



4.3.2.b. Tạo mới 1 phần tử



Tạo nút mới có thành phần dữ liệu là NewData
Thuật toán


B1: Dnode = New DLLOneNode
B2: IF (Dnode == NULL)


Thực hiện BKT


B3: DNode ->NextNode = NULL
B4: DNode ->Key = NewData
B5: DNode ->PreNode = NULL
BKT: Kết thúc


DLLType DLLCreateNode(T NewData)
{ DLLType Pnode = new DLLOneNode;


if (Pnode != NULL)


{ Pnode ->NextNode = NULL;
Pnode ->Key = NewData


Pnode ->PreNode = NULL;
}


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

<b>4.3. Danh sách liên kết đôi (tt)</b>


4.3.2.c. Thêm 1 phần tử vào danh sách (Thêm đầu)
B1: NewNode = DLLCreateNode(NewData)


B2: IF (NewNode == NULL)
Thực hiện BKT



B3: IF(DLLList.DLLFirst == NULL)


B3.1: DLLList.DLLFirst = NewNode
B3.2: DLLList.DLLLast = NewNode
B3.3: Thực hiện BKT


B4: NewNode ->NextNode = DLLList.DLLFirst
B5: DLLList.DLLFirst ->PreNode = NewNode


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

66

<b>4.3. Danh sách liên kết đôi (tt)</b>



4.3.2.c. Thêm 1 phần tử vào danh sách (Thêm đầu)
DLLType DLLAddFirst(DLLPType &DList, T NewData)
{


DLLType NewNode = DLLCreateNode(NewData);
if (NewNode == NULL)


return (NULL);


if (DList.DLLFirst == NULL)


DList.DLLFirst = DList.DLLLast = NewNode;
else


{


NewNode ->NextNode = DList.DLLFirst;


DList.DLLFirst ->PreNode = NewNode;
DList.DLLFirst = NewNode;


}


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

<b>4.3. Danh sách liên kết đôi (tt)</b>


4.3.2.c. Thêm 1 phần tử vào danh sách (Thêm cuối)
B1: NewNode = DLLCreateNode(NewData)


B2: IF (NewNode == NULL)
Thực hiện BKT


B3: IF(DLLList.DLLFirst == NULL)


B3.1: DLLList.DLLFirst = NewNode
B3.2: DLLList.DLLLast = NewNode
B3.3: Thực hiện BKT


B4: DLLList.DLLLast ->NextNode = NewNode
B5: NewNode ->PreNode = DLLList.DLLLast


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

68

<b>4.3. Danh sách liên kết đôi (tt)</b>



4.3.2.c. Thêm 1 phần tử vào danh sách (Thêm cuối)
DLLType DLLAddLast(DLLPType &DList, T NewData)
{


DLLType NewNode = DLLCreateNode(NewData);
if (NewNode == NULL)



return (NULL);


if (DList.DLLLast == NULL)


DList.DLLFirst = DList.DLLLast = NewNode;
else


{


DList.DLLLast ->NextNode = NewNode;
NewNode ->PreNode = DList.DLLLast;
DList.DLLLast = NewNode;


}


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

<b>4.3. Danh sách liên kết đôi (tt)</b>


4.3.2.c. Thêm 1 phần tử vào danh sách (Thêm giữa)
B1: IF (InsNode ->NextNode == NULL)


B1.1: DLLAddLast(DLLList, NewData)
B1.2: Thực hiện BKT


B2: NewNode = DLLCreateNode(NewData)
B3: IF (NewNode == NULL)


Thực hiện BKT


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

70

<b>4.3. Danh sách liên kết đôi (tt)</b>




4.3.2.c. Thêm 1 phần tử vào danh sách (Thêm giữa)


DLLType DLLAddMid(DLLPType &DList, T NewData, DLLType
&InsNode)


{ DLLType NewNode = DLLCreateNode(NewData);
if (NewNode == NULL)


return (NULL);


if (InsNode ->NextNode == NULL)


{ InsNode ->NextNode = NewNode;
NewNode ->PreNode = InsNode;
DList.DLLLast = NewNode;


}
else


{ NewNode ->NextNode = InsNode ->NextNode;
InsNode ->NextNode ->PreNode = NewNode;
InsNode ->NextNode = NewNode;


NewNode ->PreNode = InsNode;
}


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

<b>4.3. Danh sách liên kết đôi (tt)</b>


4.3.2.d. Duyệt qua các nút trong 1 danh sách



Thuật toán


B1: CurrNode = DLLList.First
B2: IF (CurrNode == NULL)


Thực hiện BKT


B3: OutputData(CurrNode->Key)


B4: CurrNode = CurrNode ->NextNode
B5: Lặp lại B2


BKT: Kết thúc


Cài đặt thuật toán


void DLLTravelling (DLLPType DList)
{ DLLType CurrNode = DList.DLLFirst;


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

72

<b>4.3. Danh sách liên kết đơi (tt)</b>



4.3.2.e. Tìm kiếm 1 phần tử trong danh sách
Thuật toán


B1: CurrNode = DLLList.First


B2: IF (CurrNode == NULL OR CurrNode->Key = SearchData)
Thực hiện BKT



B3: CurrNode = CurrNode ->NextNode
B4: Lặp lại B2


BKT: Kết thúc


Cài đặt thuật toán


DLLType DLLSearching(DLLPType Dlist, T SearchData)
{ DLLType CurrNode = DList.DLLFirst;


while (CurrNode != NULL)


{ if (CurrNode->Key == SearchData)
break;


CurrNode = CurrNode ->NextNode
}


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

<b>4.3. Danh sách liên kết đôi (tt)</b>


4.3.2.f. Loại bỏ 1 phần tử trong danh sách


Thuật tốn


B1: DelNode = DLLSearching(DLLList. DelData) // Tìm kiếm nút DelData
B2: IF(DelNode == NULL)


Thực hiện BKT


B3: IF(DelNode->PreNode=NULL AND DelNode->NextNode=NULL)
B3.1: DLLList.DLLFirst = DLLList.DLLLast = NULL



B3.2: Thực hiện B8


B4: IF (DelNode ->PreNode = NULL) // Loại nút đầu tiên trong DS
B4.1: DLLList.DLLFirst = DLLList.DLLFirst ->NextNode


B4.2: DLLList.DLLFirst ->PreNode = NULL
B4.3: Thực hiện B8


B5: IF (DelNode ->NextNode = NULL) // Loại nút cuối trong DS
B4.1: DLLList.DLLLast = DLLList.DLLLast ->PreNode
B4.2: DLLList.DLLLast ->NextNode = NULL


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

74

<b>4.3. Danh sách liên kết đôi (tt)</b>



4.3.2.f. Loại bỏ 1 phần tử trong danh sách
Cài đặt thuật toán


Int DLLDeleteNode (DLLPType &DList, T DelData)


{ DLLType DelNode = DLLSearching(DList, DelData)
if (DelNode == NULL)


return (-1);


if (DelNode ->NextNode == NULL && DelNode ->PreNode == NULL)
DList.DLLFirst = DList.DLLLast = NULL;


else



if (DelNode ->PreNode ==NULL)


{ DList.DLLFirst = Dist.DLLFirst ->NextNode ;
Dist.DLLFirst ->PreNode = NULL;


}
else


if (DelNode ->NextNode ==NULL)


{ DList.DLLLast = Dist.DLLLast ->PreNode ;
Dist.DLLLast ->NextNode = NULL;


}
else


{ DelNode ->PreNode ->NextNode = DelNode ->NextNode;
DelNode ->NextNode ->PreNode = DelNode ->PreNode ;
}


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

<b>4.3. Danh sách liên kết đôi (tt)</b>


4.3.2.g. Hủy toàn bộ danh sách


Thực hiện nhiều lần thao tác hủy một nút
Thuật toán


B1: IF (DLLList.DLLFirst == NULL)
Thực hiện BKT



B2: TempNode = DLLList.DLLFirst


B3: DLLList.DLLFirst = DLLList.DLLFirst ->NextNode
B4: IF (DLLList.DLLFirst == NULL)


B4.1: DLLList.DLLLast = NULL
B4.2: Thực hiện B7


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

76

<b>4.3. Danh sách liên kết đơi (tt)</b>



4.3.2.g. Hủy tồn bộ danh sách (tt)
Cài đặt thuật toán


void DLLDelete (DLLPType &DList)
{


DLLType TempNode = DList.DLLFirst;
while (TempNode != NULL)


{


DList.DLLFirst = DList.DLLFirst ->NextNode;
TempNode ->NextNode = NULL;


if (DList.DLLFirst != NULL)


DList.DLLFirst ->PreNode = NULL;
delete TempNode;



TempNode = DList.DLLFirst;
}


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

<b>4.3. Danh sách liên kết đôi (tt)</b>


4.3.2.h. Tạo 1 danh sách mới/Nhập danh sách


Thuật toán


B1: DLLInitialize(DLLList)
B2: I = 1


B3: IF (I >N)


Thực hiện BKT


B4: NewData = InputNewData();


B5: DLLAddLast(DLLList, NewData)
B6: I++


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

78

<b>4.3. Danh sách liên kết đôi (tt)</b>



4.3.2.h. Tạo 1 danh sách mới/Nhập danh sách
Cài đặt thuật toán


DLLPType DLLCreate (DLLPType &DList, int N)
{


DLLInitialize(DList);


T NewData;


for (int i=0; i <N; i++)
{


NewData = InputNewData();


if (DLLAddLast(DList, NewData) == NULL)
{ DLLDelete(DList);


break;
}


}


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

80

<b>4.3. Danh sách liên kết đôi (tt)</b>



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

<b>4.3. Danh sách liên kết đôi (tt)</b>



4.3.2.k. Sắp xếp thứ tự thành phần dữ liệu trong danh sách
B1: Inode = DLLList.DLLFirst


B2: IF(Inode == NULL)
Thực hiện BKT


B3: IF (Inode == DLLList.DLLLast)
Thực hiện BKT


B4: Jnode = DLLList.DLLLast


B5: IF (Jnode = Inode)


Thực hiện B7
B6: ELSE


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

82

<b>4.3. Danh sách liên kết đôi (tt)</b>



4.3.2.k. Sắp xếp thứ tự thành phần dữ liệu trong danh sách (tt)
Cài đặt thuật toán


void DLLBubbleSort (DLLPType &DList)
{ DLLType Inode = DList.DLLFirst;


if (Inode == NULL)
return;


while (Inode != DList.DLLLast)


{ DLLType Jnode = DList.DLLLast;
while (Jnode != Inode)


{ if (Jnode->Key < Jnode ->PreNode ->Key)


Swap(Jnode->Key,Jnode->PreNode->Key)
Jnode = Jnode ->PreNode ;


}


Inode = Inode ->NextNode ;


}


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

<b>4.3. Danh sách liên kết đôi (tt)</b>


4.3.2.l. Sao chép 1 danh sách thành 1 danh sách mới
Thuật toán


B1: DLLInitialize(NewList)


B2: CurrNode = DLLList.DLLFirst
B3: IF (CurrNode == NULL)


Thực hiện BKT


B4: DLLAddLast(NewList, CurrNode->Key)
B5: CurrNode = CurrNode ->NextNode


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

84

<b>4.3. Danh sách liên kết đôi (tt)</b>



4.3.2.l. Sao chép 1 danh sách thành 1 danh sách mới
Cài đặt thuật toán


DLLPType DLLCopy(DLLPType &DList, DLLPType &NewList)
{


DLLInitialize(NewList);


DLLType CurrNode = DList.DLLFirst;
while (CurrNode != NULL)



{


if (DLLAddLast(NewList, CurrNode->Key) == NULL)
{ DLLDelete(NewList);


break;
}


CurrNode = CurrNode ->NextNode ;
}


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

<b>4. </b>

<b>Danh sách liên kết</b>



<i><b>4.4. Ưu nhược điểm của danh sách liên kết</b></i>


 Nhược điểm


 Mật độ sử dụng bộ nhớ của danh sách liên kết không tối
ưu tuyệt đối (<100%)


 Việc truy xuất và tìm kiếm các phần tử trong danh sách liên
kết mất nhiều thời gian vì phải duyệt tuần tự qua các phần
tử trong danh sách.


 Bộ nhớ cần nhiều vì phải lưu thêm phần tử liên kết, nếu
vùng dữ liệu là lớn thì tỷ lệ mức sử dụng bộ nhớ là cao.


 Ưu điểm


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

86


<b>5. Danh sách hạn chế</b>



<i><b>5.1. Hàng đợi (Queue)</b></i>
<i><b>5.2. Ngăn xếp (Stack)</b></i>


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

<b>5. Danh sách hạn chế</b>



<i><b>5.1. Hàng đợi (Queue)</b></i>


 Hàng đợi là một danh sách mà trong đó thao tác thêm 1 phần


tử vào trong danh sách được thực hiện 1 đầu này và lấy 1
phần tử trong danh sách lại thực hiện bởi đầu kia.


 Các phần tử đưa vào trong hàng đợi trước sẽ được lấy ra


trước, phần tử đưa vào trong hàng đợi sau sẽ được lấy ra
sau.


 Hàng đợi còn được gọi là danh sách FIFO List và cấu trúc dữ


liệu này còn được gọi cấu trúc FIFO (First In First Out)


 Có nhiều cách biểu diễn hàng đợi: dùng <i>danh sách đặc</i> hoặc


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

88

<i><b>5.1. Hàng đợi (tt)</b></i>



<i><b>5.1.1. Cấu trúc dữ liệu biểu diễn cho hàng đợi</b></i>



 Biểu diễn và tổ chức hàng đợi bằng danh sách đặc và danh


sách liên kết đơn được quản lý bởi 2 phần tử đầu và cuối


 Cấu trúc dữ liệu biểu diễn hàng đợi bằng danh sách đặc


typedef struct QC
{ int Len;


int Front, Rear;
T * List;


} CQUEUE;


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

<i><b>5.1. Hàng đợi (tt)</b></i>



<i><b>5.1.1. Cấu trúc dữ liệu biểu diễn cho hàng đợi (tt)</b></i>


Cấu trúc dữ liệu biểu diễn hàng đợi bằng danh sách liên kết
typedef struct QElement


{ T Key;


QElement *Next;
} QOneElement;


typedef QElement *QType;
typedef struct QPElement
{ QType Font;



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

90

<i><b>5.1. Hàng đợi (tt)</b></i>



<i><b>5.1.2. Các thao tác trên hàng đợi tổ chức bằng </b><b>danh sách đặc</b></i>


a. Khởi tạo hàng đợi (Initialize)


b. Thêm 1 phần tử vào hàng đợi (Add)


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

<i><b>5.1. Hàng đợi (tt)</b></i>



<i><b>5.1.2.a. Khởi tạo hàng đợi (tổ chức bằng </b><b>danh sách đặc</b><b>)</b></i>


B1: CQList.Len = Length


B2: CQList.List = new T[Length]
B3: IF(CQList.List == NULL)


Thực hiện BKT


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

92

<i><b>5.1. Hàng đợi (tt)</b></i>



<i><b>5.1.2.a. Khởi tạo hàng đợi (tổ chức bằng </b><b>danh sách đặc</b><b>)</b></i>


Cài đặt thuật toán


T * CQInitialize (CQUEUE & QList, int Length)
{



QList.Len = Length;


QList.List = new T[Length];
if (QList.List == NULL)


return (NULL);


QList.Front = QList.Rear =-1;
return (QList.List);


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

<i><b>5.1. Hàng đợi (tt)</b></i>



<i><b>5.1.2.b. Thêm 1 phần tử vào hàng đợi (tổ chức bằng </b><b>danh sách đặc</b><b>)</b></i>


Thuật toán


// nếu hàng đợi đã bị đầy


B1: IF(CQList.Front ==1 AND CQList.Rear == CQList.Len)
Thực hiện BKT


B2: IF(CQList.Rear+1 == CQList.Front)
Thực hiện BKT


B3: IF(CQList.Front = 0) // nếu hàng đợi rỗng
CQList.Front = 1


B4: IF(CQList.Rear = CQList.Len)
CQList.Rear = 1



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

94

<i><b>5.1. Hàng đợi (tt)</b></i>



<i><b>5.1.2.b. Thêm 1 phần tử vào hàng đợi (tổ chức bằng </b><b>danh sách đặc</b><b>)</b></i>


Cài đặt thuật toán


int CQAdd(CQUEUE & QList, T NewData)


{ if (QList.Front == 0 && QList.Rear == QList.Len -1)
return (-1);


if (QList.Rear +1 == QList.Front)
return (-1);


if (QList.Front == -1)
QList.Front =0


if (QList.Rear == QList.Len)
QList.Rear = 0;


else


QList.Rear += 1;


QList.List[QList.Rear] = NewData
return (QList.Rear );


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

<i><b>5.1. Hàng đợi (tt)</b></i>




<i><b>5.1.2.c. Lấy nội dung 1 phần tử trong hàng đợi ra xử lý (tổ </b></i>
<i><b>chức bằng </b><b>danh sách đặc</b><b>)</b></i>


B1: IF (CQList.Front = 0)
Thực hiện BKT


B2: Data = CQList.List[CQList.Front]
B3: IF(CQList.Rear == CQList.Front)


B3.1: CQList.Rear = CQList.Front = 0
B3.2: Thực hiện BKT


B4: IF (CQList.Front = CQList.Len)
CQList.Front = 1


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

96

<i><b>5.1. Hàng đợi (tt)</b></i>



<i><b>5.1.2.c. Lấy nội dung 1 phần tử trong hàng đợi ra xử lý (tổ chức bằng </b></i>


<i><b>danh sách đặc</b><b>)</b></i>


Cài đặt thuật toán


int CQGet(CQUEUE & QList, T &Data)


{ if (QList.Front == -1)


return (-1);



Data = QList.List[QList.Front];
if (QList.Front == QList.Rear)
{ QList.Front = QList.Rear = -1;
return (1);


}


if (QList.Front == QList.Len -1)
QList.Front = 0;


else


QList.Front += 1;
return (1);


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

<i><b>5.1. Hàng đợi (tt)</b></i>



<i><b>5.1.2.d. Hủy hàng đợi (tổ chức bằng </b><b>danh sách đặc</b><b>)</b></i>


Hủy bộ nhớ cấp phát cho hàng đợi
void CQDelete(CQUEUE & QList)
{


delete QList.List;
return;


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

98

<i><b>5.1. Hàng đợi (tt)</b></i>



<i><b>5.1.3. Các thao tác trên hàng đợi tổ chức bằng </b><b>danh sách liên </b></i>


<i><b>kết đơn</b></i>


a. Khởi tạo hàng đợi (Initialize)


b. Thêm 1 phần tử vào hàng đợi (Add)


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

<i><b>5.1. Hàng đợi (tt)</b></i>



<i><b>5.1.3.a. Khởi tạo hàng đợi (dùng </b><b>danh sách liên kết đơn</b><b>)</b></i>


Tương tự với danh sách liên kết đơn, hàm khởi tạo thực hiện gán
con trỏ Front và Rear về NULL


SQUEUE SQInitialize (SQUEUE &QList)
{


QList.Front = QList.Rear = NULL;
return (QList);


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

100

<i><b>5.1. Hàng đợi (tt)</b></i>



<i><b>5.1.3.b. Thêm 1 phần tử vào hàng đợi (dùng </b><b>danh sách liên kết </b></i>
<i><b>đơn</b><b>)</b></i>


Thêm phần tử vào sau phần tử Rear (Thêm vào cuối danh sách
liên kết)


Giả sử dữ liệu đưa vào hàng đợi là NewData
B1: NewElement = SLLCreateNode(NewData)


B2: IF (NewElement == NULL)


Thực hiện BKT


B3: IF (SQList.Front == NULL) // hàng đợi dang rỗng
B3.1: SQList.Front = SQList.Rear = NewElement
B3.2: Thực hiện BKT


B4: SQList.Rear->Next = NewElement
B5: SQList.Rear = NewElement


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

<i><b>5.1. Hàng đợi (tt)</b></i>



<i><b>5.1.3.b. Thêm 1 phần tử vào hàng đợi (dùng </b><b>danh sách liên kết đơn</b><b>)</b></i>


Cài đặt thuật toán:


QType SQAdd(SQUEUE &Qlist, T NewData)


{ QType NewElement = SLLCreateNode(NewData)
if (NewElement == NULL)


return (NULL);


if (QList.Front == NULL)


QList.Front = QList.Rear = NewElement;
else


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

102


<i><b>5.1. Hàng đợi (tt)</b></i>



<i><b>5.1.3.c. Lấy nội dung 1 phần tử trong hàng đợi ra xử lý (dùng </b></i>


<i><b>danh sách liên kết đơn</b><b>)</b></i>


Lấy nội dung thành phần dữ liệu của phần tử ở địa chỉ Front ra
biến Data và tiến hành hủy phần tử này


B1: IF (SQList.Front == NULL) // nếu hàng đợi bị rỗng
Thực hiện BKT


B2: TempElement = SQList.Front;


B3: SQList.Front = SQList.Front ->Next
B4: TempElement ->Next = NULL


B5: Data = TempElement ->Key
B6: IF (SQList.Front == NULL)


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

<i><b>5.1. Hàng đợi (tt)</b></i>



<i><b>5.1.3.c. Lấy nội dung 1 phần tử trong hàng đợi ra xử lý (dùng </b><b>danh </b></i>
<i><b>sách liên kết đơn</b><b>) </b></i>Cài đặt thuật toán


int SQGet (SQUEUE &QList, T &Data)
{ if (QList.Front = NULL)


return (-1);



QType TempElement = QList.Front;
QList.Front = QList.Front ->Next;
TempElement ->Next = NULL;
Data = TempElement ->Next ;
if (QList.Front = NULL)


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

104

<i><b>5.1. Hàng đợi (tt)</b></i>



<i><b>5.1.3.d. Hủy hàng đợi (dùng </b><b>danh sách liên kết đơn</b><b>)</b></i>


void SQQueue (SQUEUE &QList)
{


QList.Rear = NULL;


while (QList.Front != NULL)
{


QType TempElement = QList.Front;
TempElement ->Next = NULL;


delete TempElement;
}


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

<i><b>5.2. Ngăn xếp (Stack)</b></i>



Ngăn xếp là một danh sách mà trong đó thao tác trên 1 phần tử
vào trong ngăn xếp và thao tác lấy ra một phần tử được thực
hiện 1 đầu.



Các phần tử được đưa vào ngăn xếp sau cùng sẽ được lấy ra
trước tiên, phần tử được đưa vào trước tiên sẽ được lấy ra
sau cùng.


Ngăn xếp được gọi là danh sách vào sau ra trước LIFO, cấu trúc
dữ liệu này được gọi là cấu trúc LIFO.


<i>5.2.1. Cấu trúc dữ liệu</i>


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

106

<i><b>5.2. Ngăn xếp (tt)</b></i>



<i>5.2.1. Cấu trúc dữ liệu</i>


Biểu diễn và tổ chức bằng danh sách đặc
typedef struct SC


{ int Size;
int SP;
T * List;
} CSTACK;


CSTACK CSList;


Biểu diễn và tổ chức bằng danh sách liên kết
typedef struct SElement


{ T Key;



SElement *Next;


} SOneElement;


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

<i><b>5.2. Ngăn xếp (tt)</b></i>



<i>5.2.2. Các thao tác trên ngăn xếp tổ chức bằng danh sách đặc</i>
<i>5.2.2.a. Khởi tạo ngăn xếp (Initialize)</i>


<i>5.2.2.b. Thêm 1 phần tử vào ngăn xếp (Push)</i>


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

108

<i><b>5.2. Ngăn xếp (tt)</b></i>



<i>5.2.2.a. Khởi tạo ngăn xếp (dùng danh sách đặc)</i>


B1: CSList.Size = MaxSize


B2: CSList.List = new T[MaxSize]
B3: IF (CSList.List == NULL)


Thực hiện BKT


B4: CSList.SP = CSList.Size +1
BKT: Kết thúc


T * CSInitialize(CSTACK &SList, int MaxSize)
{ SList.Size = MaxSize;


SList.List = new T[MaxSize];


if (SList.List == NULL)


return (NULL);


SList.SP = SList.Size ;
return (SList.List);


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

<i><b>5.2. Ngăn xếp (tt)</b></i>



<i>5.2.2.b. Thêm 1 phần tử vào ngăn xếp (dùng danh sách đặc)</i>


B1: IF (CSList.SP == 1)
Thực hiện BKT


B2: CSList.SP


--B3: CSList.List[CSList.SP] = NewData
BKT: Kết thúc


int CSPush(CSTACK &SList, T NewData)
{ if (SList.SP == 0)


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

110

<i><b>5.2. Ngăn xếp (tt)</b></i>



<i>5.2.2.c. Lấy nội dung 1 phần tử trong ngăn xếp ra xử lý (dùng danh sách </i>
<i>đặc)</i>


B1: IF (CSList.SP == CSList.Size +!)
Thực hiện BKT



B2: Data = CSList.List[CSList.SP]
B3: CSList.SP++


BKT: Kết thúc


int CSPop(CSTACK &SList, T &Data)
{ if (SList.SP == SList.Size)


return (-1);


Data = SList.List[SList.SP];
SList.SP += 1;


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

<i><b>5.2. Ngăn xếp (tt)</b></i>



<i>5.2.2.d. Hủy ngăn xếp (dùng danh sách đặc)</i>


int CSDelete(CSTACK &SList)
{


delete SList.SList;
return;


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

112

<i><b>5.2. Ngăn xếp (tt)</b></i>



<i>5.2.2. Các thao tác trên ngăn xếp tổ chức bằng danh sách liên kết</i>
<i>5.2.3.a. Khởi tạo ngăn xếp (Initialize)</i>



<i>5.2.3.b. Thêm 1 phần tử vào ngăn xếp (Push)</i>


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

<i><b>5.2. Ngăn xếp (tt)</b></i>



<i>5.2.3.a. Khởi tạo ngăn xếp (dùng danh sách liên kết)</i>


SSTACK SSInitialize (SSTACK &SList)
{ SList = NULL;


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

114

<i><b>5.2. Ngăn xếp (tt)</b></i>



<i>5.2.3.b. Thêm 1 phần tử vào ngăn xếp (dùng danh sách liên kết)</i>


B1: NewElement = SLLCreateNode(NewData)
B2: if (NewElement == NULL)


Thực hiện BKT
B3: if (SSP == NULL)


B3.1: SSP = NewElement
B3.2: Thực hiện BKT


B4: NewElement ->Next = SSP
B5: SSP = NewElement


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

<i><b>5.2. Ngăn xếp (tt)</b></i>



<i>5.2.3.b. Thêm 1 phần tử vào ngăn xếp (dùng danh sách liên kết)</i>



SSTACK SSPush (SSTACK &SList, T NewData)


{ SSTACK NewElement = SLLCreateNode(NewData);
if (NewElement == NULL)


return (NULL);


NewElement ->Next = SList;
SList = NewElement;


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

116

<i><b>5.2. Ngăn xếp (tt)</b></i>



<i>5.2.3.c. Lấy nội dung 1 phần tử trong ngăn xếp ra xử lý (dùng </i>
<i>danh sách liên kết)</i>


B1: if (SSP == NULL)
Thực hiện BKT


B2: TempElement = SSP
B3: SSP = SSP ->Next


B4: TempElement ->Next = NULL
B5: Data = TempElement->Key
B6: delete


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

<i><b>5.2. Ngăn xếp (tt)</b></i>



<i>5.2.3.c. Lấy nội dung 1 phần tử trong ngăn xếp ra xử lý (dùng </i>
<i>danh sách liên kết)</i>



int SSPop (SSTACK &SList, T &Data)
{


if (SList == NULL)
return (-1);


SSTACK TempElement = SList;
SList = SList ->Next;


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

118

<i><b>5.2. Ngăn xếp (tt)</b></i>



<i>5.2.3.d. Hủy ngăn xếp (dùng danh sách liên kết)</i>


void SSDelete (SSTACK &SList)
{


while (SList != NULL)


{ SSTACK TempElement = SList;
SList = SList ->Next;


TempElement ->Next = NULL;
delete TempElement;


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

<i><b>5.2. Ngăn xếp (tt)</b></i>



<i><b>5.3. Ứng dụng của danh sách hạn chế</b></i>



 Hàng đợi dùng trong nhiều trường hợp lưu trữ dữ liệu cần xử


lý tuần tự.


 Ngăn xếp dùng trong việc xử lý dữ liệu truy hồi, đặc biệt trong


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

120

<b>BÀI TẬP CHƯƠNG 4</b>



 Bài tập chương 4, giáo trình Cấu trúc dữ liệu và giải thuật


</div>

<!--links-->

×