1. Trang chủ
  2. » Giáo Dục - Đào Tạo

Extract pages from dc2me21 bai giang cau truc du lieu va giai thuat pdfp2 4017

66 5 0

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 66
Dung lượng 5,36 MB

Nội dung

Chương Cấu trúc liệu 4.1 Mảng danh sách 4.1.1 Các khái niệm Có thể nói, mảng cấu trúc liệu sử dụng rộng rãi tất ngôn ngữ lập trình Một mảng tập hợp cố định thành phần có kiểu liệu, lưu trữ truy cập thơng qua số Ví dụ, để truy cập tới phần tử thứ i mảng a, ta viết a[i] Chỉ số phải số nguyên không âm nhỏ kích thước mảng (số phần tử mảng) Trong chương trình, số khơng thiết phải số biến số, mà biểu thức hàm a1 a2 a i+1 an Lưu ý cấu trúc nhớ máy tính tổ chức thành nhớ, truy cập ngẫu nhiên thông qua địa Do vậy, việc lưu trữ liệu mảng có tương thích hồn tồn với nhớ máy tính, coi tồn bộ nhớ máy tính mảng, địa ô nhớ tương ứng số mảng Chính tương thích mà việc sử dụng cấu trúc liệu mảng ngơn ngữ lập trình làm cho chương trình hiệu chạy nhanh Mảng có nhiều chiều Khi đó, số số mảng tương ứng với số chiều Chẳng hạn, mảng chiều a, thành phần thuộc cột i, hàng j viết a[i][j] Mảng chiều gọi ma trận (matrix) a ll a 2l a il a a i2 ai+l2 m2 i+lj a mj a i+lj+l a a i+ ln a a22 a a a ij a a a ij+l a a in alj+l a ln 2j 2j+l 2n 128 ^ml a al2 lj i+ll mj+l mn Như nói trên, mảng cấu trúc liệu dễ sử dụng, tốc độ truy cập cao Tuy nhiên, nhược điểm mảng khơng linh hoạt kích thước Nghĩa ta khai báo l mảng kích thước cố định, khơng thể thay đổi q trình thực chương trình Điều bất tiện ta chưa biết trước số phần tử cần xử lý Nếu khai báo mảng lớn tốn nhớ ảnh hưởng đến hiệu suất chương trình Nếu khai báo mảng nhỏ dẫn đến thiếu nhớ Ngồi ra, việc bố trí lại phần tử mảng phức tạp, phần tử có vị trí cố định mảng, để bố trí l phần tử sang l vị trí khác, ta phải tiến hành “dồn” phần tử có liên quan Khác với mảng, danh sách liên kết l cấu trúc liệu có kiểu truy cập Mỗi phần tử danh sách liên kết có chứa thơng tin phần tử tiếp theo, qua ta truy cập tới phần tử R Sedgewick (Alogrithms in Java - 2002) định nghĩa danh sách liên kết sau: Danh sách liên kết l cấu trúc liệu bao gồm l tập phần tử, phần tử l phần l nút có chứa liên kết tới nút Nói “mỗi phần tử l phần l nút” nút ngồi việc chứa thơng tin phần tử cịn chứa thơng tin liên kết tới nút danh sách Có thể nói danh sách liên kết l cấu trúc liệu định nghĩa kiểu đệ qui, định nghĩa l nút danh sách có tham chiếu tới khái niệm nút Thơng thường, nút thường có liên kết trỏ tới nút khác, nhiên trỏ tới Danh sách liên kết xem l bố trí phần tử l tập Bắt đầu từ l nút, ta coi phần tử danh sách Từ nút này, theo liên kết mà trỏ tới, ta có nút thứ 2, coi phần tử thứ danh sách, v.v tiếp tục hết danh sách Nút cuối có liên kết liên kết null, tức khơng trỏ tới nút nào, trỏ nút để tạo thành l vòng NULL Như vậy, cấu trúc liệu bao gồm tập phần tử, danh sách liên kết mảng có số điểm khác biệt sau: - Mảng truy cập ngẫu nhiên thơng qua số, cịn danh sách truy cập Trong danh sách liên kết, muốn truy cập tới phần từ phải đầu danh sách sau qua phần tử đến phần tử cần truy 129 cập - Việc bố trí, đặt lại phần tử danh sách liên kết đơn giản nhiều so với mảng Bới danh sách liên kết, để thay đổi vị trí phần tử, ta cần thay đổi liên kết số phần tử có liên quan, cịn mảng, ta thường phải thay đổi vị trí nhiều phần tử Do chất động danh sách liên kết, kích thước danh sách liên kết linh hoạt nhiều so với mảng Kích thước danh sách khơng cần phải khai báo trước, lúc tạo phần tử thêm vào vị trí danh sách Nói cách khác, mảng tập có số lượng cố định phần tử, cịn danh sách liên kết tập có số lượng phần tử không cố định 4.1.2 Cấu trúc lưu trữ mảng Cấu trúc liệu đơn giản dùng địa tính để thực lưu trữ tìm kiếm phần tử, mảng chiều hay véc tơ Thơng thường số từ máy dành để lưu trữ phần tử mảng Cách lưu trữ gọi cáchlưu trữ (sequential storage allocation) Trường hợp mảng chiều hay véc tơ có n phần tử lưu trữ từ máy cần phải dành cho n từ máy Do kích thước véc tơ xác định nên không gian nhớ dành ấn định trước Véc tơ A có n phần tử, phần tử (0 ≤ i ≤ n) chiếm c từ máy lưu trữ cn từ máy hình vẽ: L0 – Địa phần tử a0 Địa tính cơng thức: Loc(ai) = L0 + c * i Trong : L0 gọi địa gốc - địa từ máy miền nhớ dành để lưu trữ véc tơ (gọi véc tơ lưu trữ) f(i) = c * i gọi hàm địa (address function) 130 Đối với mảng nhiều chiều việc lưu trữ tương tự nghĩa sử dụng véc tơ lưu trữ a01 a11 aij anm Giả sử phần tử ma trận n hàng m cột (mảng nhiều chiều) chiếm từ máy địa aij tính cơng thức tổng qt sau: Loc(aij) = L0 + j * n + i { theo thứ tự ưu tiên cột (column major order } Cũng với ma trận n hàng, m cột cách lưu trữ theo thứ tự ưu tiên hàng (row major order) cơng thức tính địa là: Loc(aij) = L0 + i * m + j + Trường hợp cận số 1, nghĩa ứng với aij b1 ≤ i ≤ u1, b2 ≤ j ≤ u2 ta có cơng thức tính địa sau: Loc(aij) = L0 + (i - b1) * (u2 - b2 + 1) + (j - b2) hàng có (u2 - b2 + 1) phần tử Ví dụ : Xét mảng ba chiều B có phần tử bijk với ≤ i ≤ 2; ≤ j ≤ 3; ≤ k ≤ 4; lưu trữ theo thứ tự ưu tiên hàng phần tử đặt sau: b111, b112, b113, b114, b121, b122, b123, b124, b131, b132, b133, b134, b211, b212, b213, b214, b221, b222, b223, b224, b231, b232, b233, b234 Cơng thức tính địa : Loc(aijk) = L0 + (i - 1) *12 + (j - 1) * + (k - 1) VD: Loc(b223) = L0 + 22 Xét trường hợp tổng quát với mảng A n chiều mà phần tử : A[s1, s2, , sn] bi ≤ si ≤ ui ( i = 1, 2, , n), ứng với thứ tự ưu tiên hàng ta có: đặc biệt pn = Chú ý : 131 Khi mảng lưu trữ việc truy nhập vào phần tử mảng thực trực tiếp dựa vào địa tính nên tốc độ nhanh đồng phần tử Mặc dầu có nhiều ứng dụng mảng sử dụng để thể mối quan hệ cấu trúc phần tử liệu, khơng phải khơng có trường hợp mà mảng lộ rõ nhược điểm Ví dụ : Xét tốn tính đa thức x,y chẳng hạn cộng hai đa thức sau: (3x2 - xy + y2 + 2y - x) + (x2 + 4xy - y2 +2x) = (4x2 + 3xy + 2y + x) Ta biết thực cộng đa thức ta phải phân biệt số hạng, phân biệt biến, hệ số số mũ Để biểu diễn đa thức với biến x,y ta dùng ma trận: hệ số số hạng x y lưu trữ phần tử có hàng i cột j ma trận Nếu ta hạn chế kích thước ma trận n × n số mũ cao x,y xử lý với đa thức bậc n-1 i j Với cách biểu diễn kiểu việc thực phép cộng hai đa thức cộng ma trận mà Nhưng có số hạn chế : số mũ đa thức bị hạn chế kích thước ma trận lớp đa thức xử lý bị giới hạn phạm vi hẹp Mặt khác ma trận biểu diễn có nhiều phần tử 0, dẫn đến lãng phí nhớ 4.1.3 Danh sách tuyến tính a) Khái niệm 132 Một danh sách mà quan hệ lân cận hiển thị gọi danh sách tuyến tính (linear list) VD: Véc tơ trường hợp đặc biệt danh sách tuyến tính xét thời điểm Danh sách tuyến tính danh sách rỗng (khơng có phần tử nào) có dạng (a1, a2, , an) với (1 ≤ i ≤ n) liệu nguyên tử Trong danh sách tuyến tính tồn phần tử đầu a1, phần tử cuối an Đối với phần tử với ≤ i ≤ n - có phần tử ai+1 gọi phần tử sau ai, với ≤ i ≤ n có phần tử - gọi phần tử trước ai gọi phần tử thứ i danh sách tuyến tính, n gọi độ dài kích thước danh sách Mỗi phần tử danh sách thường ghi ( gồm nhiều trường (fields)) phần thơng tin nhỏ tham khảo VD: Danh sách sinh viên lớp danh sách tuyến tính mà phần tử ứng với sinh viên, bao gồm trường: Mã SV (STT), Họ tên, Ngày sinh, Quê quán, b) Lưu trữ Lưu trữ phương pháp lưu trữ sử dụng mảng chiều làm cấu trúc lưu trữ danh sách tuyến tính nghĩa dùng véc tơ lưu trữ Vi với ≤ i ≤ n để lưu trữ danh sách tuyến tính (a1, a2, , an) phần tử chứa Vi Ưu điểm : Tốc độ truy nhập nhanh, dễ thao tác việc bổ sung, loại bỏ tìm kiếm phần tử danh sách Nhược điểm: Do số phần tử danh sách tuyến tính thường biến động (kích thước n thay đổi) dẫn đến tượng lãng phí nhớ Mặt khác dự trữ đủ thị việc bổ sung hay loại bỏ phần tử danh sách mà phần tử cuối đòi hỏi phải dồn dãn danh sách (nghĩa phải dịch chuyển số phần tử để lấy chỗ bổ sung hay tiến lên để lấp chỗ phần tử bị loại bỏ) tốn nhiều thời gian Nhu cầu xây dựng cấu trúc liệu động: Với cấu trúc liệu xây dựng từ kiểu sở như: kiểu thực, kiểu nguyên, kiểu ký tự từ cấu trúc đơn giản mẩu tin, tập hợp, mảng lập trình viên giải hầu hết toán đặt Các đối tượng liệu xác định thuộc kiểu liệu có đặc điểm chung khơng thay đổi kích thước, cấu trúc q trình sống, thường cứng ngắt, gị bó khiến đơi khó diễn tả thực tế vốn sinh động, phong phú Các kiểu liệu kể gọi kiểu liệu tĩnh Ví dụ : 133 Trong thực tế, số đối tượng định nghĩa đệ qui, ví dụ để mô tả đối tượng "con người" cần thể thông tin tối thiểu :  Họ tên  Số CMND  Thông tin cha, mẹ   Ðể biễu diễn đối tượng có nhiều thành phần thơng tin sử dụng kiểu ghi Tuy nhiên, cần lưu ý cha, mẹ người đối tượng kiểu NGƯỜI, nguyên tắc cần phải có định nghĩa sau: typedef struct NGUOI{ char Hoten[30]; int So_CMND ; NGUOI Cha,Me; }; Nhưng với khai báo trên, ngôn ngữ lập trình gặp khó khăn việc cài đặt khơng vượt qua xác định kích thước đối tượng kiểu NGUOI Một số đối tượng liệu chu kỳ sống thay đổi cấu trúc, độ lớn, danh sách học viên lớp học tăng thêm, giảm Khi cố tình dùng cấu trúc liệu tĩnh biết mảng để biểu diễn đối tượng lập trình viên phải sử dụng thao tác phức tạp, tự nhiên khiến chương trình trở nên khó đọc, khó bảo trì khó sử dụng nhớ cách có hiệu Một lý làm cho kiểu liệu tĩnh đáp ứng nhu cầu thực tế tổng kích thước vùng nhớ dành cho tất biến tĩnh có giới hạn Khi có nhu cầu dùng nhiều nhớ ta phải sử dụng cấu trúc liệu động Cuối cùng, chất liệu tĩnh, chúng chiếm vùng nhớ dành cho chúng suốt trình hoạt động chương trình Tuy nhiên, thực tế, xảy trường hợp liệu tồn thời hay khơng thường xun q trình hoạt động chương trình Vì việc dùng CTDL tĩnh không cho phép sử dụng hiệu nhớ Do vậy, nhằm đáp ứng nhu cầu thể sát thực chất liệu xây dựng thao tác hiệu liệu, cần phải tìm cách tổ chức kết hợp liệu với hình thức linh động hơn, thay đổi kích thước, cấu trúc suốt thời gian sống Các hình thức tổ chức liệu gọi cấu trúc liệu động Bài 134 sau giới thiệu cấu trúc liệu động tập trung khảo sát cấu trúc đơn giản thuộc loại danh sách liên kết c) Lưu trữ móc nối Danh sách liên kết xem l bố trí phần tử l tập Bắt đầu từ l nút, ta coi phần tử danh sách Từ nút này, theo liên kết mà trỏ tới, ta có nút thứ 2, coi phần tử thứ danh sách, v.v tiếp tục hết danh sách Nút cuối có liên kết liên kết null, tức khơng trỏ tới nút nào, trỏ nút để tạo thành l vòng NULL Để khai báo danh sách C, ta dùng cấu trúc tự trỏ Ví dụ, để khai báo danh sách liên kết mà nút chứa phần tử số nguyên sau: struct node { int item; struct node *next; }; typedef struct node *listnode; Đầu tiên, ta khai báo cấu trúc node bao gồm thành phần Thành phần thứ biến nguyên chứa liệu, thành phần thứ trỏ chứa địa nút Tiếp theo, ta định nghĩa kiểu liệu trỏ tới nút có tên listnode Với danh sách liên kết có kiểu phần tử phức tạp hơn, ta phải khai báo cấu trúc phần tử trước (itemstruct), sau đưa kiểu cấu trúc vào kiểu phần tử cấu trúc node struct node { itemstruct item; struct node *next; }; typedef struct node *listnode; Các thao tác danh sách liên kết Như nói trên, với tính chất động danh sách liên kết, nút danh sách 135 không tạo từ đầu mà tạo cần thiết Do vây, thao tác cần có danh sách tạo cấp phát nhớ cho nút Tương ứng với thao tác giải phóng nhớ hủy nút không dùng đến Thao tác cần xem xét việc chèn nút tạo vào danh sách Do cấu trúc đặc biệt cua danh sách liên kết, việc chèn nút vào đầu, cuối, danh sách có số điểm khác biệt Do vậy, cần xem xét trường hợp Tương tự vậy, việc loại bỏ nút khỏi danh sách cung xem xét trường hợp Cuối la thao tác duyệt qua toàn danh sách Trong phần tiếp theo, ta se xem xét chi tiết việc thực thao tác này, thực danh sách liên kết có phần tử nút la số nguyên khai báo trình bày Con trỏ tới node struct node { int infor; struct node *next; }; typedef struct node *NODEPTR; Cấp phát nhớ cho node NODEPTR Getnode(void) { NODEPTR p; P = (NODEPTR) malloc(sizeof( struct node)); Return(p); } Giải phóng node NODEPTR Freenode( NODEPTR p){ free(p); } Thêm phần tử vào đỉnh danh sách void Push_Top( NODEPTR *plist, int x) { NODEPTR p; 136 p= Getnode(); p -> infor = x; p ->next = *plist; *plist = p; } Thêm node vào cuối danh sách void Push_Bottom( NODEPTR *plist, int x) { NODEPTR p, q; p= Getnode(); p->infor = x; q = *plist; while (q-> next != NULL) q = q -> next; q -> next = p; p ->next = NULL; } Thêm node vào danh sách void Push_Before( NODEPTR p, int x ){ NODEPTR q; if (p->next==NULL) Push_Bottom(p, x); else { q= Getnode(); q -> infor = x; q-> next = p-> next; p->next = q; } } Xóa node đầu danh sách void Del_Top( NODEPTR *plist) { NODEPTR p; p = *plist; if (p==NULL) return; (*plist) = (*plist) -> next; 137 Bước 2: Chèn phần tử ll vào nửa Dịch chuyển 32 sang phải l vị trí đưa ll vào vị trí trống ll 32 49 98 06 25 53 6l 53 6l Bước 3, 4: Lần lượt chèn phần tử 49, 98 vào nửa ll 32 49 98 06 25 Bước 5: Chèn phần tử 06 vào nửa Dịch chuyển phần tử ll, 32, 49, 98 sang phải l vị trí đưa 06 vào vị trí trống 06 11 32 49 98 25 53 6l Đã Chưa Bước 6: Chèn phần tử 25 vào nửa Dịch chuyển phần tử 32, 49, 98 sang phải vị trí đưa 25 vào vị trí trống 06 17 25 32 49 98 53 61 - ' > Đã Chưa Bước 7: Chèn phần tử 53 vào nửa Dịch chuyển phần tử 98 sang phải vị trí đưa 53 vào vị trí trống 06 17 25 32 49 Đã 53 98 61 Chưa 179 Bước 8: Chèn phần tử cuối 61 vào nửa Dịch chuyển phần tử 98 sang phải vị trí đưa 61 vào vị trí trống 06 17 25 32 49 53 61 98 5.1.4 Sắp xếp đổi chỗ trực tiếp a) Tư tưởng giải thuật  Tại bước thứ i, xét phần tử thứ a[i].   Với phần tử a[i], xét phần tử a[j] nằm sau (j=i+1,…,n-1) Nếu a[i]>a[j] đổi chỗ a[i] cho a[j] Lặp lại trình dãy xếp Các bước tiến hành sau: Bước 1: i = 0; // phần tử dãy Bước 2: j = i + // Tìm phần tử a[j]br) { c[k]=a[i++]; continue; } if (a[i]ar){ c[k]=a[i++]; 185 continue ; } if (a[i]

Ngày đăng: 28/06/2023, 21:24