Cho một dãy các số thực a1,a2,…,an. Tìm giá trị lớn nhất m của các số đã cho và chỉ số lớn nhất i trong các số đạt giá trị m.
Trang 1Tài liệu tham khảo
1 Cấu trúc dữ liệu và giải thuật
Trang 2Chương 1 Giải thuật
1.1 Khái niệm giải thuật
1.2 Thiết kế giải thuật
1.3 Phân tích và đánh giá giải thuật
1.1 Khái niệm giải thuật
1.1.1 Giải thuật là gì?
1.1.2 Cấu trúc dữ liệu
1.1.3 Diễn đạt giải thuật
Trang 3xuất phát từ số cuối cùng của dãy là an và sẽ so
sánh với các số trước đó , khi tìm thấy một giá trị
lớn hơn thì ta ghi lại (đánh dấu) và lại tiếp tục so
sánh số này với các số trước đó , công việc sẽ
được thực hiện cho đến khi đã so với số đầu tiên
Trang 41.1.1 Giải thuật là gì?
Giải thuật là:
Cách làm để giải quyết bài toán
Một dãy có trình tự các thao tác trên một số đối
thực hiện ta đạt được kết quả mong muốn
Một giải thuật có
Đầu vào (Input): tập các đối tượng (dữ liệu)
Đầu ra(Output): một tập các giá trị (thông tin)
Các bướcthực hiện
1.1.1 Giải thuật là gì?
Các đặc trưng của giải thuật
Tính có đại lượng vào/ra
Tính xác định
Tính hữu hạn (tính dừng)
Tính tổng quát
Tính hiệu quả
Một vài đặc điểm cần lưu ý
Không cần biết giá trị cụ thể của kết quả sau mỗi bước, chỉ
cần biết cách chuyển từ bước trước tới bước sau;
Kết quả cụ thể của giải thuật có thể không phải là kết quả
đúng (chính xác) mặc dầu phương pháp là đúng
Trang 51.1.2 Cấu trúc dữ liệu
Dữ liệu có cấu trúc:
Tập hợp dữ liệu
Có mối quan hệ với nhau trong bài toán xác định
Lựa chọn cấu trúc dữ liệu và giải thuật thích hợp: rất
quan trọng
Vídụ: viết chương trình tìm kiếm số điện thoại theo tên đơn
vị
Giải thuật + Dữliệu = Chương trình
Biểu diễn cấu trúc dữ liệu trong bộ nhớ:
Lưu trữ trong
Thông qua các biến
Lưu trữ ngoài
Tệp (định kiểu và không định kiểu)
1.1.3 Diễn đạt giải thuật
Ngôn ngữ tự nhiên
Ngôn ngữ liệt kê các bước
Trang 61.1.3 Diễn đạt giải thuật
Giả ngôn ngữ (máy tính)
Phép toán logic: &&, ||, !
Giá trị logic: true, false
Biến được chỉ số hóa: ai, aij
Thứ tự ưu tiên của các phép toán:
như trong ngôn ngữ C và các ngôn ngữ chuẩn khác
Trang 71.1.3 Diễn đạt giải thuật
Lệnh vào/ra:
read (<danh sách biến>)
write (<danh sách biến hoặc dòng ký tự>)
Gọi chương trình con:
<tên hàm> (<danh sách tham số thực sự>)
1.1.3 Diễn đạt giải thuật
Nối tiếp đoạn lệnh
Luồng thực hiện
Trang 81.1.3 Diễn đạt giải thuật
Trang 91.1.3 Diễn đạt giải thuật
Trang 101.1.3 Diễn đạt giải thuật
Ngôn ngữ lập trình
Cài đặt giải thuật: ngôn ngữ C/C++
1.2 Thiết kế giải thuật
1.2.1 Mô đun hóa và việc giải quyết bài toán
1.2.2 Phương pháp tinh chỉnh từng bước
(Stepwise Refinement) 1.2.3 Ví dụ
Trang 111.2.1 Mô đun hóa và việc giải quyết
bài toán
Module hóa bài toán
Chia bài toán lớn (module chính) thành các bài toán (module)
nhỏ hơn
Mỗi module thực hiện công việc cụ thể nào đó
Lặp đi lặp lại cho đến khi các module là cô đọng, đơn thể và biết
cách giải quyết
=> chiến thuật “Chia để trị”
1.2.1 Mô đun hóa và việc giải quyết
bài toán
Thiết kếTopdown – từ đỉnh xuống, hay từ khái
quát đến chi tiết.
Bước 1: Xác định dữ kiện đầu vào, yêu cầu đặt ra
Bước 2: Xác định các công việc chủ yếu (mỗi công việc
tương đương với 1 module)
Bước 3: Giải quyết từng công việc một cách chi tiết
bằng cách lặp đi lặp lại bước 1 + 2
Ví dụ: Bài toán “Quản lý và bảo trì các hồ sơ về
học bổng của sinh viên, thường kỳ lập báo cáo
tổng kết”.
Trang 121.2.1 Mô đun hóa và việc giải quyết
bài toán
Thiết kếTopdown – Bước 1
Bước 1: Xác định dữ kiện đầu vào và các yêu cầu
đặt ra
Đầu vào: Tập các file bao gồm các thông tin vềhọc bổng
của sinh viên: Mã SV, ĐiểmTB, Mức HB
Yêu cầu:
Tìm kiếm và hiển thị thông tin của bất kỳ sinh viên nào
Cập nhật thông tin của một sinh viên cho trước
In bản tổng kết
1.2.1 Mô đun hóa và việc giải quyết
bài toán
Thiết kếTopdown – Bước 2
Bước 2: Xác định các công việc chủ yếu
Đọc các thông tin của sinh viên từ file vào bộ nhớ trong
(Đọc file)
Xử lý các thông tin (Xử lý thông tin)
Lưu thông tin đã cập nhật vào file (Ghi file)
Trang 131.2.1 Mô đun hóa và việc giải quyết
bài toán
Thiết kế Topdown – Bước 3
Bước 3: Lặp lại bước 1 + 2
Đọc file:
Đầu vào: File thông tin trên đĩa
Yêu cầu: Đọc file và lưu vào mảng: mỗi phần tử mảng lưu
thông tin của một sinh viên
Đã cô đọng
Ghi file:
Đầu vào: Mảng lưu thông tin của các sinh viên
Yêu cầu: Lưu trở lại file
Tìm một sinh viên cho trước
Hiển thị thông tin của sinh viên
Cập nhật thông tin của sinh viên
In bản tổng kết
Trang 141.2.2 Phương pháp tinh chỉnh từng bước
Ban đầu giải thuật được trình bày ở dạng ngôn ngữ
Bài toán: “Sắp xếp một dãy n số nguyên theo thứ tự tăng dần”
Ngôn ngữ tự nhiên của giải thuật:
Từ dãy số nguyên chưa được sắp xếp chọn ra số nhỏ nhất và
đặt vào đầu dãy đã được sắp xếp
Loại số nguyên đó ra khỏi dãy chưa được sắp xếp
Lặp lại cho đến khi dãy chưa được sắp xếp là rỗng
Trang 151.2.3 Ví dụ
Cấu trúc dữ liệu:
Dãy số ban đầu được lưu trữ trong một mảng một chiều
Dãy đã sắp xếp sẽ được lưu trùng với dãy chưa sắp xếp
=> Giải thuật: Đặt số nhỏ nhất của lượt thứ i vào dãy đã sắp
xếp bằng cách đổi chỗ với số thứ i trong dãy
So sánh “số nhỏ nhất” và ai+1, số nào nhỏ hơn thì coi là “số
nhỏ nhất” (nếu ai+1< ajthì j = i+1)
Tiếp tục so sánh “số nhỏ nhất” với ai+2, ai+3, …an-1, an
Trang 16 Bài tập: Trình bày ngôn ngữ tự nhiên, các bước tính chỉnh và
giải thuật để giải bài toán: “Cho một dãy các số nguyên
a1,a2,…,an Tìm giá trị lớn nhất m của các số đã cho và chỉ số
lớn nhất i trong các số đạt giá trị m
Trang 17Giải bài tập
Ngôn ngữ tự nhiên
Vì phải tìm số lớn nhất với chỉ số lớn nhất, ta sẽ xuất phát từ số cuối
cùng của dãy là anvà sẽ
so sánh với các số trước đó , khi tìm thấy một giá trị lớn hơn thì ta ghi lại
(đánh dấu) và lại tiếp tục so sánh số này với các số trước đó ,
công việc sẽ được thực hiện cho đến khi đã so với số đầu tiên
Tinh chỉnh lần đầu
0) xuất phát từ số cuối cùng của dãy là an(i=n) và tạm thời coi giá trị lớn
nhất m là an, tất nhiên lúc này k=n;
1) Xét i=i-1;
2) Nếu i=0, thì viết ra k, m (việc tìm là xong - thuật toán kết thúc).
3) Nếu ngược lại thì (so sánh aivới m)
Nếu ai> m thì coi m là ai, k=i
Quay lại 1) (Chuyển qua xét số trước số thứ i).
{ i=n; m=aii=i-1;
While (i > 0)
{
If (m<ai) {
m=ai; k=i;
} i=i-1;
}
Trang 181 3 Phân tích giải thuật
1.3.1 Tại sao cần phân tích giải thuật?
1.3.2 Phân tích thuật toán
1.3.3 Độ phức tạp giải thuật
1.3.1.Tại sao cần phân tích giải thuật?
Viết một chương trình chạy thông là chưa đủ
Chương trình có thể thực hiện chưa hiệu quả!
Nếu chương trình chạy trên một tập dữ liệu lớn, thì
thời gian chạy sẽ là một vấn đề cần lưu ý
Vídụ: Bài toán lựa chọn
Cho một dãy gồm N số, hãy tìm phần tử lớn thứ k,
Trang 191.3.1.Tại sao cần phân tích giải thuật?
Thuật toán2:
(1) Đọc k phần tử đầu tiên vào mảng và sắp xếp chúng
theo thứ tự giảm dần
(2) Mỗi phần tử còn lại chỉ đọc một lần
Nếu phần tử đó là nhỏ hơn phần tử thứ k, bỏ qua
Ngược lại, đặt nó vào vị trí phù hợp của mảng, đẩy phần
tử hiện tại ra khỏi mảng
(3) Phần tử tại vị trí thứ k là phần tử cần tìm
1.3.1.Tại sao cần phân tích giải thuật?
Thuật toán nào là tốt hơn khi
Trang 201.3.2 Phân tích thuật toán
Đối tượng phân tích
Chúng ta chỉ phân tích những thuật toánđúng
Một thuật toán là đúng?
Nếu,với một dữ liệu đầu vào, thuật toán dừng và đưa ra kết quả
đúng
Thuật toán không đúng
Có thể không dừng với một số dữ liệu đầu vào
Dừng nhưng đưa ra kết quả sai
Dự đoán lượng tài nguyên mà thuật toán yêu cầu
Tài nguyên gồm
Bộ nhớ
Băng thông giao tiếp
Thời gian tính –Thời gian thực hiện GT(thường là quan trọng nhất)
1.3.2 Phân tích thuật toán
Thời gian thực hiện giải thuật
Các nhân tố ảnh hưởng đến thời gian tính
Máy tính
Chương trình dịch
Thuật toán được sử dụng
Dữ liệu đầu vào của thuật toán
Giá trịcủa dữ liệu ảnh hưởng đến thời gian tính
Thông thường, kích thước của dữ liệu đầu vào là nhân tố
chínhquyết định thời gian tính
Với bài toán sắp xếp: số phần tử cần sắp xếp
Với bài toán nhân ma trận: kích thước (số phần tử) của
2 ma trận
Trang 211.3.2 Phân tích thuật toán
Độ phức tạp về thời gian
Thuật toán A mất 2 phút để chạy với dữ liệu đầu vào X.
Thuật toán B mất 1 phút 45 giây để chạy với cùng dữ liệu X.
Liệu B có phải là thuật toán “tốt hơn” A?
Không hẳn là như vậy!
Chỉ kiểm tra với một bộ dữ liệu X Có thể với dữ liệu X này B chạy nhanh
hơn A, nhưng với phần lớn các dữ liệu khác B chạy chậm hơn A
Thuật toán A bị ngắt bởi các tiến trình khác.
Thuật toán B được chạy trên máy tính cócấu hình cao hơn.
Phép đo cần phải không phụ thuộc vào máy
Đo bằng cách đếm số các phép tính cơ sở (phép gán, phép so
sánh, các phép tính số học, v.v.).
Ta thường ký hiệu số lượng các phép tính, các thao tác cơ bản (gán,
so sánh) của một thuật toán là f(n).
1.3.2 Phân tích thuật toán
Trang 221.3.2 Phân tích thuật toán
Trường hợp tồi nhất / trung bình / tốt nhất
Thời gian tính tốt nhất: Thời gian tối thiểu cần thiết để thực hiện
thuật toán với mọi bộ dữ liệu đầu vào kích thước n
Thời gian tính tồi nhất: Thời gian nhiều nhất cần thiết để thực
hiện thuật toán với mọi bộ dữ liệu đầu vào kích thước n
Thời gian trung bình: cần thiết để thực hiện thuật toán trên tập
hữu hạn các đầu vào kích thước n.
Việc xác định độ phức tạp tính toán nhiều khi còn phụ thuộc vào
tình trạng của dữ liệu Do đó ta phải xét tới f(n) trong trường hợp
thuận lợi nhất, f(n) trong trường hợp xấu nhất và f(n) trong
trường hợp trung bình Tuy nhiên việc xác định f(n) trong trường
hợp trung bình thường khó khăn Vì vậy, trong các trường hợp
f(n) xác định khó khăn ta lấy f(n) trong trường hợp xấu nhất để
đánh giá độ phức tạp tính toán của giải thuật
1.3.2 Phân tích thuật toán
Điều quan trọng đối với giải thuật là
Mất bao nhiêu giây để chạy với dữ liệu đầu vào có kích
thước n?
Thời gian tính phụ thuộc vào kích thước dữ liệu đầu vào
Một số tốc độ thay đổi của thời gian tính khi n tăng.
Thuật toán có thời gian hằng số: nếu thời gian chạy của nó
là không đổi khi kích thước dữ liệu thay đổi
Thuật toán có thời gian tuyến tính: nếu thời gian chạy của
nó tỷ lệ thuận với n
Thuật toán có thời gian tính là hàm số mũ nếu thời gian
chạy tăng theo một hàm số mũ của n
Trang 231.3.3 Độ phức tạp giải thuật
Định nghĩa bậc O-lớn
Giả sử f(n) và g(n) là hai hàm xác định trên một tập hợp các số
nguyên dương Ta nói rằng f(n) có bậc O-lớn của g(n), và viết
f(n)=O(g(n)) hoặc f=O(g) nếu tồn tại hằng số C>0 sao cho với n
đủ lớn, các hàm f(n) và g(n) đều dương, đồng thời f(n)<Cg(n)
O(g) đặc trưng cho độ tăng của hàm
Ví dụ Nếu f(n) là đa thức adnd+ad-1nd-1+…+a1n+a0 trong đó ad>0
thì f(n)=O(nd)
Một vài tính chất
Nếu f1(n)=Og(n), f2(n)=Og(n) thì f1+f2=O(g)
Nếu f1=O(g1), f2=O(g2) thì f1f2=O(g1g2)
Nếu tồn tại giới hạn thì f=O(g)
Với mọi số ε>0 thì log(n)=O(n ε )
) (
) ( lim
n g
n f
n→ ∞
1.3.3 Độ phức tạp giải thuật
Định nghĩa
Một thuật toán được gọi là có độ phức tạp đa thức (hoặc
gọi là có thời gian đa thức) nếu số phép tính cần thiết để
thực hiện thuật toán không vượt quá O(logd(n)), trong đó n
là độ lớn của dữ liệu đầu vào và d là số nguyên dương nào
đó
Để ước lượng độ phức tạp của giải thuật người ta
thường so sánh khối lượng tính toán f(n) của một
giải thuật với một hàm g(n) nào đó thông qua bậc
O-lớn của g(n), mà thông thường g(n) là các hàm sau
đây (với thứ tự có độ tăng lớn dần):
Trang 241.3.3 Độ phức tạp giải thuật
Trang 251.3.3 Độ phức tạp giải thuật
Định nghĩa
Giả sử f(n) và g(n) là hai hàm xác định trên một
tập hợp các số nguyên dương Ta nói rằng f(n) có
bậc Omega-lớn của g(n), và viết f(n)= Ω(g(n)) hoặc
f= Ω(g) nếu tồn tại hằng số C>0 sao cho với n đủ
lớn, các hàm f(n) và g(n) đều dương, đồng thời
Giả sử f(n) và g(n) là hai hàm xác định trên một tập hợp
các số nguyên dương Ta nói rằng f(n) có bậc Theta-lớn
của g(n), và viết f(n)=Θ(g(n)) hoặc f= Θ(g) nếu thỏa mãn
Trang 261.3.3 Độ phức tạp giải thuật
Như vậy, để xác định độ phức tạp của một giải thuật khi đã biết hàm
ước lượng khối lượng tính toán cần thiết của giải thuật đó, ta cần tính
giới hạn của tỉ số
và đánh giá theo quy tắc sau
Nếu giới hạn của tỉ số
không xác định thì không kết luận được mối liên hệ giữa độ phức tạp
f(n) và g(n)
)(
)(lim
n g
n f
&
)(
)(
)(
&
)(,
,0
0)
(
)(lim
g f g f
g f
g f g f c
n g
n f
n
)(
)(lim
n g
n f
Trang 271.3.3 Độ phức tạp giải thuật
Xác định độ phức tạp
Các câu lệnh kế tiếp
Quy tắc cộng: độ phức tạp của khối lệnh kế tiếp là tổng khối
lượng tính toán của các câu lệnh
Nếu f1(n)=Og1(n), f2(n)=Og2(n) thì f1+f2=Omax(g1,g2)
Với một vòng lặp
độ phức tạp là tổng khối lượng tính toán số học và so sánh
của các câu lệnh bên trong vòng lặp nhân với số lần lặp
Với các vòng lặp lồng nhau
Quy tắc nhân: độ phức tạp của khối lệnh lặp lồng nhau là tổng
khối lượng tính toán của các câu lệnh trong mỗi vòng lặp
nhân với tích của các kích thước của các vòng lặp
Nếu f1=O(g1), f2=O(g2) thì f1f2=O(g1g2)
Cho đoạn chương trình:
for (i = 0; i < n; i++) getch(A[i]);
for (i = 0; i < n; i++) printf(“%d”,A[i]);
Khi đó T(n) =T1(n) +T2(n) = O(max(n,n)) = O(n)
Trang 28Bài tập
Trang 29Chương 2 Kiểu dữ liệu
và mô hình dữ liệu
2.1 Biểu diễn dữ liệu và các kiểu dữ liệu đơn
2.2 Kiểu dữ liệu có cấu trúc – Cấu trúc dữ liệu
2.2 Hệ kiểu của ngôn ngữ C
2.3 Mô hình dữ liệu và kiểu dữ liệu trừu tượng
2.1 Biểu diễn dữ liệu và
các kiểu dữ liệu đơn
2.1.1 Sự cần thiết của việc biểu diễn dữ liệu
2.1.2 Kiểu dữ liệu đơn
2.1.3 Tổ chức các kiểu dữ liệu đơn trong máy tính
Trang 309 September 2010 2.1 Biểu diễn dữ liệu 59
2.1.1 Sự cần thiết của việc biểu diễn
dữ liệu
Dữ liệu sơ cấp - Biểu diễn nhị phân
Bit, Byte, Word → thanh ghi,
Các phép tính số học và logic → bộ xử lý số học và logic
Các kiểu dữ liệu
Sự trừu tượng hóa trong toán học của các đối tượng trong thế
giới hiện thực là các khái niệm biểu diễn đặc trưng về mặt số
lượngvàcác quan hệcủa các đối tượng
Các dữ liệu trong ngôn ngữ lập trình bậc cao (FORTRAN,
BASIC, PASSCAL, C ), biểu diễn đặc trưng về mặtsố lượng và
các quan hệcủa các đối tượng
Trên cơ sở các khái niệm toán học này, người ta đã đưa vào
trong các ngôn ngữ lập trình bậc cao các kiểu dữ liệu đơn (bao
gồm các kiểu: số, ký tự, con trỏ ) vàcác tác vụ(các phép toán)
tác động lên các kiểu cơ bản, các hàm thư viện, các chương
trình condo người lập trình viết thêm
2.1.2 Kiểu dữ liệu đơn
Kiểu dữ liệu là gì?
Trong các ngôn ngữ lập trình bậc cao, các dữ liệu
được phân lớp thành các lớp dữ liệu dựa vào bản
chất của dữ liệu Mỗi một lớp dữ liệu được gọi là một
kiểu dữ liệu
Kiểu dữ liệu là một tập hợp các phần tử cùng chung
thuộc tính nào đó
các phần tử của tập được gọi là các giá trị của kiểu.
Thông thường trong một hệ kiểu của một ngôn ngữ
lập trình sẽ có một số kiểu dữ liệu được gọi là kiểu dữ
liệu đơn (single) hay kiểu dữ liệu phân tử (atomic).
Trang 319 September 2010 2.1 Biểu diễn dữ liệu 61
2.1.2 Kiểu dữ liệu đơn
Hệ kiểu của một ngôn ngữ
bao gồm các kiểu dữ liệu đơn
và các phương pháp cho phép ta từ các kiểu dữ liệu đã có
xây dựng nên các kiểu dữ liệu mới
Các ngôn ngữ lập trình khác nhau có thể có các
kiểu dữ liệu đơn khác nhau.
Chẳng hạn,
trong ngôn ngữ Pascal, các kiểu dữ liệu integer, real,
boolean, char và các kiểu liệt kê được gọi là các kiểu dữ
liệu đơn.
trong Fortran có các kiểu dữ liệu là integer, real, logical,
complex và double complex…
trong C là char, int, float, double, con trỏ,
2.1.2 Kiểu dữ liệu đơn
Các đặc trưng của các kiểu dữ liệu đơn
1. Kích thước của kiểu: Mỗi giá trị thuộc kiểu chiếm dụng một
dung lượng không đổi bộ nhớ cần thiết
2. Phạm vi của kiểu: Mỗi kiểu dữ liệu xác định một tập hợp cố
định các giá trị thuộc kiểu
Chẳng hạn, kiểu integer trong ngôn ngữ Pascal (int trong C) gồm tất
cả các số nguyên được biểu diễn bởi hai byte, tức là gồm các số
nguyên từ -32768 đến + 32767
3. Các toán tử trên kiểu: Mỗi kiểu dữ liệu, cần phải xác định một
tập hợp nào đó các phép toán, các hàm chuẩn có thể thực hiện
được trên các dữ liệu của kiểu
Chẳng hạn, với kiểu real, các phép toán có thể thực hiện được là
các phép toán số học thông thường +, -, *, / , và các phép toán so
sánh =, < >, < , < =, >, > =; các hàm chuẩn abs(.), sin(.), round(.),….
Trang 329 September 2010 2.1 Biểu diễn dữ liệu 63
2.1.3.Tổ chức các kiểu dữ liệu đơn
trong máy tính
Số nhị phân
Số nhị phân không âm
Chuỗi n bit để biểu diễn
Chuỗi có n bit sẽ biểu diễn các số (không âm) trong phạm vi 0
đến 2n-1, do đó nếu có 8 bit (1 byte) sẽ biểu diễn được các số
Số dương được biểu diễn như trên
Số âm hoán đổi trị 0 thành 1, trị 1 thành 0 trong biểu diến giá trị tuyệt đối
của nó
Như vậy, để biểu diễn một số âm x dưới dạng nhị phân bù 1 ta thực
hiện các bước sau:
Biểu diễn –x (giá trị tuyệt đối của x) dưới dạng nhị phân không âm
Đảo bit
Ví dụ: -38 → 00100110 → 11011001
Chuỗi có n bit sẽ biểu diễn các số (không âm) trong phạm vi từ
-2 n-1 +1 đến 2 n-1 -1, do đó nếu có 8 bit (1 byte) sẽ biểu diễn được các số
từ -127 đến 127
Với số nhị phân 8 bit dạng bù 1 có hai giá trị 0 là 00000000 (0
“dương”) và 11111111 (0 “âm”).
Trang 339 September 2010 2.1 Biểu diễn dữ liệu 65
2.1.3.Tổ chức các kiểu dữ liệu đơn
trong máy tính
Số nhị phân dạng bù 2
Được dùng đề biểu diễn các số nguyên nhị phân có cả
số âm và số không âm
Để biểu diễn một số âm x dưới dạng nhị phân bù 2 ta
thực hiện các bước sau:
Biểu diễn x dưới dạng nhị phân bù 1
Cộng thêm 1
Ví dụ: -38 → 00100110 → 11011001 → 11011010
Chuỗi có n bit sẽ biểu diễn các số (không âm) trong
phạm vi từ -2n-1đến 2n-1-1, do đó nếu có 8 bit (1 byte) sẽ
biểu diễn được các số từ -128 đến 127
Với số nhị phân 8 bit dạng bù 2 có một giá trị 0 là
00000000
2.1.3.Tổ chức các kiểu dữ liệu đơn
trong máy tính
Số nguyên dạng thập phân không âm
Được tổ chức theo dạng mã hóa thành nhị phân (binary
coded decimal) Mỗi ký số thập phân được đổi bởi một xâu
nhị phân 4 bit tương ứng
Ví dụ: 0 → 0000; 1 → 0001; 2 → 0010; 3 → 0011; …
6 → 0110; 7 → 0111; 8 → 1000; 9 → 1001;
Để đổi ngược lại, số thập phân đã mã hóa nhị phân sang
thập phân, ta thực hiện chia xâu bit thành từng nhóm 4 bit
(từ phải sang trái), sau đó đổi mỗi nhóm thành số thập
phân
Ví dụ: 0010 0110 → 26
1000 1001 0010 → 892
Trang 349 September 2010 2.1 Biểu diễn dữ liệu 67
2.1.3.Tổ chức các kiểu dữ liệu đơn
trong máy tính
Số hữu tỉ (thực)
Được tổ chức bằng một chuỗi cố định các bit (32 bit)
Mỗi số được chia thành 3 thành phần
Phần định trị được biểu diến bởi 24 bit dạng bù 2
Phần cơ số được ngầm định là 10
Phần số mũ được biểu diến bởi 8 bit dạng bù 2
Biểu diễn phần định trị và phần mũ ở những biến này tuân
theo chuẩn IEEE (Institute of Electrical and Electronics
Engineers) về số thực dấu chấm động Hầu hết các trình
biên dịch C hiện nay đều theo chuẩn này (Xem thêm trong
Mỗi ký tự được đặt tương ứng bởi một số nguyên trong bộ
mã ASCII bằng chuỗi 8 bit (1 byte),
chẳng hạn
00100110 → &; 01000001 → A;
01000010 → B; 01000011 → C
Chuỗi ký tự
Chuỗi ký tự được tổ chức trong bộ nhớ bằng dãy mã ASCII
của từng ký tự thuộc chuỗi
Chẳng hạn
01000001 01000010 → AB
01000001 01000010 01000011 → ABC
Vấn đề cần tìm hiểu thêm là với một dãy nhị phân, cơ chế nào để
máy tính biết được đâu là số nguyên, đâu là số thực, đâu là xâu ký
tự, đâu là con trỏ
Trang 352.2 Các kiểu dữ liệu có
cấu trúc
2.2.1 Cấu trúc dữ liệu là gì?
2.2.2 Ba phương pháp thông thường tạo CTDL
2.2.3 Quá trình giải một bài toán trên máy tính
2.2.1 Cấu trúc dữ liệu là gì?
Các kiểu dữ liệu đơn chưa đủ mạnh để khai thác máy tính
Cấu trúc dữ liệu là các dữ liệu phức tạp, được xây dựng nên
từ các dữ liệu đã có, đơn giản hơn bằng các phương pháp
liên kết nào đó
Tuỳ từng ứng dụng, ta sẽ xây dựng những cấu trúc dữ liệu
nào mà các thao tác cần thực hiện là hiệu quả nhất có thể
được
Có thể hình dung một cấu trúc dữ liệu được tạo nên từ các
khối, mỗi khối có thể xem như một cái hộp chứa các dữ liệu
Trang 369 September 2010 2.1 Biểu diễn dữ liệu 71
Như vậy, khi tổ chức một cấu trúc dữ liệu cần thiết phải
quan tâm tới các yếu tố sau:
Các dữ liệu thành phần tham gia để tạo nên cấu trúc đó
Cách bố trí, sắp xếp các thành phần đó như thế nào (cơ
cấu?)
Khả năng truy nhập và xử lý – các thao tác, các phép toán
Các dữ liệu thành phần có thể là dữ liệu đơn, hoặc cũng
có thể là một cấu trúc dữ liệu đã được xây dựng
Hầu hết các ngôn ngữ lập trình bậc cao đều các cấu trúc
dữ liệu như xâu ký tự, mảng, bản ghi, tập hợp, tệp.
2.2.2 Ba phương pháp thông thường
tạo CTDL
Sắp xếp các tế bào chứa các dữ liệu cùng một kiểu
thành một dãy
Xâu ký tự, Mảng, Tệp
Kết hợp một số tế bào (có thể chứa các dữ liệu có kiểu
khác nhau) thành một đối tượng
Bản ghi (cấu trúc)
Sử dụng con trỏ để liên kết các khối, mỗi khối là một bản
ghi gồm hai phần INFOR và LINK, phần INFOR có thể
có một hay nhiều trường dữ liệu, còn phần LINK có thể
chứa một hay nhiều con trỏ trỏ đến các khối khác có
quan hệ với khối đó
Danh sách
Trang 379 September 2010 2.1 Biểu diễn dữ liệu 73
2.2.3 Quá trình giải một bài toán trên máy
tính
Quá trình giải một bài toán trên máy tính có thể quy
về 3 giai đoạn kế tiếp như sau
GĐ 1
Xây dựng mô hình mô tả bài toán
Thiết kế thuật toán hình thức bằng cách sử dụng các thao tác,
các phép toán trên các mô hình dữ liệu
GĐ 2
Biểu diễn các mô hình dữ liệu bởi các kiểu dữ liệu trừu tượng
Biểu diễn các thuật toán bẳng giả ngôn ngữ
GĐ 3
Lựa chọn cấu trúc dữ liệu
Thể hiện thuật toán bởi các thủ tục (hàm) trong ngôn ngữ lập
trình nào đó
2.3 Hệ kiểu của ngôn ngữ C
2.3.1 Các kiểu dữ liệu đơn trong C
2.3.2 Các kiểu dữ liệu có cấu trúc trong C
Trang 389 September 2010 2.2 Hệ kiểu của ngôn ngữ C 75
2.3.1.Các kiểu dữ liệu đơn trong C
Các kiểu dữ liệu đơn trong C
Tuy nhiên có thể thêm một số kiểu trong C bằng cách thay đổi
khai báo các kiểu char, int thông qua việc bổ sung các tiền tố
signed, unsigned, short, long(Xem Help của C);
4 byte0 65535
Địa chỉ ô nhớcon trỏ
8 byte
±1.7E-308 ± 1.7E308
Số thựcdouble
4 byte
±3.4E-38 ± 3.4E38
Số thựcfloat
2 byte-32768 32767
Số nguyênint
1 byte-128 127
Ký tựchar
Kích thướcPhạm vi
Ý nghĩaTên
2.3.1.Các kiểu dữ liệu đơn trong C
Con trỏ
Biến con trỏ là một loại biến đặc biệt, có kích thước cố
định, không dùng để lưu trữ dữ liệu mà để lưu trữ địa chỉ
của một biến khác nhằm giúp truy nhập và quản lý dữ liệu
được lưu trữ trong vùng nhớ dành cho biến đó
Kích thước biến con trỏ phụ thuộc cách biểu diễn địa chỉ
bộ nhớ Trong máy PC thường sử dụng hai thanh ghi 16
bit để biểu thị địa chỉ bộ nhớ nên kích thước của biến con
trỏ là 4 byte
Kiểu con trỏ là gì?
Mỗi kiểu dữ liệu được trỏ bởi một biến con trỏ nào đó thì biến con trỏ
ấy phải được khai báo để có thể truy xuất được dữ liệu mà nó trỏ
đến Vì vậy mà có kiểu con trỏ
Có các kiểu con trỏ nguyên , con trỏ thực , con trỏ ký tự , con trỏ
mảng, …
Trang 399 September 2010 2.2 Hệ kiểu của ngôn ngữ C 77
2.3.1 Các kiểu dữ liệu đơn trong C
Chú ý:
Kiểu con trỏ không phải
là kiểu để lưu giữ giá trị
của con trỏ
Kiểu để lưu giữ giá trị
của con trỏ bao giờ
cũng là kiểu cố định
(nguyên không âm)
Kiểu con trỏ là kiểu đặc
biệt tương ứng với kiểu
của dữ liệu được con trỏ
ấy trỏ đến
Biến con trỏ P
Biến được trỏ bởi biến con trỏ
Mảng là một tập hợp hữu hạn các phần tử có cùng kiểu, được
sắp xếp theo một trật tự nào đấy trong bộ nhớ
Một mảng có cố định số phần tử (gọi là kích thước mảng)
Kích thước này phải được khai báo tường minh trong phần
khai báo mảng vì nó xác định vị trí và kích thước của vùng
nhớ trong bộ nhớ được cấp phát cho mảng
Các phần tử của mảng phải có cùng kiểu và được sắp thứ tự
nhờ chỉ số của phần tử
Phép toán cơ bản thực hiện trong mảng là truy nhập trực tiếp
đến từng vị trí của mảng nhờ chỉ số của phần tử để có thể lưu
trữ hoặc thu nhận thông tin (cất vào hoặc lấy ra)
Chỉ số của phần tử còn được gọi làđịa chỉ tường minh
Trang 409 September 2010 2.2 Hệ kiểu của ngôn ngữ C 79
2.3.2 Các kiểu dữ liệu có cấu trúc
trong C
Chính việc có thể truy nhập trực tiếp (hay ngẫu nhiên) vào
từng phần tử của mảng thông qua địa chỉ tường minh mà thời
gian để truy nhập đến mỗi phần tử của mảng là như nhau,
nghĩa là thời gian cần thiết để truy nhập đến phần tử thứ 5
cũng như thời gian cần thiết để truy nhập đến phần tử thứ 75
trong một mảng có n≥75 phần tử
Trong các ngôn ngữ lập trình một mảng được khai báo
như là một biến, trong đó giá trị của nó là một tập hợp có
thứ tự các phần tử, thứ tự đó được xác định theo một quy
luật nào đó và được xác định nhờ chỉ số của nó
Nếu một chỉ số được dùng thì mảng được gọi là 1 chiều,
Nếu nhiều chỉ số được dùng ta gọi là mảng nhiều chiều
(2-chiều, 3-(2-chiều, )
2.3.2 Các kiểu dữ liệu có cấu trúc
trong C
Mảng 1 chiều
Là một dãy liên tiếp Nmax ô nhớ để lưu trữ các phần tử của
mảng Mỗi ô nhớ là một khối dành để lưu trữ dữ liệu có kiểu là
kiểu phần tửcủa mảng
Lưu ý rằng trong C và trong Pascal có sự khác biệt về
mối liên hệ giữa chỉ số và thứ tự của các phần tử của mảng
Việc kiểm tra tràn ô của mảng (Pascal có kiểm tra, còn C thì
không)
Nmax-1
ni
21
0
…x[n]
…x[i]
…x[2]
x[1]
x[0]
Đchỉ cơ sở Đ chỉ của ph tử có chỉ số i = đ chỉ cơ sở +i*kích thước của kiểu ph tử