1. Trang chủ
  2. » Công Nghệ Thông Tin

Bài giảng Kỹ thuật lập trình: Đệ quy - Trịnh Tấn Đạt

62 8 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 62
Dung lượng 1,9 MB

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

Nội dung

Bài giảng Kỹ thuật lập trình: Đệ quy cung cấp cho người học các kiến thức: Các vấn đề đệ quy thông dụng, khái niệm, phân loại, đệ quy và chia để trị, bài toán tháp Hà Nội, bài toán Edit distance,... Mời các bạn cùng tham khảo.

Trang 1

Đệ Quy (Recursion)

Trịnh Tấn Đạt

Khoa CNTT - Đại Học Sài Gòn

Email: trinhtandat@sgu.edu.vn

Website: https://sites.google.com/site/ttdat88/

Trang 2

▪ Bài toán tháp hà nội

▪ Đệ quy và quy lui (option)

▪ Bài toán Edit distance (option)

▪ Bài toán Closet pairs of points (option)

▪ Bài Tập

Trang 3

Đệ Quy

▪ Đệ quy là kỹ thuật đưa bài toán hiện tại về một bài toán cùng loại, cùng tính chất

(đồng dạng) nhưng ở cấp độ thấp hơn Quá trình này tiếp tục cho đến khi bài

toán được đưa về một cấp độ mà tại đó có thể giải được Từ cấp độ này ta lần

ngược lại để giải các bài toán ở cấp độ cao hơn cho đến khi giải xong bài toán banđầu

▪ Ví dụ: Định nghĩa n giai thừa:

n! = 1*2*3*4*5*…*n → định nghĩa tự nhiên

n*(n-1)! với 0!=1 → định nghĩa bằng đệ quy

Trang 4

Đệ Quy

Trang 6

Đệ Quy - Khái niệm

▪ Kỹ thuật đệ quy: là kỹ thuật định nghĩa một khái niệm có sử dụng

chính khái niệm đang cần định nghĩa.

▪ Hàm đệ quy: là hàm mà trong thân của nó có lệnh gọi lại chính nó

dành cho đối tượng ở cấp thấp hơn.

▪ Ví dụ: Hàm tính n!

Trang 7

Đệ quy

▪ Hai yếu tố cần để tiến hành

một phương thức đệ quy là:

o Có điều kiện dừng (phần cơ sở,

phần neo): Xác định quy luật

của phương thức và tìm giá trị

cụ thể khi thỏa mãn một điều

kiện nhất định.

Nếu hàm đệ quy không có phần

này thì hàm sẽ bị lặp vô hạn và

sinh lỗi khi thực hiện.

thức đệ quy sẽ gọi lại chính nó

nhưng dành cho cấp độ thấp

hơn cho đến khi nó trả về điều

kiện dừng ở bước 1.

S = 1+2+3+…+n

Trang 8

} int main() { cout << "Giai thua cua 5 la:" << factorial(5); return 0;

}

Tính giai thừa n!

Trang 9

Đệ Quy

❖ Cách viết hàm đệ quy

▪ Định nghĩa tác vụ đệ quy thế nào thì viết hàm đệ quy như vậy.

Xét 2 trường hợp neo (thực hiện không đệ quy) và trường hợp

Trang 10

Bài toán dãy số Fibonacci

▪ Fibonacci (1180 - 1250) được biết đến nhiều nhất với dãy số mang tên ông - dãy số Fibonacci.

▪ Dãy số này xuất hiện trong bài toán dưới đây viết trong cuốn Liber

Abaci: "Trong một năm, bắt đầu chỉ từ một đôi thỏ, bao nhiêu đôi thỏ sẽ được sinh ra nếu mỗi tháng một đôi thỏ sinh được một đôi thỏ con và cặp thỏ này lại đẻ được từ tháng thứ hai trở đi?“

▪ Dãy số Fibonacci có nguồn gốc từ bài toán trên là một dãy sao cho mỗi

số hạng, kể từ sau số hạng thứ nhất, bằng tổng của hai số đứng ngay trước nó Dãy số đó là:

1,1,2,3,5,8,13,21,34,55,89,144

Trang 11

