Bài giảng Các kĩ thuật lập trình: Phần 1

78 11 0
Bài giảng Các kĩ thuật lập trình: Phần 1

Đ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

Bài giảng Các kĩ thuật lập trình được hình thành trên cơ sở các kinh nghiệm đã được đúc rút từ bài giảng của môn học Kỹ thuật lập trình cho sinh viên các ngành nói trên trong những năm học vừa qua với mục đích cung cấp cho sinh viên những kiến thức cơ bản nhất, có tính hệ thống liên quan tới môn học này. Phần 1 trình bày các nội dung chính sau: Đại cương về lập trình cấu trúc; Con trỏ và mảng; Duyệt và đệ qui;... Mời các bạn cùng tham khảo để nắm nội dung chi tiết.

HỌC VIỆN CƠNG NGHỆ BƯU CHÍNH VIỄN THƠNG  KHOA CÔNG NGHỆ THÔNG TIN BÀI GIẢNG CÁC KĨ THUẬT LẬP TRÌNH NGUYỄN DUY PHƯƠNG HàNội 2017 LỜI NĨI ĐẦU Sự phát triển công nghệ thông tin năm vừa qua làm thay đổi mặt kinh tế xã hội tồn cầu, cơng nghệ phần mềm trở thành ngành công nghiệp quan trọng đầy tiềm Với hội tụ công nghệ viễn thông công nghệ thông tin, tỷ trọng giá trị phần mềm chiếm cao hệ thống viễn thông nhƣ thiết bị đầu cuối Chính lý đó, việc nghiên cứu, tìm hiểu, tiến tới phát triển nhƣ làm chủ hệ thống phần mềm kỹ sƣ điện tử viễn thông cần thiết Mơn học Kỹ thuật lập trình mơn học sở bắt buộc sinh viên chuyên ngành điện tử viễn thông công nghệ thông tin Học viện cơng nghệ Bƣu Viễn thơng Cuốn giáo trình “Kỹ thuật lập trình”, đƣợc hình thành sở kinh nghiệm đƣợc đúc rút từ giảng mơn học Kỹ thuật lập trình cho sinh viên ngành nói năm học vừa qua với mục đích cung cấp cho sinh viên kiến thức nhất, có tính hệ thống liên quan tới môn học Khi học môn Kỹ thuật lập trình, sinh viên cần học qua mơn “Tin học sở” cần bạn có đủ kiến thức sở cần thiết để tiếp thu kiến thức Kỹ thuật lập trình Thơng qua giáo trình này, chúng tơi muốn giới thiệu với bạn đọc kỹ lập trình cấu trúc thơng qua số thuật tốn quan trọng, bao gồm: Đại cƣơng lập trình cấu trúc; Con trỏ mảng; Duyệt đệ qui; Ngăn xếp, hàng đợi danh sách móc nối; Cây; Đồ thị cuối Sắp xếp tìm kiếm Phần phụ lục tập tổng hợp lại kiến thức đƣợc đề cập giáo trình đƣợc thể chƣơng trình Tuy ý cẩn trọng trình biên soạn, nhƣng giáo trình chắn khơng tránh khỏi thiếu sót hạn chế Chúng tơi xin chân thành mong bạn đọc đóng góp ý kiến để giáo trình ngày hồn thiện Mọi đóng góp ý kiến xin gửi Khoa Công nghệ thông tin – Học viện Cơng nghệ Bƣu Viễn thơng Hà Nội, ngày 14 tháng 12 năm 2016 Các tác giả MỤC LỤC CHƢƠNG MỞ ĐẦU 1.1 Sơ lƣợc lịch sử lập trình cấu trúc 1.2 Cấu trúc lệnh - Lệnh có cấu trúc- Cấu trúc liệu 1.2.1 Cấu trúc lệnh (cấu trúc điều khiển) 1.2.2 Lệnh có cấu trúc 1.2.3 Cấu trúc liệu 1.3 Nguyên lý tối thiểu 10 1.3.1 Tập phép toán 10 1.3.2 Tập lệnh vào 12 1.3.3 Thao tác kiểu liệu có cấu trúc 13 1.4 Nguyên lý địa phƣơng 15 1.5 Nguyên lý quán 16 1.6 Nguyên lý an toàn 18 1.6 Phƣơng pháp Top-Down 19 1.7 Phƣơng pháp Bottom - Up 24 BÀI TẬP CHƢƠNG 28 CHƢƠNG MẢNG VÀ CON TRỎ 28 2.1 Cấu trúc lƣu trữ mảng 29 2.1.1 Khái niệm mảng 29 2.1.2 Cấu trúc lƣu trữ mảng chiều 29 2.1.3 Cấu trúc lƣu trữ mảng nhiều chiều 31 2.2 Các thao tác mảng 32 2.3 Mảng đối hàm 34 2.4 Xâu kí tự (string) 36 2.5 Con trỏ (Pointer) 37 2.5.1 Các phép toán trỏ 38 2.5.2 Con trỏ đối hàm 39 2.5.3 Con trỏ mảng 40 BÀI TẬP CHƢƠNG 46 CHƢƠNG DUYỆT VÀ ĐỆ QUI .53 3.1 Định nghĩa đệ qui 54 3.2 Giải thuật đệ qui 55 3.3 Thuật toán sinh 56 3.3.1 Bài toán liệt kê tập tập n phần tử 57 3.3.2 Bài toán liệt kê tập m phần tử tập n phần tử 59 3.3.3 Bài toán liệt kê hoán vị tập n phần tử 61 3.3.4 Bài toán chia số tự nhiên n thành tổng số nhỏ 63 3.4 Thuật toán quay lui (Back track) 65 3.4.1 Thuật toán quay lui liệt kê xâu nhị phân độ dài n 67 3.4.2 Thuật toán quay lui liệt kê tập m phần tử tập n phần tử 68 3.4.3 Thuật toán quay lui liệt kê hoán vị tập n phần tử 69 3.4.4 Bài toán Xếp Hậu 71 BÀI TẬP CHƢƠNG 74 CHƢƠNG NGĂN XẾP, HÀNG ĐỢI, DANH SÁCH LIÊN KẾT 78 4.1 Kiểu liệu ngăn xếp ứng dụng 78 4.1.1 Định nghĩa khai báo 78 4.1.2 Các thao tác với stack 79 4.1.3 ứng dụng stack 80 4.2 Hàng đợi (Queue) 85 4.2.1 Giới thiệu hàng đợi 85 4.2.2 ứng dụng hàng đợi 86 4.3 Danh sách liên kết đơn 91 4.3.1 Giới thiệu định nghĩa 91 4.3.2 Các thao tác danh sách móc nối 92 4.3.3 ứng dụng danh sách liên kết đơn 97 4.4 Danh sách liên kết kép 103 BÀI TẬP CHƢƠNG .117 CHƢƠNG CÂY NHỊ PHÂN 121 5.1 Định nghĩa khái niệm 121 5.2 Cây nhị phân 121 5.3 Biểu diễn nhị phân 123 5.3.1 Biểu diễn nhị phân danh sách tuyến tính 123 5.3.2 Biểu diễn nhị phân danh sách móc nối 123 5.4 Các thao tác nhị phân 124 5.4.1 Định nghĩa nhị phân danh sách tuyến tính 124 5.4.2 Định nghĩa nhị phân theo danh sách liên kết: 124 5.4.3 Các thao tác nhị phân 124 5.5 Ba phép duyệt nhị phân (Traversing Binary Tree) 128 5.5.1 Duyệt theo thứ tự trƣớc (Preorder Travesal) 129 5.5.2 Duyệt theo thứ tự (Inorder Travesal) 129 5.5.3 Duyệt theo thứ tự sau (Postorder Travesal) 130 5.6 Cài đặt nhị phân danh sách tuyến tính 130 5.7 Cài đặt nhị phân hoàn toàn cân bằng link list 136 5.8 Cài đặt nhị phân tìm kiếm link list 142 BÀI TẬP CHƢƠNG .151 CHƢƠNG ĐỒ THỊ (Graph) 153 6.1 Những khái niệm đồ thị 153 6.1.1 Các loại đồ thị 153 6.1.2 Các thuật ngữ 156 6.1.3 Đƣờng đi, chu trình, đồ thị liên thơng 157 6.2 Biểu diễn đồ thị máy tính 158 6.2.1 Ma trận kề, ma trận trọng số 158 6.2.2 Danh sách cạnh (cung ) 160 2.3 Danh sách kề 160 6.3 Các thuật tốn tìm kiếm đồ thị 161 6.3.1 Thuật tốn tìm kiếm theo chiều sâu 161 6.3.2 Thuật tốn tìm kiếm theo chiều rộng (Breadth First Search) 163 6.3.3 Kiểm tra tính liên thơng đồ thị 166 6.3.4 Tìm đƣờng hai đỉnh đồ thị 169 6.4 Đƣờng chu trình Euler 171 6.5 Đƣờng chu trình Hamilton 179 6.6 Cây bao trùm 183 6.6.1 Tìm bao trùm đồ thị 184 6.6.2 Tìm bao trùm ngắn 187 6.6.3 Thuật toán Kruskal 190 6.6.4 Thuật toán Prim 193 6.7 Bài tốn tìm đƣờng ngắn 196 6.7.1 Thuật toán gán nhãn 196 6.7 Thuật toán Dijkstra 197 6.7.3 Thuật toán Floy 200 BÀI TẬP CHƢƠNG .204 CHƢƠNG MỞ ĐẦU 1.1 Sơ lƣợc lịch sử lập trình cấu trúc Lập trình cơng việc nặng nhọc khoa học máy tính Có thể nói, suất xây dựng sản phẩm phần mềm thấp so với hoạt động trí tuệ khác Một sản phẩm phần mềm đƣợc thiết kế cài đặt vịng tháng với lao động Nhƣng để kiểm tra tìm lỗi tiếp tục hồn thiện sản phẩm phải thêm chừng năm Đây tƣợng phổ biến tin học năm 1960 xây dựng sản phẩm phần mềm kỹ thuật lập trình tuyến tính Để khắc phục tình trạng lỗi sản phẩm, ngƣời ta che chắn mành che mang tính chất thƣơng mại đƣợc gọi Version Thực chất, Version việc thay sản phẩm cũ cách sửa đổi công bố dƣới dạng Version mới, giống nhƣ: MS-DOS 4.0 tồn thời gian vài tháng thay đổi thành MS-DOS 5.0, MS-DOS 5.5, MS-DOS 6.0 Đây sản phẩm nhƣ ta tƣởng mà cịn tồn lỗi khơng thể bỏ qua đƣợc, MS-DOS 6.0 khắc phục hạn chế MS-DOS 3.3 ban đầu Trong thời kỳ đầu tin học, lập trình viên xây dựng chƣơng trình ngơn ngữ lập trình bậc thấp, q trình nạp theo dõi hoạt động chƣơng trình cách trực tiếp chế độ trực tuyến (on-line) Việc tìm sửa lỗi (debbugging) nhƣ ngày thực đƣợc Do vậy, trƣớc năm 1960, ngƣời ta coi việc lập trình giống nhƣ hoạt động nghệ thuật nhuộm màu sắc cá nhân khoa học Một số ngƣời nắm đƣợc vài ngôn ngữ lập trình, số mẹo vặt tận dụng cấu hình vật lý cụ thể hệ thống máy tính, tạo nên số lạ phần mềm đƣợc coi chuyên gia nắm bắt đƣợc bí ẩn nghệ thuật lập trình Các hệ thống máy tính giai đoạn có cấu hình yếu, nhớ nhỏ, tốc độ thiết bị vào thấp làm chậm trình nạp thực chƣơng trình Chƣơng trình đƣợc xây dựng kỹ thuật lập trình tuyến tính mà bật ngơn ngữ lập trình Assembler Fortran Với phƣơng pháp lập trình tuyến tính, lập trình viên đƣợc phép thể chƣơng trình hai cấu trúc lệnh, cấu trúc lệnh (sequential) nhảy không điều kiện (goto) Hệ thống thƣ viện vào nghèo nàn làm cho việc lập trình trở nên khó khăn, chi phí cho sản phẩm phần mềm lớn, độ tin cậy sản phẩm phần mềm không cao dẫn tới hàng loạt dự án tin học bị thất bại, đặc biệt hệ thống tin học có tầm cỡ lớn Năm 1973, Hoare khẳng định, nguyên nhân thất bại mà ngƣời Mỹ gặp phải phóng vệ tinh nhân tạo phía Vệ nữ ( Sao Kim) lỗi chƣơng trình điều khiển viết Fortran Thay viết: DO 50 I = 12, 523 ( thực số 50 với I 12, 13, , 523) Lập trình viên (hoặc thao tác viên đục bìa) viết thành: DO 50 I = 12.523 (Dấu phảy thay dấu chấm) Gặp câu lệnh này, chƣơng trình dịch Fortran hiểu gán giá trị thực 12.523 cho biến DO50I làm cho kết chƣơng trình sai Để giải vƣớng mắc kỹ thuật lập trình, nhà tin học lý thuyết sâu vào nghiên cứu tìm hiểu chất ngơn ngữ, thuật tốn hoạt động lập trình, nâng nội dung kỹ thuật lập trình lên thành nguyên lý khoa học ngày Kết bật giai đoạn Knuth xuất tập sách mang tên “Nghệ thuật lập trình” giới thiệu tỉ mỉ sở lý thuyết đảm bảo toán học thuật toán xử lý liệu nửa số, xếp tìm kiếm Năm 1968, Dijkstra cơng bố thƣ “ Về nguy hại toán tử goto” Trong cơng trình này, Dijkstra khẳng định, có số lỗi goto gây nên xác định đƣợc điểm bắt đầu lỗi Dijkstra khẳng định thêm: “Tay nghề lập trình viên tỉ lệ nghịch với số lƣợng toán tử goto mà sử dụng chƣơng trình”, đồng thời kêu gọi huỷ bỏ triệt để tốn tử goto ngơn ngữ lập trình ngoại trừ ngơn ngữ lập trình bậc thấp Dijkstra cịn đƣa khẳng định, động thái chƣơng trình đƣợc đánh giá tƣờng minh qua cấu trúc lặp, rẽ nhánh, gọi đệ qui sở lập trình cấu trúc ngày Những kết đƣợc Dijikstra công bố tạo nên cách mạng kỹ thuật lập trình, Knuth liệt kê số trƣờng hợp có lợi goto nhƣ vịng lặp kết thúc chừng, bắt lỗi , Dijkstra, Hoare, Knuth tiếp tục phát triển tƣ tƣởng coi chƣơng trình máy tính với lập trình viên đối tƣợng nghiên cứu kỹ thuật lập trình phƣơng pháp làm chủ phức tạp hoạt động lập trình Năm 1969, Hoare phát biểu tiên đề phục vụ cho việc chứng minh tính đắn chƣơng trình, phát tính bất biến vịng lặp cách coi chƣơng trình vừa mã hố thuật tốn đồng thời chứng minh tính đắn chƣơng trình Sau Dahl, Hoare, Dijiksta phát triển thành ngơn ngữ lập trình cấu trúc Để triển khai nguyên lý lập trình cấu trúc, L Wirth thiết kế cài đặt ngôn ngữ ALGOL W biến thể ALGOL 60 Sau này, L Wirth tiếp tục hồn thiện để trở thành ngơn ngữ lập trình Pascal Đây ngơn ngữ lập trình giản dị, sáng sủa cú pháp, dễ minh họa vấn đề phức tạp lập trình đại đƣợc coi chuẩn mực giảng dạy lập trình Năm 1978, Brian Barninghan Denit Ritche thiết kế ngơn ngữ lập trình C với tối thiểu cấu trúc lệnh hàm phù hợp với tƣ tâm lý của ngƣời lập trình Đồng thời, hai tác giả phát hành phiên hệ điều hành UNIX viết chủ yếu ngôn ngữ C, khẳng định thêm uy C lập trình hệ thống 1.2 Cấu trúc lệnh - Lệnh có cấu trúc- Cấu trúc liệu 1.2.1 Cấu trúc lệnh (cấu trúc điều khiển) Mỗi chƣơng trình máy tính chất mã hoá thuật toán Thuật toán đƣợc coi dãy hữu hạn thao tác sơ cấp tập đối tƣợng vào (Input) nhằm thu đƣợc kết (output) Các thao tác ngơn ngữ lập trình cụ thể đƣợc điều khiển lệnh hay cấu trúc điều khiển, đối tƣợng chịu thao tác đƣợc mơ tả biểu diễn thông qua cấu trúc liệu Trong ngơn ngữ lập trình cấu trúc, cấu trúc lệnh sau đƣợc sử dụng để xây dựng chƣơng trình Dĩ nhiên, không bàn tới cấu trúc nhảy không điều kiện goto ngôn ngữ lập trình cấu trúc trang bị cấu trúc lệnh goto Cấu trúc câu A; lệnh GOTO Cấu trúc rẽ nhánh dạng đầy đủ If (E) A; S Else B; A E Đ A B B; B Sau thực lệnh A thực lệnh B Nếu biểu thức E có giá trị (khác 0) thực A; Nếu E sai thực B; Cấu trúc lặp với điều kiện trƣớc While (E) A; Cấu trúc lặp với điều kiện sau S E A S A; while (E); Đ E Thực A E đúng; A Trong biểu thức E cịn có giá trị thực A; Cấu trúc lặp FOR For (E1; E2;E3) A; E1 E3 S E2 Đ A Thực E1; kiểm tra E2 E2 có giá trị thực A; Quá trình đƣợc lặp lại việc thực E3 kiểm tra E2; Đ A, B : ký hiệu cho câu lệnh đơn lệnh hợp thành Mỗi lệnh đơn lẻ đƣợc gọi lệnh đơn, lệnh hợp thành lệnh hay cấu trúc lệnh đƣợc ghép lại với theo qui định ngôn ngữ, Pascal tập lệnh hay cấu trúc lệnh đƣợc bao thân begin end; C tập lệnh hay cấu trúc lệnh đƣợc bao hai ký hiệu { } E, E1, E2, E3 biểu thức số học logic Một số ngơn ngữ lập trình coi giá trị biểu thức logic (TRUE) sai (FALSE), số ngơn ngữ lập trình khác nhƣ C coi giá trị biểu thức logic có giá trị khác 0, ngƣợc lại biểu thức logic có giá trị sai Cần lƣu ý rằng, chƣơng trình đƣợc thể cấu trúc điều khiển lệnh : tuần tự, tuyển chọn if else, switch case default, lặp với điều kiện trƣớc while , lặp với điều kiện sau while, vòng lặp for chuyển đƣợc chƣơng trình, sử dụng tối thiểu hai cấu trúc lệnh lặp với điều kiện trƣớc while Phuơng pháp lập trình cịn đƣợc gọi phƣơng pháp lập trình hạn chế 1.2.2 Lệnh có cấu trúc Lệnh có cấu trúc lệnh cho phép chứa cấu trúc điều khiển Khi tìm hiểu cấu trúc điều khiển cần xác định rõ vị trí đƣợc phép đặt cấu trúc điều khiển nó, nhƣ phần cấu trúc điều khiển Điều tƣởng nhƣ tầm thƣờng nhƣng có ý nghĩa quan trọng xây dựng kiểm tra lỗi xảy chƣơng trình Nguyên tắc viết chƣơng trình theo cấu trúc: Cấu trúc phải đƣợc viết lọt cấu trúc cha, điểm vào điểm cấu trúc phải nằm hàng dọc Ví dụ sau minh họa cho nguyên tắc viết chƣơng trình: if (E) while (E1) A; else B; while(E2); Trong ví dụ trên, while (E1) A; cấu trúc nằm thân cấu trúc cha if (E) ; B while(E2); cấu trúc thân else Do vậy, câu lệnh while(E1); while(E2) có cấp với nên phải nằm cột, tƣơng tự nhƣ với A, B if với else 1.2.3 Cấu trúc liệu Các ngơn ngữ lập trình cấu trúc nói chung giống cấu trúc lệnh cấu trúc liệu Điểm khác ngơn ngữ lập trình cấu trúc phƣơng pháp đặt tên, cách khai báo, cú pháp câu lệnh tập phép toán đƣợc phép thực cấu trúc liệu cụ thể Nắm bắt đƣợc nguyên tắc này, dễ dàng chuyển đổi cách thể chƣơng trình từ ngơn ngữ lập trình sang ngơn ngữ lập trình khác cánh nhanh chóng mà khơng tốn q nhiều thời gian cho việc học tập ngơn ngữ lập trình Thơng thƣờng, cấu trúc liệu đƣợc phân thành hai loại: cấu trúc liệu có kiểu (Base type) cấu trúc liệu có kiểu ngƣời dùng định nghĩa (User type) hay gọi kiểu liệu có cấu trúc Kiểu liệu bao gồm: Kiểu kí tự (char), kiểu số ngun có dấu (signed int), kiểu số nguyên không dấu (unsigned int), kiểu số nguyên dài có dấu (signed long), kiểu số nguyên dài không dấu (unsigned long ), kiểu số thực (float) kiểu số thực có độ xác gấp đơi (double) Kiểu liệu ngƣời dùng định nghĩa bao gồm kiểu xâu kí tự (string), kiểu mảng (array), kiểu tập hợp (union), kiểu cấu trúc (struct), kiểu file, kiểu trỏ (pointer) kiểu liệu đƣợc định nghĩa hồn tồn nhƣ kiểu danh sách móc nối (link list), kiểu (tree) Kích cỡ kiểu đồng nghĩa với miền xác định kiểu với biểu diễn nhị phân nó, phụ thuộc vào hệ thống máy tính cụ thể Để xác định kích cỡ kiểu nên dùng tốn tử sizeof( type) Chƣơng trình sau liệt kê kích cỡ kiểu Ví dụ 1.1 kiểm tra kích cỡ kiểu #include #include void main(void) { printf(“\n Kích cỡ kiểu kí tự:%d”, sizeof(char)); printf(“\n Kích cỡ kiểu kí tự khơng dấu:%d”, sizeof(unsigned char)); printf(“\n Kích cỡ kiểu số ngun khơng dấu:%d”, sizeof(unsigned int)); printf(“\n Kích cỡ kiểu số ngun có dấu:%d”, sizeof(signed int)); printf(“\n Kích cỡ kiểu số nguyên dài không dấu:%d”, sizeof(unsigned long )); printf(“\n Kích cỡ kiểu số ngun dài có dấu:%d”, sizeof(signed long )); printf(“\n Kích cỡ kiểu số thực có độ xác đơn:%d”, sizeof(float )); printf(“\n Kích cỡ kiểu số thực có độ xác kép:%d”, sizeof(double )); getch(); } Kích cỡ kiểu liệu ngƣời dùng định nghĩa tổng kích cỡ kiểu thành viên Chúng ta dùng tốn tử sizeof(tên kiểu) để xác định độ lớn tính theo byte kiểu liệu Một điểm đặc biệt ý lập trình cấu trúc liệu cấu trúc liệu phải kèm theo phép tốn đó, biến đƣợc gọi thuộc kiểu liệu k=n; while(P[j]>P[k]) k ; temp = P[j]; P[j]=P[k]; P[k]=temp; r=j+1; s=n; while(r b2 > > bk, duyệt theo trình tự từ điển ngƣợc Chẳng hạn với n = 5, có thứ tự từ điển ngƣợc cách phân chia nhƣ sau: 3 1 2 1 63 1 1 Nhƣ vậy, cách chia n Cách chia cuối dãy n số Bây cần xây dựng thuật toán sinh cho cách phân chia chƣa phải cuối Thuật toán sinh cách phân chia kế tiếp: void Next_Division(void){ int i, j, R, S, D; i = k; while(i>0 && C[i]==1)i ; if(i>0){ C[i] = C[i]-1; D = k - i +1; R = D / C[i]; S = D % C[i]; k = i; if(R>0){ for(j=i+1; j0){ k=k+1; C[k] = S; } } else Stop=TRUE; } Văn chƣơng trình đƣợc thể nhƣ sau: #include #define MAX 100 #define TRUE #define FALSE int n, C[MAX], k, count, Stop; void Init(void){ printf("\n Nhap n="); scanf("%d", &n); k=1;count=0; C[k]=n; } void Result(void){ int i; count++; printf("\n Cach chia %d:", count); for(i=1; i0 && C[i]==1) i ; if(i>0){ C[i] = C[i]-1; D = k - i +1; R = D / C[i]; S = D % C[i]; k = i; if(R>0){ for(j=i+1; j0){ k=k+1; C[k] = S; } } else Stop=TRUE; } void Division(void){ Stop = FALSE; while (!Stop){ Result(); Next_Division(); } } void main(void){ clrscr(); Init(); Division(); getch(); } 3.4 Thuật toán quay lui (Back track) Phƣơng pháp sinh giải đƣợc tốn liệt kê ta nhận biết đƣợc cấu hình tốn Tuy nhiên, khơng phải cấu hình sinh đƣợc sinh cách đơn giản từ cấu hình tại, kể việc phát cấu hình ban đầu khơng phải dễ tìm nhiều phải chứng minh tồn cấu hình Do vậy, thuật tốn sinh giải đƣợc toán liệt kê đơn giản 65 Để giải toán tổ hợp phức tạp, ngƣời ta thƣờng dùng thuật toán quay lui (Back Track) đƣợc trình bày dƣới Nội dung thuật tốn xây dựng dần thành phần cấu hình cách thử tất khả Giả sử cần phải tìm cấu hình tốn x = (x 1, x2, , xn) mà i-1 thành phần x1, x2, , xi-1 đƣợc xác định, ta xác định thành phần thứ i cấu hình cách duyệt tất khả có đánh số khả từ ni Với khả j, kiểm tra xem j có chấp nhận đƣợc hay khơng Khi xảy hai trƣờng hợp: Nếu chấp nhận j xác định xi theo j, i=n ta đƣợc cấu hình cần tìm, ngƣợc lại xác định tiếp thành phần xi+1 Nếu thử tất khả mà khơng có khả đƣợc chấp nhận quay lại bƣớc trƣớc để xác định lại xi-1 Điểm quan trọng thuật toán phải ghi nhớ lại bƣớc qua, khả đƣợc thử để tránh trùng lặp Để nhớ lại bƣớc duyệt trƣớc đó, chƣơng trình cần phải đƣợc tổ chức theo chế ngăn xếp (Last in first out) Vì vậy, thuật tốn quay lui phù hợp với phép gọi đệ qui Thuật toán quay lui xác định thành phần thứ i đƣợc mô tả thủ tục Try(i) nhƣ sau: void Try( int i ) { int j; for ( j = 1; j < ni; j ++) { if ( ) { if (i==n) ; else Try(i+1); } } } Có thể mơ tả q trình tìm kiếm lời giải theo thuật tốn quay lui tìm kiếm lời giải sau: Gốc Khả chọn x1 66 Khả chọn x2 với x1 chọn Khả chọn x3 với x1, x2 chọn Hình 3.1 Cây liệt kê lời giải theo thuật toán quay lui 3.4.1 Thuật toán quay lui liệt kê xâu nhị phân độ dài n Biểu diễn xâu nhị phân dƣới dạng b1, b2, , bn, bi{0, } Thủ tục đệ qui Try(i) xác định bi với giá trị đề cử cho bi Các giá trị đƣợc chấp nhận mà khơng cần phải thoả mãn điều kiện (do tốn khơng cần đến biến trạng thái) Thủ tục Init khởi tạo giá trị n biến đếm count Thủ tục kết in dãy nhị phân tìm đƣợc Chẳng hạn với n =3 , tìm kiếm lời giải đƣợc thể nhƣ hình 3.2 Gốc 0 000 1 001 010 011 100 101 110 111 (Hình 3.2 Cây tìm kiếm lời giải liệt kê dãy nhị phân độ dài 3) Văn chƣơng trình liệt kê xâu nhị phân có độ dài n sử dụng thuật toán quay lui đƣợc thực nhƣ sau: #include #include #include #include void Result(int *B, int n){ int i; printf("\n "); for(i=1;i

Ngày đăng: 01/03/2022, 09:34

Tài liệu cùng người dùng

  • Đang cập nhật ...

Tài liệu liên quan