2.2 Lập trình hướng đối tượng• Aây dựng dựa trên nền tảng khái niệm lập trình có cấu trúc • Phân chia bài toán thành các đối tượng và bài toán đi giải quyết mối quan hệ giữa các đối tư
Trang 1Kỹ thuật lập trình
Giảng viên: Đỗ Tuấn Anh
323 C1 ĐHBK Hà Nội
Điện thoại: 0989095167
Trang 2• Tìm hiểu các thao tác vào ra
Trang 3Nội dung trình bày
• Chương 4: Lập trình hướng đối tượng
• Chương 5: Thao tác vào ra với tệp tin
Trang 4Tài liệu tham khảo
• [1] Data Structures and
Algorithm Analysis in C
– Mark Allen Weiss
• [2] Cấu trúc dữ liệu và giải
trúc dữ liệu trên Pascal
– Lê Minh Trung
Trang 5Chương 1: Mở đầu
• Giới thiệu ngôn ngữ lập trình
1 Lịch sử phát triển
2 Các mô hình ngôn ngữ lập trình
Trang 82 Phân loại (tiếp)
• Mệnh lệnh
– Thủ tục: Fortran (1957), Pascal (1970), C(1971), …
– Đối tượng: Smalltalk (1969), C++(1983), Java(1991), C#(2000),…
– Song song: Ada, Occam(1982), C-Linda
Trang 92 Phân loại (tiếp)
• Đặc điểm của ngôn ngữ mệnh lệnh
– Diễn đạt thuật toán sử dụng tập các trạng thái.
– Aử lý lần lượt
– Khai báo dữ liệu
– Kiểu dữ liệu cơ bản, và kiểu dữ liệu mới
– Hai kiểu dữ liệu có cùng tên thì tương đương
– Thay đổi trạng thái thông qua lệnh gán
– Cấu trúc điều khiển là tuần tự
– Chương trình con: hàm, thủ tục với truyền tham số – Hiệu ứng phụ khi sử dụng chương trình con
– Bốn mức: Khối, CT con, module, chương trình
• Đặc điểm của ngôn ngữ khai báo
– Sử dụng các hàm suy luận
– Đánh giá một biểu thức
Trang 102.1 Lập trình cấu trúc
• Chương trình được tổ chức theo các công việc cần thực hiện, phân chia chương trình theo chức năng.
Trang 112.2 Lập trình hướng đối tượng
• Aây dựng dựa trên nền tảng khái niệm lập trình có cấu trúc
• Phân chia bài toán thành các đối
tượng và bài toán đi giải quyết mối
quan hệ giữa các đối tượng
• Các khái niệm
– Class
• Method
• Properties– Object
Trang 12– Bài tập: Viết một chương trình
• Đọc dữ liệu từ file văn bản VB.TAT
• Liệt kê các từ có trong văn bản và đếm xem
có bao nhiêu lần từ đó xuất hiện và xem nó hiển thị ở trang bao nhiêu (mỗi trang 25 dòng)
Trang 13Khái niệm
Software
Program 2 Program 1
Trang 14Ngôn ngữ cấp trung
Ngôn ngữ cấp cao
Ngôn ngữ hợp ngữ
C
Trang 16Cấu trúc chương trình C
main()
• Chương trình C được chia nhỏ thành những đơn vị gọi là hàm
• Không kể có bao nhiêu hàm trong
chương trình, Hệ điều hành luôn trao quyền điều khiển cho hàm main() khi một chương trình C được thực thi.
• Theo sau tên hàm là dấu ngoặc đơn
• Dấu ngoặc đơn có thể có chứa hay không chứa những tham số
Trang 18Biên dịch và thi hành chương trình
Trang 1915
Trang 20Định danh
• Tên của các biến (variables), các hàm (functions), các nhãn (labels) và các đối tượng khác nhau do người dùng định nghĩa gọi là định danh
• Các định danh trong C có phân biệt chữ hoa và chữ thường
Trang 21Các nguyên tắc đặt tên định danh
Tên biến phải bắt đầu bằng một ký tự alphabet Nên tránh đặt tên biến trùng tên các từ khoá
Theo sau ký tự đầu có thể là các ký tự chữ, số …
Tên biến nên mô tả được ý nghĩa của nó
Tránh dùng các ký tự gây lầm lẫn
Nên áp dụng các quy ước đặt tên biến chuẩn khi lập trình
Trang 22Kiểu dữ liệu cơ bản
void
char double
Kiểu dữ liệu cơ bản
float int
Trang 23Những kiểu dữ liệu dẫn xuất
int
( chiếm ít bộ nhớ hơn int )
Kiểu dữ liệu dẫn xuất
Trang 24Kiểu dữ liệu & phạm vi giá trị
Kiểu Dung lượng
tính bằng bit
Phạm vi
Trang 25Biểu thức (Expressions)
Sự kết hợp các toán tử và các toán hạng
Toán hạng Toán Tử
Trang 26Toán tử gán
Toán tử gán (=) có thể được dùng với bất kỳ biểu thức C hợp lệ nào
(Toán tử gán)
Trang 27Bốn Kiểu Toán Tử
Số học (Arithmetic)
Quan hệ
(Relational)
Logic (Logical)
Nhị phân (Bitwise)
Trang 28Vào ra trong C
#include <stdio.h>
• Đây là câu lệnh tiền xử lý
stdio.h là tập tin header (header file)
Chứa các macro sử dụng cho nhiều hàm nhập/xuất trong C
Các macro trong stdio.h giúp các hàm printf(), scanf(), putchar(), getchar() thực thi
Trang 29Các cấu trúc điều khiển
Trang 30Lệnh IF
• if (expression)
statement; else
statement;
Trang 31Lệnh switch
Trang 32 initialize counter là một lệnh gán để khởi tạo biến điều
khiển của vòng lặp trước khi đi vào vòng lặp
conditional test là một biểu thức quan hệ để chỉ định
khi nào vòng lặp sẽ kết thúc
• re-evaluation parameter định nghĩa cách thức thay đổi
của biến điều khiển vòng lặp mỗi khi vòng lặp được
thực thi
Trang 34Vòng lặp Do…While
Trong vòng lặp do while phần thân của vòng lặp
được thực thi trước khi biểu thức điều kiện được kiểm tra
Khi điều kiện mang giá trị False, vòng lặp do while
sẽ được kết thúc, và điều khiển chuyển đến lệnh xuất hiện ngay sau lệnh while
• Cú pháp
do{
statement;
} while (condition);
Trang 36Contrỏ
Trang 37Chương II: Đệ qui
• 1 Mô tả đệ qui
• 2 Bài toán đệ qui
• 3 Khử đệ qui
Trang 381 Mô tả đệ qui
• 1.1 Khái niệm về đệ qui
• 1.2 Các loại đệ qui
• 1.3 Mô tả đệ qui các cấu trúc dữ liệu
• 1.4 Mô tả đệ qui các giải thuật
• 1.5 Các dạng đệ qui đơn giản thường gặp
Trang 391.1 Khái niệm về đệ qui
• Mô tả mang tính đệ qui về một đối
tượng là mô tả theo cách phân tích đối tượng thành nhiều thành phần mà
trong số các thành phần có thành phần mang tính chất của chính đối tượng được mô tả
• Tức là mô tả đối tượng qua chính nó
Trang 401.1 Khái niệm về đệ qui
• Mô tả đệ quy tập số tự nhiên N :
– Số 1 là số tự nhiên ( 1 - N).
– Số tự nhiên bằng số tự nhiên cộng 1.
• Mô tả đệ quy cấu trúc ds(list) kiểu T :
– Cấu trúc rỗng là một ds kiểu T.
– Ghép nối một thành phần kiểu T(nút kiểu
T ) với một ds kiểu T ta có một ds kiểu T.
• Mô tả đệ quy cây gia phả : Gia phảcủa một người bao gồm người đó vàgia phả của cha và gia phả của mẹ
Trang 411.1 Khái niệm về đệ qui
• Mô tả đệ quy thủ tục sắp tăng dãy
• a[m:n] ( dãy a[m], a[m+1], , a[n] ) bằng phương pháp Sort_Merge (SM):
• SM (a[m:n]) ≡ Merge ( SM(a[m :
(n+m) div 2]) , SM (a[(n+m) div 2 +1 : n] )
– Với : SM (a[x : x]) là thao tác rỗng
(không làm gì cả )
– Merge (a[x : y] , a[(y+1) : z]) là thủ tục trộn 2 dãy tăng a [x : y] , a[(y+1) : z] để được một dãy a[x : z] tăng
Trang 421.1 Khái niệm về đệ qui
• Mô tả đệ qui hàm giai thừa
Trang 431.1 Khái niệm về đệ qui
• Mô tả đệ qui gồm hai phần
– Phần neo:trường hợp suy biến của đối tượng
• Ví dụ: 1 là số tự nhiên, cấu trúc rỗng là ds
kiểu T, 0 ! = 1 , SM (a[x:x]) là thao tác rỗng.
– Phần quy nạp: mô tả đối tượng (giải
thuật) thông qua chính đối tượng (giải thuật ) đó một cách trực tiếp hoặc gián tiếp
• Ví dụ:
n! = n * (n – 1) !
SM (a[m:n]) ≡ Merge (SM (a[m:( m+n) div 2] ,
SM (a[(m+n) div 2 +1 : n]) )
Trang 451.2 Các loại đệ qui
• Đệ quy trực tiếp là loại đệ quy mà
đối tượng được mô tả trực tiếp qua nó– A mô tả qua A, B, C, trong đó B, C, không chứa A
• Đệ quy gián tiếp là loại đệ quy mà
đối tượng được mô tả gián tiếp qua nó– A mô tả qua A1 ,A2 , , An Trong đó cómột Ai được mô tả qua A
Trang 461.3 Mô tả đệ qui các cấu trúc dữ liệu
• Cấu trúc dữ liệu có tính đệ quy thường gồm một
số thành phần dữ liệu cùng kiểu được ghép nối theo cùng một phương thức
• Ví dụ :
– Mô tả đệ quy cây nhi phân :Cây nhi phân kiểu T
• Hoặc là một cấu trúc rỗng (phần neo).
• Hoặc là một nút kiểu T (nút gốc) và 2 cây nhị phân kiểu T rời nhau (cây con nhị phân phải, cây con nhị phân trái) kết hợp với nhau
– Mô tả đệ quy mảng nhiều chiều :
• Mảng một chiều là dãy có thứ tự các thành phần cùng kiểu
• Mảng n chiều là mảng 1 chiều mà các thành phần có kiểu mảng n-1 chiều
Trang 471.4 Mô tả đệ qui các giải thuật
• Giải thuật đệ qui
– Giải thuật đệ quy là giải thuật có chứa thao tác gọi đến nó
– Đặc điểm: mô tả một dãy lớn các thao tác bằng một số ít các thao tác trong đó có chứa thao tác gọi lại giải thuật (gọi đệ quy)
– Biểu diễn giải thuật đệ qui
Trang 481.4 Mô tả đệ qui các giải thuật
• Dãy các giai thừa : { n! } ? 1 ,1 , 2 , 6 , 24 , 120
– Ký hiệu FAC(n ) = n !
• FAC(0 ) = 1 ; ( 0 ! = 1 )
• FAC(n ) = n * FAC(n - 1 ) ; ( n ! = n * (n - 1 ) ! ) với n >= 1
• Giải thuật đệ quy tính FAC(n ) là :
– FAC(n )
– if (n = 0 ) then return 1 ;
– else return (n * FAC(n - 1 )) ;
Trang 491.4 Mô tả đệ qui các giải thuật
• Dãy số Fibonaci(FIBO) :{ FIBO (n) } ≡ 1 ,1 , 2 ,
3 , 5 , 8 , 13 , 21 , 34 , 55 , 89 , 144 , 233 , 377 ,
– FIBO(0 ) = FIBO (1 ) = 1 ;
– FIBO(n ) = FIBO (n - 1 ) + FIBO ( n - 2 ) ; với n > = 2
• Giải thuật đệ quy tính FIBO ( n ) là :
– FIBO(n)
– if ((n = 0 ) or ( n = 1 )) then return 1 ;
– else return ( FIBO (n - 1) + FIBO (n - 2)) ;
Trang 501.5 Các dạng đệ qui đơn giản thường gặp
• Đệ qui tuyến tính: là dạng đệ qui trực tiếp đơn giản nhất có dạng
– P Ù {
– If (B) thực hiện S;
– else { thực hiện S* ; gọi P }
– }
Với S , S* là các thao tác không đệ quy
Ví dụ:Hàm FAC(n) tính số hạng n của dãy n!
– Dạng hàm trong ngôn ngữ mã giả :
• { Nếu n = 0 thì FAC = 1 ; /* trường hợp neo*/
• Ngược lại FAC = n*FAC(n-1) }
Trang 511.5 Các dạng đệ qui đơn giản thường gặp
• Chương trình con tính USCLN của 2 số dựa vào thuật toán Euclide
– Dạng hàm trên ngôn ngữ toán học
• USCLN(m , n ) = USCLN(n , m mod n ) khi n ≠ 0
• USCLN(m , 0) = m– Dạng hàm trong C++ :
• int USCLN( int m , int n )
• { if(n == 0 ) return (m) ;
• else return ( USCLN( n , m mod n)) ; }
Trang 521.5 Các dạng đệ qui đơn giản thường gặp (tiếp)
• Đệ qui nhị phân: là đệ qui trực tiếp có dạng như
Với S , S* là các thao tác không đệ quy
Ví dụ : Hàm FIBO(n) tính số hạng n của dãy
Trang 531.5 Các dạng đệ qui đơn giản thường gặp (tiếp)
• Đệ qui phi tuyến: là đệ quy trực tiếp mà lời gọi đệ quy được thực hiện bên trong vòng lặp.
Với S , S* là các thao tác không đệ quy
– Ví dụ: Cho dãy { An } xác định theo công thức truy
hồi :
A0 = 1 ; An = n2 A0 +(n-1)2 A1 + + 22 An-2 + 12 An-1
Trang 541.5 Các dạng đệ qui đơn giản thường gặp (tiếp)
• Dạng hàm đệ quy tính An trên ngôn ngữ C++ là :
Trang 552 Bài toán đệ qui
• 2.1 Tìm giải thuật đệ qui
• 2.2 Một số bài toán giải bằng đệ qui
Trang 562.1 Tìm giải thuật đệ qui
• Thực hiện 3 bước
– Thông số hóa bài toán
– Tìm các trường hợp neo cùng giải thuật giải tương ứng– Tìm giải thuật giải trong trường hợp tổng quát bằng phân rã bài toán theo kiểu đệ quy
Trang 572.1 Tìm giải thuật đệ qui
• Thông số hóa bài toán
– Tổng quát hóa bài toán cụ thể cần giải thành bài toán tổng quát (một họ các bài toán chứa bài toán cần giải )– Tìm ra các thông số cho bài toán tổng quát
• các thông số điều khiển: các thông số mà độ lớn của chúng đặc trưng cho độ phức tạp của bài toán , và giảm đi qua mỗi lần gọi đệ qui.
– Ví dụ
• n trong hàm FAC(n) ;
• a , b trong hàm USCLN(a,b)
Trang 582.1 Tìm giải thuật đệ qui (tiếp)
• Phát hiện trường hợp suy biến
– trường hợp suy biến của bài toán tổng quát
– các trường hợp tương ứng với các gía trịbiên của các biến điều khiển
Trang 592.1 Tìm giải thuật đệ qui (tiếp)
• Phân rã bài toán tổng quát theo phương thức đệ qui
– Tìm phương án (giải thuật ) giải bài toán trong trường hợp tổng quát phân chia nó thành các thành phần
• giải thuật không đệ quy
• bài toán trên nhưng có kích thước nhỏ hơn.
• Ví dụ
– FAC(n) = n * FAC(n -1)
– Tmax(a[1:n]) = max(Tmax(a[1:(n-1)]) , a[n] )
Trang 602.2 Một số bài toán giải bằng đệ qui
• Bài toán tháp Hà Nội
• Bài toán chia phần thưởng
• Bài toán hoán vị
Trang 612.2 Một số bài toán giải bằng đệ qui (tiếp)
• Bài toán tháp Hà Nội
– Truyền thuyết kể rằng : Một nhà toán học Pháp sang thăm Đông Dương đến một ngôi chùa cổ ở Hà Nội thấy các vị sư đang
chuyển một chồng đĩa qúy gồm 64 đĩa với kích thước khác nhau
từ cột A sang cột C theo cách :
• Mỗi lần chỉ chuyển 1 đĩa
• Khi chuyển có thể dùng cột trung gian B
• Trong suốt qúa 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é được đặt trên đĩa có kích thước lớn )
– Khi được hỏi các vị sư cho biết khi chuyển xong chồng đĩa thì đến ngày tận thế !
• Phân tích
– Với chồng gồm n đĩa cần 2 n - 1 lần chuyển
– Giả sử thời gian để chuyển 1 đỉa là t giây thì thời gian để chuyển xong chồng 64 đĩa sẽ là :
– T = ( 2 64 -1) * t = 1.84 10 19 t
– Với t = 1/100 s thì T = 5.8*109 năm = 5.8 tỷ năm
Trang 62Bài toán tháp Hà Nội
• Giải bài toán bằng đệ qui
– Thông số hóa bài toán
• Xét bài toán ở mức tổng quát nhất : chuyển n (n>=0) đĩa từ cột A sang cột C lấy cột B làm trung gian
• THN(n ,A ,B,C) -> với 64 đĩa gọi THN(64,A ,B,C)
• n sẽ là thông số quyết định bài toán – n là tham số điều khiển– Trường hợp suy biến và cách giải
• Với n =1 : THN (1,A,B,C)
– Giải thuật giải bài toán THN (1,A,B,C) là thực hiện chỉ 1 thao tác cơ bản : Chuyển 1 đĩa từ A sang C ( ký hiệu là Move (A , C) )
• THN(1,A,B,C) ≡ { Move( A, C ) }
• THN(0, A,B,C) ≡ { φ }
Trang 63Bài toán tháp Hà Nội
• Phân rã bài toán
– Ta có thể phần rã bài toán TH N (k,A,B,C) : chuyển k đĩa từ cột A sang cột C lấy cột B làm trung gian thành dãy tuần tự 3 công việc sau :
• Chuyển (k -1) đĩa từ cột A sang cột B lấy cột C làm trung gian :
– THN (k -1,A,C,B) (bài toán THN với n = k-1,A= A , B = C , C
Trang 64Bài toán tháp Hà Nội
• Vậy giải thuật trong trường hợp tổng quát (n > 1)
Trang 65Bài toán tháp Hà Nội
• Độ phức tạp của bài toán
– Với n đĩa , gọi f(n) là số các thao tác chuyển một đĩa
• Ta có : f(0) = 0
• f(1) =1
• f(n) = 2f(n -1) + 1 với n > 0– Do đó: f(n) = 1+ 21 + 22 + + 2n-1 = 2n - 1
Trang 66Bài toán tháp Hà Nội
• void THN( int n , char X,Y,Z) {
Trang 67Bài toán chia phần thưởng
• Có 100 phần thưởng đem chia cho
12 học sinh giỏi đã được xếp hạng
Có bao nhiêu cách khác nhau để thực hiện cách chia?
• Tìm giải thuật giải bài toàn bằng
phương pháp đệ quy
Trang 68Bài toán chia phần thưởng
• Giải bài toán bằng đệ qui
– Nhìn góc độ bài toán tổng quát: Tìm số cách chia
m vật (phần thưởng ) cho n đối tượng (học sinh )
Trang 69Bài toán chia phần thưởng
• Các trường hợp suy biến
– m = 0 : mọi học sinh đều nhận được 0 phần thưởng
PART(0 , n ) = 1 với mọi n
– n = 0 , m <> 0 : không có cách chiaPART(m , 0 ) = 0 với mọi m <> 0
Trang 70Bài toán chia phần thưởng
• Phân rã bài toán trong trường hợp
tổng quát
– m < n : n - m học sinh xếp cuối sẽ luôn không nhận được gì cả trong mọi cách chia
Vậy: n > m thì PART(m , n ) = PART(m , m )– m>=n: là tổng
• Học sinh cuối cùng không có phần thưởng
PART(m , n -1 )
• Học sinh cuối cùng có ít nhất 1
PART(m - n , n ) Vậy: n > m PART(m , n ) = PART(m , n -1 ) + PART(m - n , n )
Trang 71Bài toán chia phần thưởng
Trang 72Bài toán tìm tất cả hoán vị của một dãy các phần tử
• Bài toán : In ra tất cả các hoán vị của
dãy A.
• Ví dụ:
– Với dãy A gồm N = 3 phần tử A[1] = a ,
A[2] = b , A[3] = c thì bài toán bắt phải
xuất 6 hoán vị có thể của A :
– Với n=4 thì bài toán phải xuất ra 24 hoán
vị có thể có của A
Trang 73Bài toán tìm tất cả hoán vị của một dãy các phần tử
• Thông số hóa bài toán.
– Gọi HV(v, m )
• v : array[1 N ] of T
• m :integer ; m <= N
• T là một kiểu dữ liệu– Ví dụ : N = 4 , A[1] = 1 , A[2] = 2 , A[3] = 3 , A[4] =
4 thì lời gọi HV(A ,3 ) xuất tất cả hoán vị của A có được bằng cách hoán vị 3 phần tử đầu (có 6 h vị ) :
– Để giải bài toán tổng quát HV(A,N)
Trang 74Bài toán tìm tất cả hoán vị của một dãy các phần tử
• Trường hợp neo
– Vơi m = 1 : HV(v,1): xuất v
• HV(v,1) ≡ print(v) ≡ for k:= 1 to N do write(v[k])
Trang 75Bài toán tìm tất cả hoán vị của một dãy các phần tử
• Phân rã bài toán
– Giữ nguyên các phần tử cuối V[m] , ,V[N] hoán vị m-1
• gọi đệ quy HV(V ,m - 1)
– - Đổi chổ V[m] cho V[1] ,giữ nguyên các phần tử cuối V[m], ,V[N] hoán vị m-1 phần tử đầu
• gọi đệ quy HV(V ,m - 1)
Trang 76Bài toán tìm tất cả hoán vị của một dãy các phần tử
Trang 77SWAP(x , y ) là thủ tục hoán đổi giá trị của 2 đối tượng dữ liệu x ,y )
• Vậy :HV(V , m ) ≡ for k := m downto 1 do begin
– SWAP( V[m], V[k] ) ;
– HV(V,m – 1) ;
– end ;
Trang 78Bài toán tìm tất cả hoán vị của một dãy các phần tử
• const size = Val ; // Val là hằng gía trị
typedef typebase vector[size] ; // typebase là một kiểu dữ liệu có thứ tự
• void Swap( typebase & x , typebase& y) {
typebase t ;
t = x ; x = y ; y = t ; }
•
• void print( const vector &A) {
for(int j= 0 ; j <size ; j++ ) cout<< A[j] ;
} }