Bài toán dãy số Fibonacci

Trang 12

Bài tập Viết hàm đệ quy cho các bài toán

Trang 15

Đệ quy tuyến tính

▪ Đệ quy tuyến tính: bên trong thân hàm chỉ gọi hàm đệ quy 1 lần

▪ Cấu trúc hàm dạng đệ quy tuyến tính

Trang 16

Đệ quy nhị phân

▪ Đệ quy nhị phân: bên trong thân hàm gọi hàm đệ quy 2 lần

▪ Cấu trúc hàm dạng đệ quy nhị phân

Trang 17

Đệ quy lồng

▪ Hàm được gọi là đệ quy lồng nếu tham số trong lời gọi hàm là một lời gọi đệ quy

▪ Cấu trúc hàm dạng đệ qui lồng

Trang 18

Đệ quy hỗ tương

▪ Trong đệ quy tương hỗ thì thường có 2 hàm, và trong thân của hàm này có lời gọi

của hàm kia , điều kiện dừng và giá tri trả về của cả hai hàm có thể giống nhau hoặc khác nhau

Hàm nguyên mẫu (Function

Prototype)

Cấu trúc hàm dạng đệ quy

Trang 19

Function Prototype

▪ Hàm nguyên mẫu cung cấp cho trìnhbiên dịch (compiler) tên của hàm,kiểu dữ liệu mà hàm trả về, số lượngcác đối số mà hàm cần cung cấp,kiểu dữ liệu và thứ tự của các đối sốđó

▪ Hàm nguyên mẫu giúp cho trìnhbiên dịch xác nhận các lời gọi hàm

mà chưa cần định nghĩa hàm đó

Trang 20

Đệ quy phi tuyến

▪ Đệ quy phi tuyến: nếu bên trong thân hàm có lời gọi lại chính nó được đặt bên trong thân của vòng lặp

▪ Cấu trúc hàm dạng đệ quy phi tuyến

Trang 21

#include <stdio.h>

int tinhXn(int);

