Giáo trình Cấu trúc dữ liệu
Trong ngôn ngữlập trình, dữliệu bao gồm hai kiểu chính là :
- Kiểu dữliệu đơn giản : char, int, long, float,enumeration, subrange.
- Kiểu dữliệu có cấu trúc : struct, array, file (kiểu dữliệu có kích thước
không đổi).
Giáo trình này tập trung vào việc nghiên cứu các kiểu dữliệu có cấu trúc
có kích thước không đổi hoặc thay đổi trong ngôn ngữlập trình, môtảthông qua
ngôn ngữC. Ngoài ra còn giới thiệu các giải thuật chung quanh các cấu trúcdữ
liệu này nhưcách tổchức, thực hiện các phép toán tìmkiếm, sắp thứtựnội, sắp
thứtựngoại.
Điều kiện đểcó thểtìm hiểu rõ ràng vềmôn học này là học viên đã biết
các khái niệm vềkỹthuật lập trình trên ngôn ngữC. Trong phần mở đầu, bài
giảng này sẽgiới thiệu cách thức phân tích & thiết kếmột giải thuật trước khi
tìmhiểu vềcác cấu trúc dữliệu cụthể.
Vào cuối khóa học, sinh viên có thể:
- Phân tích độphức tạp của các chương trình có kíchthước nhỏvà trung
bình.
- Nhận thức được sựcần thiết của việc thiết kếcấu trúc dữliệu.
- Làm quen với các khái niệmstacks, queues, danh sách đặc, danh sách
liên kết, cây nhịphân, cây nhịphân tìm kiếm, .
- Hiểu được nguyên lý của việc xây dựng một chương trình máy tính.
- Có thểchọn lựa việc tổchức dữliệu phù hợp và các giải thuật xửlý dữ
liệu có hiệu quảtrong khi xây dựng chương trình. Sinh viên cần lưu ý rằng, tùy
vào công việc cụthểmà tanên chọn cấu trúc dữliệu nào là thích hợp theo
hướng tối ưu vềthời gian thực hiện hay tối ưu vềbộnhớ.
nút còn lại trong đồ thị. * ải thuật dà gắ hấ ừ v ến t cả Gi : D g t t S ch c nú ã xác đ h được khoảng cách ngắn nhất từ nút ến các nút đ D g t m g ist c ị c oả cách ngắn nhất này. Nếu nút u ở on t Di u] gi rị khoả cá ng nhất từ v cho đến u. Nếu u chưa t g thì ist ] a dài từ đế ột nút w nào đó trong S ng với khoảng cách từ w đến u. Mảng Dist sẽ được khởi tạo bằng giá trị trọng lượn nút còn lại nếu có cạnh trực tiếp, và bằng vô cùng (MA cạnh trực tiếp. ùn mộ ập để ứa ác t đ ịn v đ ó. ùn mộ ản D để hứa giá tr cá kh ng tr g S hì st [ là á t ng ch ắn có ron S D [u chứ độ v n m cộ g từ nút v đến các XINT) nếu không có 182 a0 4 1 3 2 2 5 3 d=5 d=3 d=2 d=∞ S={0} b 0 4 1 3 2 2 5 4 3 d=5 d=3 d=2 d=6 10 6 S={0,4} c 0 4 1 3 2 2 2 1 3 d=4 d=3 d=2 d=5 6 S={0,4,2,1} e 0 4 1 3 2 2 2 1 3 d=4 d=3 d=2 d=5 S={0,4,2,1,3} f 0 4 1 3 2 2 5 2 4 1 3 d=4 d=3 d=2 d=5 d S={0,4,2} 0 4 1 3 2 2 5 2 4 1 6 3 10 6 2 Hình 6.9 Mi đường đi ngắn nhất từ i trong đồ thị hình 6.8 * Giải t nh họa các bước áp dụng giải thuật Dijkstra tìm c nút còn lạ nút 0 cho đến tất cả cá huật void Shortest_path(BYTE v, const long G[][MAX]) { neu G[i][j]=-1 thi Cost[i][j] = MAXINT */ ][MAX] ; ien do dai cua duong di ngan nhat tu nut v den nut j hi dinh huong G co MAX nut; G duoc bieu dien boi long int Dist [MAX] /* Cost chua do dai cac cung cua do thi G, voi qui uoc long Cost[MAX /* Dist[j] : the h trong do t ma tran ke huu huong co trong so kich thuoc MAX x MAX */ ; 183 /* S : Tap cac dinh (ke ca v) theo do cac duong di ngan nhat da xac lap */ ) for (j=0;j<MAX;j++) [j]= (G[i][j]==-1? MAXINT : G[i][j]); Khoi tao S va Dist ][i],i++ ); ist[v]=0 ; k=1; //dua v vao S hile (k < MAX) // xac dinh n-1 duong di tu dinh v n u sao cho: Dist[u] = min (Dist[j]), S[j]=0 while (j<MAX && S[j]!=0) j++; // Tim S[j] = 0 dau tien <MAX; j++) u=j; *) S[u]=1 ; k++; 0; w< MAX; w++) if (S[w] == 0) if (Dist[u]+Cost[u][w] < Dist [w]) Dist[w]= Dist[u]+Cost[u][w]; 0; w<MAX; w++) AXINT) " " <<w <<": " << Dist[w]; cout " <<w << ": Khong co duong di"; } V. ẮP THỨ TỰ TOPO int S[MAX] ; int w,i,j,u,k ; for (i=0; i<MAX; i++ Cost[i] // for (i=0; i< MAX; S[i]=0, Dist[i]=Cost[v S[v]=1; D w { // cho j=0; u=j; for (j=u; j if (S[j] == 0 && Dist[u] > Dist[j]) //Dua u vao tap S for (w= } for (w= if (Dist[w] < M cout << "\n else S : V.1. Khái niệm: Sắp thứ tự Topo là một quá trình sắp thứ tự các phần tử mà trong đó có định nghĩa một thứ tự bộ phận, nghĩa là một thứ tự cho trước trên một vài cặp các phần tử mà không phải trên tất cả các phần tử. Một thứ tự bộ phận của một tập hợp S là một quan hệ giữa các phần tử của S. Nó được ký hiệu bởi <, đọc là "đứng trước", và thỏa mãn ba tính chất sau đây đối với mọi phần tử phân biệt x, y, z của S: 184 (1) Nếu x < y và y < z thì x < z (tính bắc cầu) (3 ông phản xạ) Th ắp xếp các phần việc trong một công việ đó cho logic, nghĩa là khi ta thực hiện đến phần việc thứ i thì phải đảm bảo ần việc chuẩn bị cho nó trước rồi. Chẳng hạn như sắp xếp các tín ch ôn học sao cho khi đăng ký đến môn học i thì ta phải học qua các môn chuẩn bị trước cho nó. V.2 ậ (2) Nếu x < y thì không có thể có y < x (tính phản xứng) ) Không thể có x < x (tính kh ông thường, bài toán Topo nhằm để s c nào đã thực hiện các ph ỉ m . t toánThu : Để đơn giản, ta lấy ví dụ sau để minh họa: Gi ôn học sau: đại số tuyến t ăn bản (LTCB), Kỹ thuật lậ T), Cấu trúc dữ liệu (CTDL), Cấu trúc máy tính (CTMT), Cơ sở d uản trị giao tác (QTGT), Phân tích & thiết kế hệ thống thông Yê ả sử khoa công nghệ thông tin có giảng dạy các m Tin học cơ bản (THCB), Lập trình cính (ĐSTT), p trình (KTL ữ liệu (CSDL), Q tin (PTTK), Hệ quản trị cơ sở dữ liệu (HQT). u cầu: Hãy sắp xếp các môn học trên sao cho khi sinh viên đăng ký tín chỉ môn học thì phải đảm bảo các điều kiện sau: Môn học Các môn phải học trước Đại số tuyến tính Tin học cơ bản Lập trìn học cơ bản h căn bản Tin Kỹ thuật lập trình Lập trình căn bản, Đại số tuyến tính Cấu trúc dữ liệu Kỹ thuật lập trình Cấu trúc máy tính Cơ sở dữ liệu Tin học cơ bản Quản trị giao tác Cơ sở dữ liệu Phân tích & thiết kế hệ thống thông tin Hệ quản trị cơ sở dữ liệu Cơ sở dữ liệu, Phân tích & thiết kế hệ thống thông tin Ta có đồ thị minh họa bài toán trên với qui ước: Cung với u là môn phải học trước môn v 185 §STT KTLT THCB LTCB CTDL CTMT CSD QTGTL PTTK HQT Hình 6.10 Đồ thị minh họa bài toán sắp thứ tự các môn học thỏa ràng buộc đã cho Giải thuật: (i) Ta tìm nút nào không có cung đến nó thì chọn, sau đó hủy tất cả các khi không còn nút nào trên đồ thị Lưu ý cung từ nút đó đi ra. (ii) Lặp lại bước i cho đến : Nếu trong quá trình chọn mà không tìm được 1 nút không có cung hể thực hiện sắp được Nút chọn Đồ thị còn lại ĐSTT tới nó thì có nghĩa là đồ thị có chu trình. Do đó, không t Topo . Áp dụng giải thuật trên với đồ thị hình 6.10 THCB CTMT CSDL QTGT HQTPTTK LTCB CTDL KTLT THCB CTMT CSDL QTGT HQTPTTK LTCB CTDL KTLT 186 187 CTMT CSDL QTGT HQTPTTK LTCB CTDL KTLT LTCB CSDL QTGT HQTPTTK CTDLKTLT KTLT CSDL QTGT HQTPTTK CTDL CTDL CSDL QTGT HQTPTTK CSDL QTGT HQTPTTK PTTK QTGT HQT QTGT HQT HQT V.3. Cài đặt: Do số nút trên đồ thị thường nhiều và số cung trên đồ thị tương đối ít nên để tiết kiệm bộ nhớ, ta chọn cấu trúc dữ liệu để lưu trữ là danh sách kề; trong đó mảng 1 chiều chứa danh sách các nút của đồ thị, còn danh sách liên kết sẽ chứa các cung trên đồ thị. Chẳng hạn như danh sách kề của đồ thị hình 6.10 như sau: 188 ÑSTT THCB CTMT LTCB KTLT CTDL CSDL PTTK QTGT HQT 0 0 0 1 2 1 0 2 KTLT 1 1 LTCB CSDL KTLT CTDL QTGT HQT HQT Hình 6.11 Danh sách kề của đồ thị hình 6.10 Để biết được có bao nhiêu cung đi tới nút i, ta thêm trường count vào mảng chứa danh sách các nút. Dưới đây là chương trình sắp Topo với giả thiết của bài toán được chứa trong 1 file văn bản. File văn bản có dạng sau: Số n : số nút của đồ thị Ma trận số biểu diễn đồ thị UVí dụ U: File văn bản biểu diễn đồ thị hình 6.10 có dạng: 10 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 #include #include #include #include #include struct node 189 { int dinh_ke; struct node *next; }; typedef struct node *NODEPTR; struct phantu_ke { int count; NODEPTR pF; NODEPTR pL ; }; typedef struct phantu_ke Dothi[100]; Dothi G; int MAX; void Init_graph(Dothi G) { for(int i=0; i< MAX; G[i++].pF=NULL); } void Create_graph() { int i,j ; NODEPTR p; unsigned B[100][100]; FILE *fptr; if ( (fptr = fopen ("dt.txt", "rt")) == NULL ) { printf("\nKhong the mo file dt.txt"); getch(); exit(0); } fscanf(fptr,"%d", &MAX); for (i=0; i< MAX ; i++) for (j=0; j<MAX; j++) fscanf(fptr,"%d", &B[i][j]); /// Khoi tao rong do thi Init_graph(G); //Tao count : so cung toi dinh j for (j=0; j<MAX; j++) { G[j].count=0; for (i=0; i< MAX; i++) 190 if (B[i][j] ==1) G[j].count++; } for (i=0; i< MAX; i++) for (j=0;j<MAX; j++) if (B[i][j] == 1) { p = (NODEPTR)malloc(sizeof(struct node)); p->next=NULL; p->dinh_ke=j; if( G[i].pF == NULL) G[i].pF=p; else G[i].pL->next=p; G[i].pL=p; } } void Topo_Sort(Dothi G) { int Stack[100]; int i,j,k, Sp=-1 ; NODEPTR p; for(i=0;i<MAX; i++) // Dua vao Stack tat cac cac nut khong co cung di // toi no if (G[i].count==0) { // day la cac task co the lam doc lap Stack[++ Sp]=i; } for( i=0; i<MAX; i++) { if (Sp ==-1) { printf("\nCo chu trinh trong do thi!!!"); exit(0); } j=Stack[Sp--]; printf("%5d",j); // Lay 1 nut trong Stack ra p=G[j].pF; while (p !=NULL) { k=p->dinh_ke; // k la ngon cua cung j --> k G[k].count --; if (G[k].count == 0) // khong co dinh nao toi nut k { Stack[++Sp]=k; 191 } p=p->next; } } } void main() { clrscr(); Create_graph(); Topo_Sort(G); getch(); } 192 UBÀI TẬP : 1. Viết thủ tục ReadGraph để nhập vào các đỉnh và các cạnh của đồ thị G từ 1 file văn bản, biết rằng: - Nội dung của file văn bản là như sau: n u v trọngsố ..... với : n : số nút của đồ thị G u v trọngsố : chiều dài đường đi từ nút u đến nút v - Cấu trúc dữ liệu của đồ thị G được sử dụng là : a. Bảng kề b. Danh sách kề 2. Cho một đồ thị G, viết thủ tục WriteGraph để in các đỉnh của đồ thị, và các cạnh của đồ thị ra màn hình. 3. Cho một đồ thị G. Hãy xác định xem giữa 2 nút u và v có đường đi hay không? Nếu có, hãy xác định lộ trình từ nút u đến nút v. 4. Cho một đồ thị G. Hãy xác định xem đồ thị G có liên thông hay không ? 5. Cài đặt và kiểm tra thủ tục tìm đường đi ngắn nhất từ nút u cho đến nút v trong một đồ thị có hướng. Hãy xác định rõ lộ trình đó và cho biết chiều dài đường đi ngắn nhất là bao nhiêu? Minh họa các bước của giải thuật Dijkstra tìm đường đi ngắn nhất từ nút 0 đến nút 5 trên đồ thị sau: 0 1 2 5 4 3 12 25 30 20 30 24 80 80 50 30 40 193 TÀI LIỆU THAM KHẢO [1] Cấu trúc dữ liệu - Ứng dụng Nguyễn Hồng Chương 1999 và cài đặt bằng C [2] Cấu trúc dữ liệu + Giải thuật Niklaus Wirth - = Chương trình Người dịch Nguyễn Quốc Cường [3] Cấu trúc dữ liệu Đỗ Xuân Lôi [4] Cấu trúc dữ liệu Nguyễn Trung Trực 1992 [5] Phân tích và thiết kế giải thuật Đinh Nghiệp 1992 ĐH BK Tp. Hồ Chí Minh [6] Course 12.2AB2 Data Structures Alison Cousey 1999 and Algorithms II -
File đính kèm:
- CTDL.pdf