1. Trang chủ
  2. » Tất cả

Báo cáo môn học giải thuật tìm kiếm adt ngăn xếp stack và adt hàng đợi queue

37 5 0
Tài liệu đã được kiểm tra trùng lặp

Đ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

Tiêu đề Báo cáo môn học giải thuật tìm kiếm adt ngăn xếp stack và adt hàng đợi queue
Tác giả Cấu Trúc Dữ Liệu Và Giải Thuật, Đàm Văn Mạnh, Nguyễn Khắc Kiên, Nguyễn Văn Nam, Trịnh Minh Toàn, Đỗ Văn Mạnh, Nguyễn Thị Xuyến
Người hướng dẫn Ths. Giang Thị Thu Huyền
Trường học Khoa Hệ Thống Thông Tin Quản Lý
Chuyên ngành Cấu trúc dữ liệu và giải thuật
Thể loại Báo cáo môn học
Năm xuất bản 2023
Thành phố Hà Nội
Định dạng
Số trang 37
Dung lượng 1,07 MB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Cấu trúc

  • I. Tổng quan thuật toán tìm kiếm (4)
  • II. Các thuật toán tìm kiếm (4)
    • 1. Tìm kiếm t ên danh ách (4)
      • 1.1. Tìm kiếm tuần tự (5)
      • 1.2 Tìm kiếm tuần tự có lính canh (5)
      • 1.3 Tìm kiếm nhị phân (6)
    • 2. Tìm kiếm t ên cây nhị phân (7)
      • 2.1 Tìm kiếm theo chiều rộng (7)
      • 2.2 Tìm kiếm theo chiều âu (8)
      • 2.3 Cây nhị phân tìm kiếm (9)
    • 3. Tìm kiếm t ên đồ thị (12)
  • III. Cấu trúc dữ liệu ngăn xếp (ADT Stack) (0)
    • 1. Định nghĩa ADT Stack (19)
      • 1.1. Khái niệm (19)
      • 1.2. Nguyên tắc thực hiện (19)
      • 1.3. Đối tượng cất giữ (19)
      • 1.4. Các phép toán thực hiện (19)
    • 2. Cài đặt (19)
      • 2.1. Xây dựng cấu t úc (19)
      • 2.2. Các phép toán cơ bản (21)
      • 2.3. Các phép toán khác (21)
      • 2.4. Chương t ình minh họa các chức năng của stack (21)
    • 3. Ứng dụng (22)
      • 3.1. Phát biểu bài toán (22)
      • 3.2. Mô tả thuật giải và đánh giá độ phức tạp (22)
      • 3.3. Mô tả cài đặt chương t ình (23)
      • 3.4. Các ví dụ minh họa và hướng dẫn sử dụng (26)
  • IV. ADT hàng đợi (Queue) (30)
    • 1. Khái niệm hàng đợi (30)
    • 2. Các phép toán với hàng đợi (31)
    • 3. Cài đặt hàng đợi (31)
      • 3.2. Cài đặt hàng đợi bằng danh ách móc nối (33)
    • 4. Ứng dụng (33)
      • 4.1. Bài toán (33)
      • 4.2. Thuật toán (33)
      • 4.3. Mô tả cài đặt chương t ình (35)

Nội dung

Tổng quan thuật toán tìm kiếm - Nhu cầu tìm kiếm dữ liệu trong 1 HTTT: Trong hầu hết các hệ lưu trữ, quản lý dữ liệu, thao tác tìm kiếm thường được thực hiện nhất để khai thác thông tin

Tổng quan thuật toán tìm kiếm

Trong hầu hết các hệ thống lưu trữ và quản lý dữ liệu, nhu cầu tìm kiếm thông tin là cực kỳ quan trọng để khai thác dữ liệu hiệu quả Vì các hệ thống thông tin thường phải xử lý và lưu trữ khối lượng dữ liệu lớn, việc xây dựng các thuật toán tìm kiếm nhanh giúp tiết kiệm thời gian và nâng cao hiệu suất truy cập dữ liệu Tìm kiếm nhanh chóng và chính xác đóng vai trò then chốt trong tối ưu hóa hoạt động của hệ thống thông tin.

Nếu dữ liệu trong hệ thống đã được tổ chức theo một trật tự nào đó, thì việc tìm kiếm sẽ tiến hành nhanh chóng và hiệu quả hơn

Các thuật toán tìm kiếm hiệu quả phụ thuộc vào đặc điểm của cấu trúc dữ liệu mà chúng tác động đến Việc lựa chọn giải pháp phù hợp giúp tối ưu hóa hiệu suất và độ chính xác của quá trình tìm kiếm Hiểu rõ tính chất của từng loại cấu trúc dữ liệu là yếu tố then chốt để phát triển các giải pháp tìm kiếm hiệu quả hơn.