int tinhXn(int n){

int main(){

Trang 22

{

if (n<5) return n;

return U(n-1) + G(n-2);

} long G(int n) {

if (n<8) return n-3;

return U(n-1) + G(n-2);

}

int main() { int n; cout <<"input n:"; cin >> n;

cout<< "U(n)=" << U(n) << endl; cout<< "G(n)=" << G(n) << endl; system("pause");

return 0;

}

Trang 24

Các hàm đệ quy được gọi lồng nhau dẫn đến việc khó debug, khi debug cần phải nắm rõ

mình đang ở mức đệ quy nào.

Tốc độ xử lí chậm cũng vì lì do liên tục gọi các hàm lồng nhau.

Với input lớn, hàm đệ quy có thể dẫn đến việc bùng nổ trong việc gọi hàm, dẫn đến tình

trạng tràn bộ nhớ stack (stack overflow)

Trang 25

Các bước tìm giải thuật đệ quy cho bài toán

▪ Bước 1: Thông số hóa bài toán.

▪ Bước 2: Tìm các trường hợp cơ bản (phần neo) cùng giải thuật tương ứng cho các trường hợp này.

▪ Bước 3: Tìm giải thuật giải trong trường hợp tổng quát ( phần đệ quy ) bằng cách phân rã bài toán theo kiểu đệ quy

Trang 26

Thông số hóa bài toán

▪ Chuyển bài toán cần giải thành bài toán tổng quát

▪ Tìm ra các thông số cho bài toán tổng quát, đặc biệt là nhóm các thông số biểu thị kíchthước của bài toán

▪ Ví dụ:

o Bài toán tính n!: n là tham số tổng quát, biểu thị kích thước bài toán

o Bài toán tính giá trị Ackermann’s: n và m là tham số tổng quát, biểu thị kích thước bài

toán

Trang 27

Xác định thành phần cơ bản của bài toán

▪ Xác định trường hợp neo của bài toán tổng quát

▪ Đây là các trường hợp tương ứng với các giá trị biên củac ác biến điều khiển mà giảithuật giải không đệ quy Thông thường trong trường hợp này giải thuật rất đơn giản

▪ Ví dụ:

o Giá trị giai thừa của n=0 hoặc n=1 là 1

o Giá trị hàm U(n) = n, với n<5 (ví dụ 2)

o Giá trị hàm Ackerman = n+1, với m=0 và n>0

Trang 28

Phân rã bài toán theo phương thức đệ quy

▪ Tìm giải thuật giải bài toán trong trường hợp tổng quát bằng cách phân chia nó thànhcác thành phần:

o hoặc có giải thuật không đệ quy

o hoặc là bài toán trên nhưng có kích thước nhỏ hơn (có đệ quy)

▪ Mục đích của bước thực hiện này là tìm giải thuật để giải bài toán theo hướng đệ quyvới giá trị tham số tổng quát

▪ Ví dụ

Trang 29

Ví dụ

Trang 30

▪ Hàm tìm Max trong Array dùng đệ quy

int max2So (int x, int y)

Trang 31

Khử đệ quy

▪ Là quá trình chuyển đổi 1 giải thuật đệ quy thành giải thuật không đệ quy

▪ Chưa có giải pháp cho việc chuyển đổi này một cách tổng quát Ta thường khử đệquy cho đệ quy tuyến tính

▪ Cách tiếp cận:

o Dùng quan điểm đệ quy để tìm giải thuật cho bài toán

o Mã hóa giải thuật đệ quy

o Khử đệ quy để có giải thuật không-đệ-quy

▪ Có 2 cách thường dùng :

▪ Khử đệ quy bằng vòng lặp

▪ Khử đệ quy dùng Stack

Trang 32

Khử đệ quy bằng vòng lặp

▪ Ý tương: Lưu lại các trị của các lần tính toán trước làm dữ liệu cho việc tính toán củalần sau

Trang 33

Các vấn đề đệ quy thông dụng

▪ Hệ thức truy hồi: Hệ thức truy hồi của 1 dãy An là công thức biểu diễn phần tử Anthông qua 1 hoặc nhiều số hạng trước của dãy

Trang 35

Các vấn đề đệ quy thông dụng

▪ Chia để trị

o Chia bài toán thành nhiều bài toán con.

o Giải quyết từng bài toán con.

o Tổng hợp kết quả từng bài toán con để ra lời giải.

Trang 36

Chia để trị

Ví dụ: Tìm kiếm nhị phân trên mảng tăng dần

Trang 38

Chia để trị

Ví dụ: Tìm kiếm nhị phân trên mảng tăng dần

// Hàm tìm kiếm nhị phân sử dụng giải thuật đệ quy

int binarySearch(int arr[], int l, int r, int x)

return binarySearch(arr, l, mid - 1, x) ;

// Nếu arr[mid] < x, thực hiện tìm kiếm nửa phải của mảng

return binarySearch(arr, mid + 1, r, x) ;

}

// Nếu không tìm thấy

return -1;

}

// Hàm tìm kiếm nhị phân sử dụng giải thuật khử đệ quy

