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

Báo cáo đồ án 1Phạm Duy Anh

18 974 18

Đ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 18
Dung lượng 606,89 KB

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

Nội dung

Tài liệu chia sẻ cách viết bài báo cáo đồ án 1 đề tài game tic tắc toe và các thuật toán sắp xếp cho các bạn sinh viên lần đầu làm báo cáo đồ án công nghệ thông tin. Mình mong rằng sẽ nhận được sự ủng hộ tích cực từ phía các bạn.

Trang 1

TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI

VIỆN CÔNG NGHỆ THÔNG TIN VÀ TRUYỀN THỒNG

-o0o -

Đồ án 1: Lập trình

Giảng viên hướng dẫn: TS.Ngô Lam Trung

Họ và tên: Phạm Duy Anh

MSSV: 20155076

Lớp: CN-CNTT2-K60

Hà Nội, tháng 6 năm 2017

Trang 2

MỤC LỤC

PHẦN MỞ ĐẦU 3

CHUƠNG 1 GIỚI THIỆU 3

1.1 Các thuật toán sắp xếp 3

1.2 Nén và giải nén bằng giải thuật Huffman 3

1.3 Game Tic Tac Toe 3

CHƯƠNG 2 PHÁT BIỂU VẤN ĐỀ 4

2.1 Các thuật toán sắp xếp 4

2.1.1 Sắp xếp nổi bọt( Bubble sort) 4

2.1.2 Sắp xếp chọn( select sort) 5

2.1.3 Sắp xếp chèn ( Insert sort) 6

2.1.5 Sắp xếp trộn( Merge sort) 8

2.1.6 Sắp xếp vun đống( Heap sort) 10

2.2 Nén và giải nén bằng giải thuật Huffman 13

2.2.1 Tổng quan 13

2.2.2 Nén và giải nén 13

2.3 Game Tic Tac Toe 15

2.3.1 Giới thiệu 15

2.3.2 Phân tích và thiết kế 16

CHƯƠNG 3 KẾT QUẢ VÀ ỨNG DỤNG 18

Trang 3

PHẦN MỞ ĐẦU

Sau các đề tài của môn học Đồ án 1, em đã đạt được một số bài học và kĩ năng cho bản thân Trong quá trình làm đề tài này cùng với sự hướng dẫn tận tình của TS Ngô Lam Trung, em đã phát hiện và khắc phục được nhiều lỗi nhỏ Các kĩ thuật xử

lý dữ liệu với file, pointer, …

Em xin gửi lời cảm ơn chân thành và sâu sắc tới TS Ngô Lam Trung- giảng viên hướng dẫn Đồ án 1: Lập trình đã giúp em rất nhiều trong quá trình thực hiện Sự hướng dẫn tận tình của thầy đã giúp em thu được nhiều kết quả tốt

CHUƠNG 1 GIỚI THIỆU

Bài báo cáo về 3 vấn đề: Các thuật toán sắp xếp, Nén và giải nén bằng giải thuật Huffman, và game Tic Tac Toe

1.1 Các thuật toán sắp xếp

Các thuật toán sắp xếp cũng như các thuật toán tìm kiếm là một trong những vấn đề được nhiều nhà khoa học quan tâm Trong khoa học máy tính và trong toán học, thuật toán sắp xếp là thuật toán sắp xếp các phần tử của một danh sách hoặc mảng theo thứ tự tăng( hoặc giảm), và thường xét đến các trường hợp là số

1.2 Nén và giải nén bằng giải thuật Huffman

Trong khoa học máy tính và lý thuyết thông tin, mã hóa Huffman là một trong những thuật toán mã hóa khởi đầu cho việc nén dữ liệu nó dựa trên bảng tần suất xuất hiện các kí tự cần mã hóa để xây dựng một bộ mã nhị phân cho các kí

tự trên sao cho dung lượng( tổng số bit) là nhỏ nhất

1.3 Game Tic Tac Toe

Trang 4

Tic Tac Toe là một trong những trò chơi khá phổ biến hiện nay, được chơi trên bàn cờ có kích thước 3x3 Hai người chơi, một người dùng kí hiệu O, một người dùng kí hiệu X, lần lượt điền kí hiệu của mình vào các ô còn trống