Dữ liệu chủ yếu được lưu trữ trong bộ nhớ chính và bộ nhớ phụ, mỗi loại có đặc điểm riêng biệt ảnh hưởng đến các thuật toán tìm kiếm và sắp xếp Các thuật toán này được thiết kế phù hợp với cấu trúc lưu trữ trên bộ nhớ chính hoặc bộ nhớ phụ nhằm tối ưu hiệu quả truy xuất dữ liệu Việc hiểu rõ đặc thù của từng loại bộ nhớ giúp cải thiện hiệu suất của các hệ thống lưu trữ và xử lý dữ liệu trong công nghệ thông tin.

Chúng tôi trình bày các thuật toán sắp xếp và tìm kiếm dữ liệu nội bộ được lưu trữ trên bộ nhớ chính, giúp tối ưu quá trình xử lý dữ liệu trong hệ thống máy tính Các giải thuật này đóng vai trò quan trọng trong việc nâng cao hiệu suất truy cập và quản lý dữ liệu nội bộ, đảm bảo hoạt động hiệu quả của các ứng dụng và phần mềm Việc hiểu rõ các thuật toán tìm kiếm và sắp xếp nội bộ là nền tảng quan trọng trong lĩnh vực khoa học máy tính, giúp tối ưu các thao tác xử lý dữ liệu trong bộ nhớ chính.

Các thuật toán tìm kiếm

Tìm kiếm t ên danh ách

Cấu trúc dữ liệu và giải thuật 5

 Bài toán: Tìm vị trí xuất hiện của phần tử có giá trị x trên danh sách đặc a

 Tư tưởng: Lần lượt so sánh giá trị x với từng phần tử trong mảng a cho đến khi tìm thấy hoặc hết các phần tử trong mảng a

Bước 2: Nếu a[i] = x : Tìm thấy Dừng, vị trí xuất hiện: i

Bước 3: i = Vị trí kế(i); // xét tiếp phần tử kế trong mảng

Bước 4: Nếu i >Vị trí cuối: //Hết mảng

Ngược lại: Lặp lại Bước 2

 Hàm t ả về 1 nếu tìm thấy, ngược lại trả về 0: int LinearSearch(int a[],int n, int x)