int binarySearch(int arr[], int n, int x) {

int r = n - 1; // chỉ số phần tử cuối int l = 0; // Chỉ số phần tử đầu tiên

while (r >= l)

{

int mid = l + (r - l) / 2;

if (arr[mid] == x) return mid;

// Nếu arr[mid] > x, cập nhật lại right

Trang 39

Chia để trị

❖ Một số bài toán khác

▪ Fast power: an = a*an-1 ; Nếu n chẵn: an = an/2 * an/2

▪ Bài toán tháp Hà Nội

▪ Các giải thuật sắp xếp: QuickSort, MergeSort

▪ Closet pair of points

❖Lưu ý

▪ Khi bài toán lớn được chia thành các bài toán nhỏ hơn mà những bài toán nhỏ hơn này không đơn giản nhiều so với bài toán gốc thì không nên dùng kỹ thuật chia để trị

Trang 40

Bài toán tháp Hà Nội

▪ Mô tả bài toán: chuyển n đĩa từ cột A sang cột C có cột B làm trung gian, với yêu cầu sau:

o Mỗi lần di chuyển 1 đĩa

o Khi chuyển có thể dùng cột trung gian B

o Trong quá trình chuyển các chồng đĩa ở các cột luôn được xếp đúng (đĩa có kích thước bé đặt trên đĩa có kích thước lớn)

Trang 41

Bài toán tháp Hà Nội

Số đĩa là n có thể được giải với số bước tối thiểu là 2 n-1

Trang 42

Bài toán tháp Hà Nội

Tìm phần cơ sở và cách giải

n=1: HaNoiTower(1, A, B, C) : tìm dãy thao tác để chuyển chồng 1 đĩa từ cột A sangcột C, lấy cột B làm cột trung gian

Trang 43

Bài toán tháp Hà Nội

❖ Phân rã bài toán:

▪ HaNoiTower(n, A, B, C): chuyển n đĩa từ cột A sang cột C, lấy cột B làm trung gianthành dãy tuần tự 3 công việc sau:

Chuyển (n-1) đĩa từ cột A sang cột B, lấy cột C làm trung gian :

Chuyển 1 đĩa từ cột A sang cột C :

Chuyển (n-1) đĩa từ cột B sang cột C, lấy A làm trung gian :

Trang 44

Bài toán tháp Hà Nội

❖ Cài đặt

Trang 45

Các vấn đề đệ quy thông dụng

❖ Lần ngược (Backtracking)

▪ Tại bước có nhiều lựa chọn, ta chọn

thử 1 bước đểđi tiếp

▪ Nếu không thành công thì “lần

ngược” chọn bước khác

▪ Nếu đã thành công thì ghi nhận lời

giải này đồng thời “lần ngược” để

truy tìm lời giải mới

▪ Thích hợp giải các bài toán kinh điển

như bài toán 8 hậu và bài toán mã đi

tuần

Trang 46

Edit Distance (option)

▪ Edit distance (hay còn gọi là Levenshtein distance) giữa hai chuỗi S1 và S2 là sốbước ít nhất biến chuỗi S1 thành chuỗi S2 thông qua 3 phép biến đổi là:

o xoá 1 ký tự (delete)

o thêm 1 ký tự ( insert)

o thay ký tự này bằng ký tự khác (replace)

▪ Ví dụ: Khoảng cách Levenshtein giữa 2 chuỗi "kitten" và "sitting" là 3, vì phảidùng ít nhất 3 lần biến đổi

kitten -> sitten (thay "k" bằng "s")

sitten -> sittin (thay "e" bằng "i")

sittin -> sitting (thêm ký tự "g")

Trang 47

We can convert str1 into str2 by replacing 'a' with 'u'.

Input: str1 = "su n day", str2 = "s at u r day"

Output: 3

Replace 'n' with 'r’

Insert t Insert a

Trang 48

Edit Distance

❖ Ứng dụng:

▪ Xử lý ngôn ngữ tự nhiên (Natural Language Processing- NLP): spell correction

▪ Bioinformatics: tính độ tương đồng của các chuỗi DNA (strings of the letters A, C, G and T)

▪ Optical Character Recognition (OCR): xem như một metric để đánh giá performance của hệ thống OCR.

▪ Fuzzy search: tìm kiếm một xâu "gần giống" (thay vì "giống hệt") so với một xâu cho trước

▪ …

Trang 49

Edit Distance

▪ Solution: dựa vào

o Kỹ thuật Đệ quy

o Kỹ thuật Qui hoạch động (thường dùng)

*Tìm hiểu về kỹ thuật Qui hoạch động giải bài toán này

https://vi.wikipedia.org/wiki/Kho%E1%BA%A3ng_c%C3%A1ch_Levenshteinhttp://www.giaithuatlaptrinh.com/?p=99

jvElaOXAKkw

Trang 50

https://viblo.asia/p/khoang-cach-levenshtein-va-fuzzy-query-trong-elasticsearch-Edit Distance

❖ Dùng đệ quy:

▪ Idea: xử lý tất cả các ký tự trong cả hai chuỗi một cách tuần tự từ phải sang tráiGiả sử

m: Length of str1 (first string)

n: Length of str2 (second string)

▪ Điều kiện 1: Nếu chuỗi str1 là empty (m ==0), thêm (insert) tất cả các ký tự trong

chuỗi str2 vào chuỗi str1 (có ít nhất n phép biến đỏi)

▪ Điều kiện 2: Nếu chuỗi str2 là empty (n==0), xóa (delete) tất cả các ký tự trong

chuỗi str1 (có ít nhất m phép biến đỏi)

▪ Trường hợp m và n khác 0: Ta xét từng ký tự trong cả hai chuỗi từ phải sang trái

Có hai trường hợp xảy ra

Trang 51

Edit distance

▪ TH1: Nếu hai ký tự cuối cùng của hai chuỗi giống nhau Loại bỏ những

ký tự cuối và xem xét lại phần còn lại của hai chuỗi Chúng ta lập lại quá trình xử ký ( gọi đệ quy) cho hai chuỗi có độ dài m-1 , n-1

Ví dụ : xét hai chuỗi : “g o ” và “hall ogọi đệ quy tính edit distance

cho hai chuỗi “g” và “hall”

Trang 52

Edit distance

▪ TH2: Nếu hai ký tự cuối khác nhau (tồn tại một phép biến đổi, +1) Chúng ta xemxét tất cả phép biến đôi trên ký tự cuối của chuỗi str1 Tính chi phí nhỏ nhất dựatrên đệ quy cho ba phép biến đổi và lấy giá trị nhỏ nhất của ba giá trị

Insert: Recur for m and n-1Delete: Recur for m-1 and nReplace: Recur for m-1 and n-1

Trang 53

Edit distance

Ví dụ: xét hai chuỗi “g” và “hall” : hai ký tự cuối khác nhau Xem xét ba trường hợpxảy ra Tìm số lượng phép biến đối ít nhất biên g thành hall.

(chiều dài chuỗi thứ 2 giảm đi 1).

“hall” (chiều dài chuỗi thứ 1 giảm đi 1) Chuỗi thứ 1 trở thành “hallg”, sau đó delete

giảm di 1) Chuỗi thứ 1 trở thành “halg”, sau đó replace“g” thành “l” để trở thành chuỗi thứ 2.

Trang 54

Closet Pair of Points (option)

Bài toán: tìm cặp điểm có khoảng cách (Euclid distance) gần nhất trong mặt phẳng

Solution: Dùng đệ quy và chia để trị

Trang 55

Closet Pair of Points

Input: Mảng P[] chứa n điểm trong mặt phẳng Oxy

Output: Khoảng cách nhỏ nhất giữa hai điểm trong mảng P[]

** Tiền xử lý: sắp xếp các điểm tăng dần theo tọa độ x

Thuật toán : 7 bước

B1: Tìm điẻm giữa (mid) trong mảng P[], có thể láy P[n/2]

Trang 56

Closet Pair of Points

B4: Xem xét các cặp điểm: một điẻm

nằm bên trái đường biên, điểm còn lại

nằm bên phải

Tìm các điẻm có khoảng cách (theo

tọa độ x) đến đường biên nhỏ hơn d

Lưu các điểm đó vào mảng strip[]

Trang 58

Bài tập

3 Viết hàm đệ quy tìm chiều dài của một chuỗi.4

Trang 59

Bài tập

5

Trang 60

Bài tập

6.

7 Cho một mảng A đã được sắp xếp tăng dần Viết chương trình tìm kiếm một phần tử k

trong mảng A

a) Không dùng đệ quy (tìm kiếm tuyến tính)

b) Dùng đệ quy (tìm kiếm nhị phân)

8. Viết hàm tính fast power a n dùng chia để trị

Trang 61

Bài tập (option)

1 Tìm hiều về bài toán 8 quân hậu

2 Tìm hiểu về bài toán mã đi tuần

Trang 62

Bài tập (option)

1 Cài đặt bài toán Edit Distance

a) Nhập hai chuỗi từ bàn phím Xuất kết quả ra màn hình.

b) Thao tác trên FILE

Input: file text chứa các cặp chuỗi cần tính Mỗi cặp chuỗi cách nhau bằng một khoảng trắng Output: lưu kết quả ra file

2 Cài đặt bài toán Closet Pair of Points

Ngày đăng: 11/05/2021, 03:08

TỪ KHÓA LIÊN QUAN

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