Người thắng cuộc là người đầu tiên tạo ra được 3 nước cờ ngang, dọc hoặc chéo

CHƯƠNG 2 PHÁT BIỂU VẤN ĐỀ

2.1 Các thuật toán sắp xếp

2.1.1 Sắp xếp nổi bọt( Bubble sort)

Sắp xếp nổi bọt là một thuật toán sắp xếp đơn giản, với thao tác cơ bản là so sánh các cặp phần tử liền nhau, nếu chúng chưa đứng đúng vị trí thì đổi vị trí ( swap) của chúng cho nhau Có thể tiến hành từ trên xuống( bên trái sang) hoặc

từ dưới lên( bên phải sang) Sắp xếp nổi bọt sử dụng phép so sánh các phần tử nên là một giải thuật so sánh

a) Giải thuật

Giả sử dãy cần xếp có n phần tử Ta bắt đầu so sánh từ cặp phần tử 1 và 2, cho đến cặp phần tử n-1 và n, nếu phần tử đứng trước lớn hơn phần tử đứng sau thì ta swap Sau n-1 bước so sánh này thì phần tử cuối cùng chính là phần tử lớn nhất

Ta tiếp tục so sánh như vậy với dãy n-1 số đầu của dãy vừa được sắp xếp ở trên

( Trong một lần duyệt mà không cần swap bất cứ lần nào có nghĩa là dãy đã được sắp xếp)

b) Mã giả

procedure swap(var a, b:integer)

var temp:integer;

temp=a;a=b;b=a;

endprocedure

procedure bubbleSort(list L, number n) //n là số phần tử của dãy

for number i from n downto 2

Trang 5

for number j from 1 to (i - 1)

if L[j] > L[j + 1] //nếu chúng không đúng thứ tự

swap(L[j], L[j + 1]) //đổi chỗ chúng cho nhau

endif

endfor

endfor

endprocedure

c) Độ phức tạp

Với mỗi i=n, n-1, …, 2 ta cần i-1 phép so sánh Vì vậy số các phép so sánh cần thực hiện là: 1+2+3+…+n-1=(𝑛−1).𝑛

Vậy độ phức tạp của thuật toán bằng O(n2)

2.1.2 Sắp xếp chọn( select sort)

Sắp xếp chọn là một thuật toán sắp xếp đơn giản dựa trên việc so sánh tại chỗ( là sắp xếp không cần dùng thêm mảng phụ)

Chọn phần tử nhỏ nhất trong n phần tử ban đầu đưa về vị trí thứ nhất của dãy

số Tiếp tục chọn phần tử nhỏ nhất trong n-1 phần tử còn lại xếp vào vị trí thứ hai của dãy,… tiếp tục chọn như vậy cho đến khi n-1 phần tử đứng đúng vị trí

a) Giải thuật

Bước 1: i←1

Bước 2: tìm phần tử amin trong dãy số từ i→n

Bước 3: hoán đổi vị trí a[i] với amin

Bước 4: nếu i<=n-1, i←i+1 quay lại bước 2, ngược lại dừng

procedure selectSort(list L, number n) //n=listsize

Trang 6

For number i from 1 to n-1

for number j from i+1 to n

if L[i] > L[j] //nếu chúng không đúng thứ tự

swap(L[i], L[j]) //đổi chỗ chúng cho nhau

endif

endfor

endfor

endprocedure

c) Độ phức tạp

Với mỗi i=1,2,…,n-1 cần thực hiện n-1, n-2,…,1 phép so sánh Suy ra cần 1+2+3+…+n-1=(𝑛−1).𝑛

2 phép so sánh

Vậy độ phức tạp là O(n2)

2.1.3 Sắp xếp chèn ( Insert sort)

Sắp xếp chèn là thuật toán sắp xếp có nét tương đồng với việc sắp xếp các quân bài của người chơi bài Muốn sắp xếp các quân bài theo một thứ tự nhất định thì từ quân bài thứ 2 người chơi sẽ so sánh với các quân bài trước đó để chèn nó vào vị trí đúng

a) Giải thuật

Giả sử danh sách gồm n phần tử Danh sách có 1 phần tử là danh sách đã được sắp xếp Giả sử danh sách a1,…,an-1 đã được sắp xếp bây giờ ta cần chèn phần tử an vào vị trí thích hợp để được danh sách sắp xếp đúng Vị trí chèn đúng là vị trí mà phần tử an lớn hơn hoặc bằng các phần tử đứng trước