{ int i=0; while((i ai thì x chỉ có thể xuất hiện trong đoạn [ai+1 , aN] của dãy

 Nếu x < a i thì x chỉ có thể xuất hiện trong đoạn [a 1 , a i-1 ] của dãy

 Tư tưởng: So sánh khóa cần tìm với phần tử giữa dãy hiện hành Nếu nó nhỏ hơn thì tìm bên trái dãy hiện hành Ngược lại tìm bên phải dãy hiện hành Lặp lại thao tác trên

Bước 1: left = VTĐ; right = VTC;

Bước 2: Trong khi left  right lặp: //đoạn tìm kiếm chưa rỗng

Bước 2.1: mid = (left+right)/2; // lấy mốc so sánh

Bước 2.2: Nếu a[mid] = x: //Tìm thấy

Dừng, vị trí xuất hiện: mid Bước 2.3: Nếu a[mid] > x: //tìm x trong dãy con aleft amid -1 right = mid - 1;

Ngược lại //tìm x trong dãy con a mid +1 a right left = mid + 1;

//Hết lặp Bước 3: Dừng, không tìm thấy

Int BinarySearch (int a[], int N, int x )

Cấu trúc dữ liệu và giải thuật 7

{ int left =0, right = N-1, midle; while (left key = x; //gán trường dữ liệu của nút

 Thêm 1 nút vào cây nhị phân tìm kiếm:

Ràng buộc: Sau khi thêm cây đảm bảo là cây nhị phân tìm kiếm int insertNode (TREE &T, Data X) { if(T)

{ if(T->Key == X) return 0; if(T->Key > X) return insertNode(T->pLeft, X); else return insertNode(T->pRight, X);}

T = new TNode; if(T == NULL) return -1;

 Xoá 1 nút có Key bằng x t ên cây

Hủy 1 phần tử trên cây phải đảm bảo điều kiện ràng buộc của Cây nhị phân tìm kiếm

Có 3 trường hợp khi hủy 1 nút trên cây

 TH1: X là nút lá, ta xoá nút lá mà không ành hưởng đến các nút khác ttrên cây

 TH2: X chỉ có 1 cây con (cây con trái hoặc cây con phải), trước khi xoá x ta móc nối cha của X với con duy nhất cùa X

Cấu trúc dữ liệu và giải thuật 11

 TH3: X có đầy đủ 2 cây con, ta dùng cách xoá gián tiếp

 Tìm 1 nút có khoá bằng x t ên cây

 Tư tưởng: So sánh x với giá trị nút gốc:

Nếu x = giá trị của nút gốc thì dừng và đã tìm được nút x

Nếu x > giá trị của nút gốc thì ta tiến hành( một cách đệ quy) việc tìm khóa x trên cây con bên phải Nếu x < giá trị của nút gốc thì ta tiến hành( một cách đệ quy) việc tìm khóa x trên cây con bên trái

 Các bước thức hiện (không cài đặt đệ qui):

TNode * searchNode(TREE Root, Data x) { Node *p = Root; while (p != NULL)

{ if(x == p->Key) return p; else if(x < p->Key) p = p->pLeft; else p = p->pRight;

 Các bước thức hiện (có cài đặt đệ qui):

Cấu trúc dữ liệu và giải thuật 12 else if (x>T->key) return SearchTNode(T->pRight,x); else return SearchTNode(T->pLeft,x);

Tìm kiếm t ên đồ thị

 Giải thuật Dijkstra - Ứng dụng bài toán tìm đường đi ngắn nhất

Có rất nhiều giải thuật đã được phát triển để giải bài toán tìm đường đi ngắn nhất giữa một cặp đỉnh Giải thuật Dijkstra là một giải thuật để giải bài toán đường đi ngắn nhất nguồn đơn trên một đồ thị có trọng số cạnh mà tất cả các trọng số đều không âm

 Mô tả các cấu t úc dữ liệu sử dụng t ong cài đặt chương t ình:

Cấu trúc danh sách các đỉnh kề với một đỉnh bất kì:

Là danh sách liên kết đơn bao gồm 3 trường: tên đỉnh, khoảng cách và con trỏ đến phần tử kế tiếp: struct dinhke { int ten_dinh; structdinhke *tiep_theo; int khoang_cach;

Trường: ten_dinh: tên đỉnh kề với đỉnh đang xét

Trường: khoang_cach: khoảng cách từ đỉnh kề đến đỉnh đang xét

Trường: *tiep_theo: chỉ đến đỉnh kề khác với đỉnh đang xét

Cấu trúc dữ liệu và giải thuật 13

Ví dụ: dinh_do_thi[1] là một con trỏ quản lí một danh sách liên kết gồm những đỉnh kề với nó và khoảng cách từ đỉnh 1 đến những đỉnh kề này

Cấu trúc đỉnh của đồ thị trong biểu diễn cây vun đống (MinHeap):

Là một cấu trúc dữ liệu với 3 trường: độ dài, đánh dấu và đỉnh trước: typedefstruct { int do_dai; int danh_dau; int dinh_truoc;

Trường "do_dai" lưu trữ độ dài của đường đi ngắn nhất từ đỉnh gốc đến đỉnh đang xét tại thời điểm đó Khi thuật toán kết thúc, giá trị trong trường này chính là độ dài của đường đi ngắn nhất từ đỉnh gốc đến đỉnh đó Việc cập nhật trường "do_dai" giúp xác định nhanh chóng đường đi tối ưu trong quá trình duyệt đồ thị Đây là yếu tố quan trọng trong các thuật toán tìm đường ngắn nhất như Dijkstra They đảm bảo rằng các bước tìm đường luôn hướng tới việc tối thiểu hóa khoảng cách từ đỉnh gốc đến các đỉnh khác trên đồ thị.

Trong thuật toán tìm đường đi ngắn nhất, "danh_dau" được sử dụng để đánh dấu các đỉnh đã được xác định có đường đi ngắn nhất từ đỉnh gốc hay chưa Giá trị của "danh_dau" bằng 1 biểu thị rằng đã tìm thấy đường đi ngắn nhất, trong khi giá trị bằng 0 nghĩa là chưa tìm được Ban đầu, tất cả các đỉnh được khởi tạo giá trị "danh_dau" bằng 0, và trong quá trình thực thi, chỉ xét các đỉnh có "danh_dau" bằng 0 Khi thuật toán kết thúc, tất cả các đỉnh sẽ có "danh_dau" bằng 1, đã được xác nhận có đường đi ngắn nhất từ đỉnh gốc.

Trường: dinh_truoc: đỉnh đi trước đỉnh đang xét trong đường đi ngắn nhất từ đỉnh gốc đến đỉnh đang xét

Mô hình: dinh_do_thi[1] dinh_do_thi[2]

… dinh_do_thi[n] Đỉnh 3 Khoảng cách 9 Tiếp NULL

Cấu trúc dữ liệu và giải thuật 14

Cây nhị phân MinHeap vun đống theo giá trị trường do_dai lưu trong mỗi nút

 Thuật toán ử dụng t ong cài đặt chương t ình:

Ban đầu, khởi tạo giá trị đường đi ngắn nhất từ đỉnh gốc (gọi là đỉnh s) tới các đỉnh khác, trong đó giá trị này tại chính đỉnh s bằng 0 Quá trình bắt đầu bằng cách thiết lập các giá trị ban đầu cho các đỉnh còn lại để xác định đường đi ngắn nhất một cách chính xác Việc khởi tạo này đóng vai trò quan trọng trong các thuật toán tìm đường đi tối ưu như Dijkstra, giúp tối ưu hóa quá trình tính toán và đảm bảo kết quả chính xác.

- Có đỉnh có đường đi ngắn hơn thì ta chọn đỉnh đó là đỉnh min thay cho đỉnh min cũ

Trong quá trình tối ưu hóa mã nguồn, chúng tôi đã thay thế mảng dinh_truoc[MAX] bằng mảng cha[MAX] nhằm đảm bảo tính rõ ràng và dễ hiểu hơn trong việc xác định cha của các đỉnh Đồng thời, mảng danh_dau[MAX] được thay thế bằng mảng tim-duong[MAX] để phản ánh rõ hơn trạng thái duyệt của các đỉnh trong thuật toán Mảng do_dai[MAX] thay cho khoang_cach[MAX] giúp thể hiện chính xác khoảng cách từ đỉnh xuất phát đến các đỉnh hơn Cuối cùng, mảng chua_xet[MAX] được thay thế bằng dinh[MAX] để đơn giản hóa quá trình kiểm tra đỉnh đã được xét hay chưa, từ đó tối ưu hóa hiệu suất của chương trình.

- Nếu các đỉnh được xét hết thì isempty(dinh) trả về 1 còn không thì trả về 0

For i=1 to so_dinh { do_dai/danh_dau/dinh_truoc do_dai/danh_dau/dinh_truoc do_dai/danh_dau/dinh_truoc

Cấu trúc dữ liệu và giải thuật 15 dinh[i]=1;//dinh=1 là chua xet 0 là da xet cha[i]=dinh s; tim_duong[i]=0; khoang_cach[i]=

} khoang_cach[s]=0; while(!isempty(dinh)) { min=1; while(dinh[min]==0) min++; for i=2 to so_dinh { if(khoang_cach[i]Next; free(firstCell); return X;

(Xem chi tiết trong file “stack.h”)

2.4 Chương t ình minh họa các chức năng của stack:

Chương trình minh họa các chức năng của Stack nằm trong thư mục “Chuong trinh minh hoa cac chuc nang cua stack” – Có thể

Cấu trúc dữ liệu và giải thuật 22 chạy trực tiếp bằng file “testStack.exe” hoặc mở file

“testStack.cpp” bằng DevC rồi biên dịch và chạy

Chương trình kiểm tra dấu ngoặc minh họa chức năng của Stack trong xử lý các ký tự ngữ pháp Được đặt trong thư mục “Minh hoa-dau ngoac”, chương trình sử dụng cú pháp của Stack để xác định xem các dấu ngoặc có được đặt đúng theo quy tắc ngữ pháp hay không Để chạy chương trình, người dùng có thể mở file “Matching.exe” hoặc biên dịch mã nguồn “Matching.cpp” từ DevC.

Ứng dụng

Trong báo cáo này, chúng em ứng dụng Stack để tính toán biểu thức số học với các phép toán: +, - , *, /, ^ và dấu ngoặc đơn để thể hiện thứ tự ưu tiên thực hiện (dấu âm được thể hiện bằng kí tự ~)

Để tính giá trị của một biểu thức trung tố gồm các số thực và các toán tử như cộng (+), trừ (-), nhân (*), chia (/), lũy thừa (^), dấu âm (~), và các dấu ngoặc để thể hiện mức độ ưu tiên, cần áp dụng quy tắc ưu tiên toán học thông thường Quy tắc này đảm bảo rằng các phép toán trong biểu thức được thực hiện theo thứ tự chính xác, từ trong ra ngoài và từ trên xuống dưới, bao gồm cả việc xử lý toán tử lũy thừa và dấu âm trước các phép tính khác Trong đó, ký hiệu ~ được quy ước là dấu âm, giúp xác định các số âm trong biểu thức trung tố một cách chính xác Việc tính toán đúng theo quy tắc ưu tiên sẽ giúp xác định giá trị chính xác của biểu thức, đảm bảo tính đúng đắn của kết quả.

3.2 Mô tả thuật giải và đánh giá độ phức tạp:

Để giải bài toán, bước đầu tiên là chuyển đổi biểu thức sang dạng hậu tố để dễ dàng tính toán Sau đó, thực hiện đánh giá biểu thức hậu tố để xác định kết quả cuối cùng Cả hai quy trình này đều sử dụng cấu trúc dữ liệu Stack nhằm đảm bảo tính chính xác và hiệu quả trong quá trình xử lý.

3.2.1 Chuyển biểu thức trung tố thành hậu tố:

Lũy thừa > nhân, chia > cộng, trừ, dấu âm

- Lũy thừa: phải qua trái

- Nhân, chia: trái qua phải

- Cộng, trừ: trái qua phải

- Dấu âm: toán tử 1 ngôi (Dấu ngoặc có độ ưu tiên cao hơn thứ tự ưu tiên và quy tắc kết hợp)

- Duyệt biểu thức từ trái sang phải

Cấu trúc dữ liệu và giải thuật 23

- Nếu gặp toán hạng thì đưa ra ngay

- Nếu gặp dấu mở ngoặc thì nạp vào ngăn xếp

- Nếu gặp dấu đóng ngoặc thì đẩy kí tự ra cho tới khi gặp dấu mở ngoặc đầu tiên

Khi gặp toán hạng, nhanh chóng đưa chúng vào ngăn xếp các toán hạng theo thứ tự ưu tiên Đối với các toán hạng có cùng cấp độ ưu tiên và tính chất kết hợp, cần nạp phép toán vào ngăn xếp sau khi đã loại bỏ các toán hạng có thứ tự ưu tiên cao hơn Quá trình này giúp đảm bảo quá trình tính toán diễn ra chính xác và hiệu quả trong các thuật toán xử lý biểu thức.

- Duyệt hết biểu thức: Đưa tất cả phép toán còn lại ra khỏi ngăn xếp

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

Thuật toán tính toán biểu thức hậu tố như sau:

- Duyệt biểu thức từ trái sang phải

- Nếu gặp toán hạng thì đưa vào ngăn xếp

Khi gặp phép toán trong biểu thức, nếu đó là toán tử hai ngôi, ta lấy hai phần tử từ ngăn xếp, áp dụng phép tính, rồi đẩy kết quả trở lại ngăn xếp Ngược lại, nếu là toán tử một ngôi, ta lấy một phần tử từ ngăn xếp, thực hiện phép toán, sau đó đẩy kết quả trở lại ngăn xếp Quá trình này giúp xử lý các biểu thức toán học một cách hiệu quả và chính xác.

- Tiếp tục duyệt cho tới khi hết xâu

- Giá trị còn lại trong ngăn xếp chính là giá trị của biểu thức

Mỗi thuật toán duyệt xâu chỉ thực hiện một lần duyệt duy nhất Trong trường hợp xấu nhất, mỗi ký tự của chuỗi phải được đưa vào Stack một lần, do đó, thời gian xử lý tỷ lệ thuận với độ dài của chuỗi biểu thức Độ phức tạp của thuật toán là O(N), trong đó N là chiều dài của chuỗi biểu thức.

3.3 Mô tả cài đặt chương t ình:

Chương trình có hai hàm chính là hàm:

+ int inToPost(char *s, char *t): Chuyển dạng trung tố thành dạng hậu tố

Cấu trúc dữ liệu và giải thuật 24

+ int postfixExp(char *strExp, float *V): Tính giá trị biểu thức hậu tố

Ngoài ra còn 1 phiên bản đồ họa, thao tác trên cửa sổ window bằng cách sử dụng các hàm API của thư viện windows.h

Input: biểu thức s dạng trung tố Output: biểu thức t dạng trung tố

Thực hiện: Như thuật toán đã trình bày ở trên, đối với các toán hạng, ta có thể nhập số thực, chẳng hạn: 17.5 -> do đó trong đầu ra t, giữa các toán hạng sẽ được chèn thêm dấu cách Do đó, nếu viết 24 thì sẽ hiểu là hai số 2 và 4, còn nếu viết 24

() thì sẽ được hiểu là 1 số 24 duy nhất

3.3.2 Int postfixExp(char*strExp, float *V):

Input: biểu thức strExp dạng hậu tố

Output: giá trị V – 1 số thực

Việc tính giá trị biểu thức hậu tố sử dụng cấu trúc dữ liệu stack theo thuật toán đã trình bày giúp xử lý nhanh chóng và chính xác Đối với các toán hạng là các xâu ký tự, cần chuyển đổi thành giá trị số để phục vụ quá trình tính toán, sử dụng thuật toán riêng biệt Quá trình này đảm bảo tính linh hoạt và hiệu quả trong việc xử lý các biểu thức phức tạp.

- Giá trị ban đầu val= 0, cờ Point = 0, Deca = 1;

- Duyệt đoạn xâu từ đầu đến cuối

- Nếu gặp dấu chấm “ ” thì Point = 1, Deca = Deca*10

- Nếu gặp chữ số thì: o Nếu Point = 0 thì val = val*10 + o Nếu Point = 1 thì

 val = val + giá trị số / Deca;

- Nếu gặp kí tự khác thì kết thúc, đưa ra giá trị val

Cấu trúc dữ liệu và giải thuật 25

Việc xử lý đồ họa được dùng theo cách sau:

- Tạo một cửa sổ có tên là Expresstion

- Trên đó, tạo 1 label có tên là Expresstion

- Tạo 1 Vùng Text Edit để nhập biểu thức

- Tạo 2 Button : Calculate để tính giá trị và Reset để nhanh chóng khôi phục lại trạng thái lúc khởi động

- Tạo 1 vùng Text ở cuối cùng để lưu giá trị

- Phương pháp xử lí như sau: o Khi người dùng nhấn Calculate thì thực hiện đọc xâu từ cửa sổ phía trên, thực hiện hai phép toán:

 Chuyển xâu biểu thức dạng trung tố thành hậu tố

 Tính biểu thức dạng hậu tố o Nếu tính thành công, đưa ra kết quả ở biểu thức bên dưới o Ngược lại, thông báo 1 message cảnh báo tới người dùng

Cấu trúc dữ liệu và giải thuật 26

3.4 Các ví dụ minh họa và hướng dẫn sử dụng:

Tính giá trị biểu thức: 3 – 2^2 + 2*(1+3)/5 Kết quả: 0.6

Tính giá trị biểu thức: 2 * 3^2*0.5/3 + 12.4/2 Kết quả: 9.2

Tính giá trị biểu thức: 3 – (~8.4)/4 + 5*2 => kết quả: 15.1

Cấu trúc dữ liệu và giải thuật 27

Tính giá trị biểu thức: 3 – (~ 4 +2)^6 => kết quả - 61

Tính giá trị biểu thức: 2.2 – 12/5 + (1+2)/3 => Kết quả 8.8

Cấu trúc dữ liệu và giải thuật 28

Cấu trúc dữ liệu và giải thuật 29

Tính giá trị biểu thức: 2.5 – (~4.5) + 2^3 – 10 + 1.2*(1+3)

3.4.2.1 Chương t ình dòng lệnh: a) Chạy chương t ình:

- Mở chương trình: Thư mục Expresstion-cmd, click đúp vào file Expresstion.exe

- Chương trình chạy màn hình cmd, người dùng nhập một biểu thức bất kì, dạng trung tố

- Chương trình tính toán và hiển thị kết quả

- Chương trình hỏi người dùng có muốn tiếp tục hay không?

- Nếu muốn chạy lại thì nhấn Y hoặc y

- Ngược lại, bấm các phím khác để thoát b) Biên dịch chương t ình:

- Mở file “Expresstion.cpp” trong cùng thư mục trên bằng DevC

- Nhấn Ctrl + F9 để biên dịch, nhấn Ctrl + F10 để chạy chương trình

3.4.2.2 Chương t ình đồ họa: a) Chạy chương t ình:

Cấu trúc dữ liệu và giải thuật 30

- Mở chương trình: Thư mục Expresstion-Do hoa, click đúp vào file “Expresstion.exe”

- Chương trình chạy sẽ mở một cửa sổ window như hình vẽ:

- Nhập biểu thức vào ô Expreestion và nhấn Calculate để tính giá trị

- Có thể xóa biểu thức rồi nhập lại như bình thường hoặc nhấn Reset b) Biên dịch chương t ình:

- Mở file “expresstion.dev” bằng devC để mở 1 project chứa mã nguồn của chương trình

- Nhấn Ctrl + F9 để biên dịch

- Nhấn Ctrl + F10 để chạy chương trình

ADT hàng đợi (Queue)

Khái niệm hàng đợi

Hàng đợi là danh sách có thứ tự trong đó phép toán chèn luôn được thực hiện ở phía cuối của danh sách, còn phép toán xóa hoặc truy cập thường được thực hiện ở phía đầu Đây là cấu trúc dữ liệu tuyến tính, giúp quản lý dữ liệu theo nguyên tắc FIFO (First In, First Out), phù hợp cho các ứng dụng yêu cầu xử lý theo thứ tự thời gian Hàng đợi có vai trò quan trọng trong lập trình và hệ thống xử lý dữ liệu, đặc biệt trong các thuật toán quản lý tài nguyên và xử lý đa luồng.

Các phần tử trong hàng đợi luôn được lấy ra theo quy tắc vào trước ra trước, đảm bảo rằng phần tử được thêm vào đầu tiên sẽ là phần tử đầu tiên rời khỏi hàng đợi Chính vì vậy, hàng đợi còn được gọi là danh sách vào trước ra trước, phản ánh chính xác nguyên lý hoạt động của cấu trúc dữ liệu này Việc hiểu rõ quy tắc này giúp tối ưu hóa quá trình xử lý dữ liệu trong các hệ thống yêu cầu xử lý theo thứ tự của thời gian hoặc ưu tiên Các ứng dụng của hàng đợi rất phổ biến trong các hệ thống máy tính, dịch vụ khách hàng và các thuật toán cần xử lý theo trình tự.

Cấu trúc dữ liệu và giải thuật 31

Các thuật ngữ liên quan đến hàng đợi:

Các phép toán với hàng đợi

 Q = init(): khởi tạo Q là hàng đợi rỗng

 isEmpty(Q): Trả lại true khi và chỉ khi Q là hàng đợi rỗng

Phần mềm kiểm tra trạng thái của hàng đợi bằng hàm isFull(Q) trả về giá trị true khi và chỉ khi hàng đợi đầy, cho biết rằng chúng ta đã sử dụng vượt quá kích thước tối đa của hàng đợi Hàm này giúp đảm bảo rằng các thao tác thêm phần tử vào hàng đợi không gây tràn và duy trì tính ổn định của cấu trúc dữ liệu Việc kiểm tra isFull là cần thiết để tránh lỗi tràn bộ nhớ hoặc vượt quá giới hạn đã định trước của hệ thống, đảm bảo hoạt động đúng và an toàn.

 front(Q): Trả lại phần tử ở phía trước (front) của hàng đợi Q hoặc gặp lỗi nếu hàng đợi rỗng

 enqueue(Q, x): chèn phần tử x vào phía sau hàng đợi Q Nếu việc chèn dẫn đến tràn hàng đợi thì cần thông báo về điều này

Hàm dequeue(Q, x) được sử dụng để loại bỏ phần tử ở phía trước của hàng đợi và trả về thông tin chứa trong phần tử đó Trong trường hợp hàng đợi rỗng, hàm cần cung cấp thông báo lỗi phù hợp Việc này giúp duy trì tính đúng đắn của cấu trúc dữ liệu hàng đợi và đảm bảo quá trình xử lý dữ liệu diễn ra thuận lợi.

 print(Q): Đưa ra danh sách tất cả các phần tử của hàng đợi Q theo thứ tự từ phía trước đến phía sau

 Size(Q): Trả lại số lượng phần tử trong hàng đợi.

Cài đặt hàng đợi

3.1 Cài đặt hàng đợi bằng mảng

- Sử dụng mảng Q kích thước N theo thứ tự vòng trò Có hai biến để lưu

Loại bỏ/ Đưa ra (Remove/ Dequeue)

Phía sau/Cuối Back/Rear

Phía trước/Đầu Front/Head

Cấu trúc dữ liệu và giải thuật 32 trữ vị trí đầu và vị trí cuối (front and rear)

- Các phép toán đối với hàng đợi sử dụng phép toán số học theo modulo

Kích thước hàng đợi return (N-f+r ) mod N;

Kiểm t a hàng đợi rỗng return (f=r) ? 0:1;

Phép toán chèn if(size()=N-1) error! else Q[r] r

Phép toán loại bỏ if(isEmpty()) Error! else x Q[f]; f (f+1) mod N; return x

Cấu trúc dữ liệu và giải thuật 33

- Đối với phép toán enqueu(Q) phải để ý đến lỗi tràn hàng đợi, phép toán dequeue(Q) phải để ý đến lỗi hàng đợi rỗng

3.2 Cài đặt hàng đợi bằng danh ách móc nối

- Có thể cài đặt hàng đợi bằng danh sách nối đơn hoặc nối đôi

- Các phép toán với hàng đợi Kiểm t a hàng đợi rỗng return (front next =rear) ? 1: 0;

Phép toán chèn new node; rear next next = node; rear next = node;

Phép toán loại bỏ, đưa a new node; node=front next ; front next=front next next; return node;

- Đối với phép toán enqueu(Q) không cần quan tâm dến lỗi tràn hàng đợi, phép toán dequeue(Q) cần để ý đến lỗi hàng đợi rỗng.

Ứng dụng

4.1 Bài toán: Ứng dụng hàng đợi giải quyết bài toán duyệt đồ thị theo chiều rộng, tìm số thành phần liên thông của đồ thị vô hướng và tìm đường đi giữa hai đỉnh trong đồ thị

Cấu trúc dữ liệu và giải thuật 34

Trong quá trình duyệt đồ thị theo chiều rộng, bắt đầu từ mỗi đỉnh chưa được xét, ta kết lập đỉnh vào hàng đợi Khi hàng đợi không rỗng, thực hiện lấy một phần tử ra khỏi hàng, thăm đỉnh đó và kết hợp các đỉnh kề vào hàng đợi, đồng thời đánh dấu đỉnh đã được thăm Để tìm số thành phần liên thông, ta sử dụng biến Inconnect và mảng Index[] để lưu trữ số thành phần liên thông và các đỉnh thuộc từng thành phần trong quá trình duyệt Ngoài ra, mảng Truoc[so dinh] được dùng để lưu đỉnh xét trước, từ đó giúp xác định các đường đi giữa hai điểm trong đồ thị một cách hiệu quả.

Thuât toán duyệt đồ thị theo chiều rộng dùng hàng đợi procedure BFS(v)

QUEUE v; (kết nạp v vào hàng đợi) chuaxet[v]e; while (QUEUE ≠ ϕ) do p QUEUE; (lấy p từ QUEUE ) thamDinh(p); for u ϵ ke(p) do if (chuaxet[u]) then

Tìm thành phần liên thông for v ϵ V do chuaxet[v]=true; for v ϵ V do if (chuaxet[v] ) then BFS(v);

Cấu trúc dữ liệu và giải thuật 35

Tìm đườn đi giưa 2 đỉnh nhập 2 đỉnh u, v

BFS(u); Đường đi: v p1=truoc[t] p2=truoc[p1] … u

4.2.2 Độ phức tạp của thuật toán:

- Độ phức tạp của thuật toán duyệt đồ thị BFS

Thuật toán loại bỏ mỗi đỉnh khỏi hàng đợi đúng một lần, do đó thao tác dequeue(Q) thực hiện đúng |V| lần

Trong thuật toán duyệt đồ thị, mỗi đỉnh được xử lý bằng cách duyệt qua tất cả các đỉnh kề của nó, với thời gian xử lý mỗi đỉnh đều là hằng số Vì vậy, thời gian thực hiện câu lệnh if trong vòng lặp while cũng tỷ lệ thuận với số đỉnh kề của đỉnh đang xét Điều này giúp xác định rõ chi phí tính toán của thuật toán dựa trên số lượng cạnh liên kết với các đỉnh trong đồ thị.

Do đó tổng thời gian thực hiện việc duyệt qua tất cả các đỉnh là một hằng số nhân với số cạnh |E|

- Độ phức tạp của thuật toán tìm ố thành phần liên thông

Inconnect là số thành phần liên thông Thuật toán phải thực hiện BFS

Inconnect lần, mỗi lần gọi mất thời gian là O(|V i | + |E i |) với |V i |, |E i | là số đỉnh và số cạnh của mỗi thành phần liên thông

Thời gian tổng cộng là: O(|V| + |E|)

- Độ phức tạp của thuật toán tìm đường đi

Thuật toán gọi BFS một lần và quay ngược để tìm đường đi mất thời gian O(|V|)

Thời gian tổng cộng là: O(|V| + |E|) + O(|V|) = O(|V| + |E|) hay O(|V| 2 )

4.3 Mô tả cài đặt chương t ình

- Sử dụng hàng đợi biểu diễn bằng danh sách liên kết đơn

- Dữ liệu được nhập từ file được chuẩn bị theo hình thức danh sách cạnh, dòng đầu tiên của file in số đỉnh của đồ thị

- Đồ thi được biểu diễn bằng danh sách kề

Cấu trúc dữ liệu và giải thuật 36

Chương trình gồm ba file chính: head1.h, định nghĩa các cấu trúc dữ liệu và các thao tác với hàng đợi biểu diễn bằng danh sách liên kết đơn; head2.h, chứa các hàm con hỗ trợ cho các thao tác này; và main.cpp, là file chương trình chính thực thi các chức năng đã xác định Các file này phối hợp để xây dựng một hệ thống hàng đợi hiệu quả, phù hợp với các yêu cầu xử lý dữ liệu theo kiểu danh sách liên kết đơn.

- Giao diện chương trình chính:

- Ví dụ kết quả tìm thành phần liên thông của đồ thị

- Ví dụ kết qua tim đường đi giữa 2 đỉnh trong đồ thị

Ngày đăng: 17/03/2023, 10:03

TỪ KHÓA LIÊN QUAN

TÀI LIỆU CÙNG NGƯỜI DÙNG

TÀI LIỆU LIÊN QUAN

🧩 Sản phẩm bạn có thể quan tâm

w