nó, nhỏ hơn hoặc bằng các phần tử đứng sau nó( nếu có)

b) Mã giả

Procedure insert(array a, int k, value) {

int i:= k-1;

while (i > 0 and a[i] > value) {

a[i+1]:= a[i];

i:= i - 1;

}

a[i+1]:= value;

}

Procedure insertSort(array a, int length) {

int k:= 2;

Trang 7

while (k < length) {

insert(a, k, a[k]);

k:= k + 1;

}

}

c) Độ phức tạp

Độ phức tạp của thuật toán Sắp xếp chèn là O(n2)

2.1.4 Sắp xếp nhanh( Quick sort)

Sắp xếp nhanh, còn được gọi là sắp xếp kiểu phân chia( part sort) là một thuật toán được phát triển bởi C.A.R Hoare Danh sách được chia thành hai danh sách con Chọn một phần tử của danh sách làm chốt, những phần tử nhỏ hơn hoặc bằng chốt được đưa về bên trái chốt thuộc dãy con thứ nhất, những phần tử lớn hơn chốt đưa về bên phải chốt thuộc dãy con thứ hai Tiếp tục như vậy cho đến khi độ dài các danh sách con đều bằng 1

a) Giải thuật

• Phần tử chốt: cách tìm phần tử chốt ảnh hưởng khá lớn đến hiệu quả của chương trình Vậy cần phải chọn phần tử chốt như thế nào để đạt được hiệu quả tốt nhất( sau log2(length) lần chia để được các danh sách con có

độ dài bằng 1) Ta có một vài cách chọn phần tử chốt như sau:

- Chọn phần tử đứng đầu hoặc cuối làm phần tử chốt

- Chọn phần tử đứng giữa danh sách làm phần tử chốt

- Chọn phần tử trung vị trong 3 phần tử đầu, giữa và cuối làm phần tử chốt

- Chọn phần tử ngẫu nhiên trong danh sách làm phần tử chốt

• Thuật phân chia: Chọn phần tử chốt xong rồi ta sẽ chia như thế nào?

1 Duyệt từ đầu đến cuối và so sánh từng phần tử của danh sách với phần tử chốt, như vậy ta cần thực hiện n phép so sánh và mất n không gian bộ nhớ cho các giá trị trung gian

2 Duyệt theo hai đường, một đường từ đầu, một đường từ cuối danh sách Đổi chỗ phần tử lớn hơn chốt đầu tiên từ bên trái với phần tử nhỏ hơn hoặc bằng chốt đầu tiên từ bên phải, lặp đến khi hai đường giao nhau

Trang 8

b) Mã giả

Thuat phan chia:

//left la dau danh sach, right la cuoi danh sach

Function partition (array, left, right, pivotIndex){

pivotValue:=array[pivotIndex];

swap(array[pivotindex, array[right]);//chuyen chot ve cuoi

storeIndex:=left;

for i:=left to right-1

Swap( array[pivotIndex], array[storeIndex]);

Return storeIndex;

Quick sort:

function quickSort(array, left, right)

if (left< right)

choose any pivotIndex such that left ≤ pivotIndex ≤ right;

pivotNewIndex:= partition(array, left, right, pivotIndex);

quicksort(array, left, pivotNewIndex-1);

quicksort(array, pivotNewIndex, right);

c) Độ phức tạp

Độ phức tạp của thuật toán thường là O(nlog(n))

2.1.5 Sắp xếp trộn( Merge sort)

Sắp xếp trộn là thuật toán sắp xếp nâng cao, sử dụng để sắp xếp các danh sách, luồng tập tin… theo một trật tự nào đó Sắp xếp trộn được xếp vào loại sắp xếp so sánh Thuật toán này là một ví dụ tương đối điển hình cho lối thuật toán chia để trị

mà John Von Neumann đưa ra vao những năm 1945

a) Giải thuật

Các bước thực hiện thuật toán trộn tự nhiên như sau:

Bước 1: // Chuẩn bị

Trang 9

r = 0; // r dùng để đếm số đường chạy

Bước 2:

Tách dãy a1, a2, , an thành 2 dãy b, c theo nguyên tắc luân phiên từng đường chạy:

Bước 2.1:

Phân phối cho b một đường chạy; r = r+1;

Nếu a còn phần tử chưa phân phối

Phân phối cho c một đường chạy; r = r+1;

Bước 2.2:

Nếu a còn phần tử: quay lại bước 2.1;

Bước 3:

Trộn từng cặp đường chạy của 2 dãy b, c vào a

Bước 4:

Nếu r <= 2 thì trở lại bước 2;

Ngược lại: Dừng;

b) Mã giả

Procedure Merge(k1,k2,k3);

Var i,j,k:integer;

T: array[k1 k3] of integer;

Begin

i:=k1;

j:=k2;

k:=k3;

while i<k2 and j<=k3 do

Begin

if a[i]<=a[j] then begin

T[k]=a[i];

i=i+1;

End

else begin

T[k]=a[j];

j=j+1;

End;

k=k+1;

End;

if i>=k2 then

while k<=k3 do begin

Trang 10

T[k]=a[j];

j=j+1;

k=k+1;

End

if j>k3 then

while k<k2 do begin

T[k]=a[i];

i=i+1;

k=k+1;

End

For k=k1 to k3

a[k]=T[k];

End

Procedure MergeSort (k1,k2)

Var k3:integer;

End;

c) Độ phức tạp

Độ phức tạp của thuật toán thường là O(nlog(n))

2.1.6 Sắp xếp vun đống( Heap sort)

Sắp xếp vun đống (Heapsort) dựa trên một cấu trúc dữ liệu được gọi là đống nhị phân (binary heap), gọi đơn giản là đống Trong mục này chỉ nói về đống trong bài toán sắp xếp

a) Giải thuật

Đống:

• Mỗi mảng a[1 n] có thể xem như một cây nhị phân gần đầy (có trọng số là các giá trị của mảng), với gốc ở phần tử thứ nhất, con bên trái của đỉnh a[i]

Trang 11

là a[2*i] con bên phải là a[2*i+1] (nếu mảng bắt đầu từ 1 còn nếu mảng bắt đầu từ 0 thì 2 con là a[2*i+1] và a[2*i+2]) (nếu 2*i<=n hoặc 2*i+1<=n, khi

đó các phần tử có chỉ số lớn hơn int(𝑛

2) không có con do đó là lá)

• Một cây nhị phân, được gọi là đống cực đại nếu khóa của mọi nút không nhỏ hơn khóa các con của nó Khi biểu diễn một mảng a[] bởi một cây nhi phân theo thứ tự tự nhiên điều đó nghĩa là a[i]>=a[2*i] và a[i]>=a[2*i+1] với mọi

i =1 int(𝑛

2) Ta cũng sẽ gọi mảng như vậy là đống Như vậy trong đống a[1] (ứng với gốc của cây) là phần tử lớn nhất Mảng bất kỳ chỉ có một phần tử luôn luôn là một đống

• Một đống cực tiểu được định nghĩa theo các bất đẳng thức ngược lại:

a[i]<=a[2*i] và a[i]<=a[2*i+1] Phần tử đứng ở gốc cây cực tiểu là phần tử nhỏ nhất

Vun đống:

• Việc sắp xếp lại các phần tử của một mảng ban đầu sao cho nó trở thành đống được gọi là vun đống

• Vun đống tại đỉnh thứ i: Nếu hai cây con gốc 2*i và 2*i+1 đã là đống thì

để cây con gốc i trở thành đống chỉ việc so sánh giá trị a[i] với giá trị lớn hơn trong hai giá trị a[2*i] và a[2*i+1], nếu a[i] nhỏ hơn thì đổi chỗ chúng cho nhau Nếu đổi chỗ cho a[2*i], tiếp tục so sánh với con lớn hơn trong hai con của nó cho đên khi hoặc gặp đỉnh lá

• Vun một mảng thành đống: Để vun mảng a[1 n] thành đống ta vun từ dưới lên, bắt đầu từ phần tử a[j]với j = int(𝑛

2) ngược lên tới a[1]

• Sắp xếp bằng vun đống:

- Đổi chỗ (Swap): sau khi mảng a[1 n] đã là đống, lấy phần tử a[1] trên đỉnh của đống ra khỏi đống đặt vào vị trí cuối cùng n, và chuyển phần tử thứ cuối cùng a[n] lên đỉnh đống thì phần tử a[n]

đã được đứng đúng vị trí

- Vun lại: phần còn lại của mảng a[1 n-1] chỉ khác cấu trúc đống ở phần tử a[1] Vun lại mảng này thành đống với n-1 phần tử

Trang 12

- Lặp: tiếp tục với mảng a[1 n-1] Quá trình dừng lại khi đống chỉ còn lại một phần tử

b) Mã giả

#include <stdio.h>

#include <conio.h>

const int n = 10;

typedef int keytype; typedef float othertype;

typedef struct recordtype{

keytype key;

othertype otherfields;

};

recordtype a[n]; // khai bao mang a co n phan tu

void Swap(recordtype &x, recordtype &y){

recordtype temp;

temp = x;

x = y;

y = temp;

}

void PushDown(int first, int last){ //while (r <= (last - 1) / 2)

if (first == last || first > (last - 1) / 2) return;

if (last == 2 * first + 1) {

if (a[first].key > a[last].key)

Swap(a[first], a[last]);

return; //first = last;

}else

if ((a[first].key > a[2*first+1].key) && a[2*first+1].key

<= a[2*first+2].key)){

Swap(a[first], a[2*first+1]);

PushDown(2 * first + 1, last);

}else

if ((a[first].key > a[2*first+2].key) && a[2*first+2].key <

a[2*first+1].key)){

Swap(a[first], a[2*first+2]);

PushDown(2 * first + 2, last);

}

else return; //first = last;

}

void HeapSort(){

int i;

Trang 13

for(i = (n-2) / 2; i >= 0; i ) PushDown(i, n-1);

for(i = n-1; i>=2; i ) {

Swap(a[0], a[i]);

PushDown(0, i-1);

}

Swap(a[0], a[1]);

}

2.2 Nén và giải nén bằng giải thuật Huffman

2.2.1 Tổng quan

Để mã hóa dữ liệu( các kí tự, chữ số…) ta thay chúng bằng các xâu nhị phân, được gọi là từ mã của các dữ liệu trên Theo ASCII, mỗi kí tự hay chữ số đều được

mã hóa bằng xâu nhị phân dài 8 bit, vd: ‘a’= ‘01100001’, ‘b’= ‘01100010’ Trong một văn bản, tần suất của các kí tự và chữ số là rất khác nhau, ví dụ như một văn bản tần suất của ‘a’ là 100000, của ‘B’ là 1, ‘c’ là 100, nhưng số bit danh cho mỗi

kí tự đều bằng 8, suy ra tổng số bit dùng cho ba kí tự trên là 800808 bit Với tần suất không đều như trên, ta có thể tiết kiệm dung lượng bằng cách những kí tự có tần suất lớn thì mã hóa với độ dài nhỏ, ngược lại mã hóa với độ dài lớn Giả sử với

ví dụ trên, mã hóa ‘a’ dài 4 bit, ‘c’ 6 bit và ‘B’ 8 bit thì tổng số bit sử dụng là: 400608<< 800808 Để tiết kiệm bộ nhớ ta sẽ mã hóa các kí tự và chữ số với độ dài bit khác nhau( không giống với mã ASCII nữa), nhưng khi giải mã ta phải làm thế nào Nếu ta chèn thêm dấu ‘,’ để phân biệt các kí tự với nhau thì dung lượng khi ấy còn lớn hơn cả dung lượng văn bản gốc Từ đó dẫn ta đến khái niệm ‘Mã tiền tố’

Mã tiền tố là bộ từ mã của một tập hợp kí hiệu sao cho từ mã của kí hiệu này

không là tiền tố( phần đầu) từ mã của một kí hiệu khác

• Biểu diễn mã tiền tố trên cây nhị phân

Một cây nhị phân gồm n lá ta có thể tạo bộ mã tiền tố cho n kí hiệu sao cho tại các node lá là các kí hiệu Từ mã của kí hiệu được tạo ra bằng việc

đi từ gốc tới lá, duyệt sang con trái thêm 0 , duyệt sang con phải thêm 1 2.2.2 Nén và giải nén

a) Giải thuật

Ngày đăng: 11/06/2017, 10:20

TỪ KHÓA LIÊN QUAN

w