Professional Documents
Culture Documents
ReportBasicProject1 Exe
ReportBasicProject1 Exe
ĐỒ ÁN CƠ SỞ
ĐỀ TÀI: 313
VIẾT CHƯƠNG TRÌNH SỬ DỤNG CẤU TRÚC
HÀNG ĐỢI VÀ PHƯƠNG PHÁP CHIA ĐÔI BẰNG
NGÔN NGỮ LẬP TRÌNH C
Đà Nẵng, 06/2020
MỤC LỤC
MỤC LỤC .............................................................................................................i
DANH MỤC HÌNH VẼ .......................................................................................ii
LỜI MỞ ĐẦU ...................................................................................................... 1
1. TỔNG QUAN ĐỀ TÀI .................................................................................... 2
2. CƠ SỞ LÝ THUYẾT ....................................................................................... 2
2.1. Ý tưởng ...................................................................................................... 2
2.2. Cơ sở lý thuyết ........................................................................................... 2
3. TỔ CHỨC CẤU TRÚC DỮ LIỆU VÀ THUẬT TOÁN ................................ 4
3.1. Phát biểu bài toán....................................................................................... 4
3.2. Cấu trúc dữ liệu ......................................................................................... 4
3.3. Thuật toán .................................................................................................. 5
4. CHƯƠNG TRÌNH VÀ KẾT QUẢ .................................................................. 6
4.1. Tổ chức chương trình................................................................................. 6
4.2. Ngôn ngữ cài đặt ........................................................................................ 6
4.3. Kết quả ....................................................................................................... 6
4.3.1. Giao diện chính của chương trình ....................................................... 6
4.3.2. Kết quả thực thi của chương trình ....................................................... 7
4.3.3. Nhận xét đánh giá................................................................................ 8
5. KẾT LUẬN VÀ HƯỚNG PHÁT TRIỂN ....................................................... 9
5.1. Kết luận ...................................................................................................... 9
5.2. Hướng phát triển ........................................................................................ 9
TÀI LIỆU THAM KHẢO .................................................................................. 10
PHỤ LỤC ........................................................................................................... 11
i
DANH MỤC HÌNH VẼ
Hình 1: File DAYSO.IN
Hình 2: Nhập dãy số từ bàn phím
Hình 3: File RESULT1.OUT
Hình 4: File RESULT2.OUT
Hình 5: Giao diện chính của chương trình
ii
Đồ án cơ sở TS. Phạm Công Thắng
LỜI MỞ ĐẦU
Hiện nay, Công nghệ thông tin đang phát triển nhanh chóng và ngày càng được
ứng dụng rộng rãi vào cuộc sống của con người. Cũng như trên thế giới, Việt Nam là
một nước đang phát triển và công nghệ thông tin cũng đang phát triển nhanh chóng thì
việc đầu tư cho công cuộc phát triển, nghiên cứu và ứng dụng công nghệ thông tin rất
quan trọng.
Một số ứng dụng của công nghệ thông tin là vào lĩnh vực tính toán. Ngày nay,
Công nghệ thông tin (CNTT) đang hiện diện và đóng vai trò quan trọng không thể thiếu
trong quá trình tính toán, thực hiện phép tính của mọi thứ cần đến toán học. Sự phát
triển của máy tính và Internet đã thay đổi mô hình tính toán và cách thức tính những bài
toán phức tạp, việc chuyển dần từ tính toán thủ công sang tính toán tự động đã ảnh
hưởng rất lớn đến các công việc phức tạp cần những thuật toán mà tính nhẩm, tính tay
không thể thực hiện được.
Vì vậy em được chọn đề tài “Viết chương trình C thực hiện các công việc kết hợp
Cấu trúc hàng đợi và Phương pháp chia đôi” làm đề tài thực hiện Đồ án cơ sở.
- Yêu cầu: Viết chương trình bằng ngôn ngữ lập trình C (có sử dụng file) để thực
hiện:
• Input: Danh sách phần tử a[i] từ file DAYSO.IN hoặc Nhập từ bàn phím danh
sách phần tử a[i].
• Output: Danh sách phần tử a[i-1], bảng tính số liệu phương trình sau khi dung
phương pháp chia đôi tìm nghiệm gần đúng.
• Phạm vi thực hiện: Nghiên cứu, phân tích và xây dựng thuật toán, viết chương
trình C.
• Phương pháp nghiên cứu: Ứng dụng kiến thức về lập trình, tham khảo một số
tài liệu về ngôn ngữ C. Tìm hiểu giáo trình Cấu trúc dữ liệu và Phương pháp tính.
2. CƠ SỞ LÝ THUYẾT
2.1. Ý tưởng:
- Sử dụng phương pháp chia đôi để giải phương trình tìm ra nghiệm gần đúng.
- Sử dụng danh sách liên kết kiểu hàng đợi.
- Sử dụng hàm đọc, ghi các phần tử vào file.
2.2. Cơ sở lý thuyết:
- Giới thiệu ngôn ngữ lập trình C: Ngôn ngữ lập trình C là một ngôn ngữ mệnh
lệnh được phát triển từ đầu thập niên 1970 bởi Dennis Ritchie để dùng trong hệ điều
hành UNIX. Từ đó, ngôn ngữ này đã lan rộng ra nhiều hệ điều hành khác và trở thành
một những ngôn ngữ phổ dụng nhất. C là ngôn ngữ rất có hiệu quả và được ưa chuộng
nhất để viết các phần mềm hệ thống, mặc dù nó cũng được dùng cho việc viết các ứng
dụng. Ngoài ra, C cũng thường được dùng làm phương tiện giảng dạy trong khoa học
máy tính mặc dù ngôn ngữ này không được thiết kế dành cho người nhập môn [6].
- Cấu trúc dữ liệu:
• Định nghĩa: Cấu trúc dữ liệu là cách lưu trữ, tổ chức dữ liệu có thứ tự, có hệ
thống để dữ liệu có thể được sử dụng một cách hiệu quả [2].
Dưới đây là hai khái niệm nền tảng hình thành nên một cấu trúc dữ liệu:
Interface: Mỗi cấu trúc dữ liệu có một Interface. Interface biểu diễn một tập hợp
các phép tính mà một cấu trúc dữ liệu hỗ trợ. Một Interface chỉ cung cấp danh sách các
phép tính được hỗ trợ, các loại tham số mà chúng có thể chấp nhận và kiểu trả về của
các phép tính này.
Implementation (có thể hiểu là sự triển khai): Cung cấp sự biểu diễn nội bộ của
một cấu trúc dữ liệu. Implementation cũng cung cấp phần định nghĩa của giải thuật được
sử dụng trong các phép tính của cấu trúc dữ liệu [5].
• Cấu trúc dữ liệu thực hiện: Danh sách liên kết kiểu hàng đợi
Hàng đợi (tiếng anh: Queue) là một cấu trúc dữ liệu dùng để lưu giữ các đối
tượng theo cơ chế FIFO (viết tắt từ tiếng Anh: First In First Out), nghĩa là “vào trước ra
trước” [4].
Hình ảnh về hàng đợi rất hay gặp trong đời sống hàng ngày, hình ảnh việc xếp
hàng dưới đây là một mô phỏng dễ hiểu nhất cho cấu trúc dữ liệu hàng đợi(queue):
Người vào đầu tiên sẽ được tiến đón đầu tiên;Người mới vào bắt buộc phải xếp hàng ở
phía cuối.
- Phương pháp tính:
• Định nghĩa: Phương pháp số hay đôi khi còn được gọi là Phương pháp tính,
Toán học tính toán hoặc Giải tích số là một lĩnh vực của toán học chuyên nghiên cứu
các phương pháp giải gần đúng các bài toán bằng cách dựa trên những dữ liệu số cụ thể
và cho kết quả cũng dưới dạng số. Nói gọn hơn, phương pháp số như bản thân tên gọi
của nó, có nghĩa là phương pháp giải các bài toán bằng những con số cụ thể [1].
Quá trình trên gọi là phương pháp chia đôi bởi vì cứ mỗi một lần lặp lại từ đầu thì
khoảng [a, b] cần xem xét được thu gọn lại chỉ còn một nửa so với lần trước bởi điểm
chính giữa c. Quá trình lặp trên cũng dừng lại khi đoạn [a,b] quá ngắn (nhỏ hơn một số
dương rất nhỏ nào đó, gọi là sai số).
- Input:
• Khởi tạo một file DAYSO.IN (Hình 1) chứa dãy số gồm N phần tử (N ≥ 7)
cùng ổ đĩa với chương trình thực hiện.
• Nhập từ bàn phím dãy số gồm N phần tử (N ≥ 7) được trình bày ở Hình 2.
- Output: File RESULT1.OUT (Hình 3) chứa dãy số kết quả sau khi xóa một phần
tử theo danh sách liên kết hang đợi. File RESULT2.OUT (Hình 4) chứa nghiệm của
phương trình G(x)=0.
3.2. Cấu trúc dữ liệu:
- Sử dụng cấu trúc danh sách liên kết kiểu hàng đợi.
- Kiểu mảng.
- Thuật toán.
• Danh sách liên kết kiểu hàng đợi: Hàng đợi (tiếng Anh: Queue) là một cấu
trúc dữ liệu dùng để lưu giữ các đối tượng theo cơ chế FIFO (viết tắt từ tiếng Anh: First
In First Out), nghĩa là “vào trước ra trước” [4].
• Hình ảnh về hàng đợi rất hay gặp trong đời sống hàng ngày, hình ảnh việc xếp
hàng dưới đây là một mô phỏng dễ hiểu nhất cho cấu trúc dữ liệu hàng đợi(Queue):
Người vào đầu tiên sẽ được tiếp đón đầu tiên; Người mới vào bắt buộc phải xếp hàng ở
phía cuối.
• Trong cấu trúc hàng đợi(queue), ta chỉ có thể thêm các phần tử vào một đầu
của queue (giả sử là cuối), và cũng chỉ có thể xóa phần tử ở đầu còn lại của queue(tạm
gọi là đầu). Như vậy, ở một đầu không thể xảy ra hai hành động thêm và xóa đồng thời.
• Như vậy, với cấu trúc Hàng đợi(Queue), chúng ta có các chức năng sau:
o EnQueue: Thêm phần tử vào cuối(rear) của Queue.
o DeQueue: Xóa phần tử khỏi đầu(front) của Queue. Nếu Queue rỗng thì
thông báo lỗi.
o IsEmpty: Kiểm tra Queue rỗng.
o Front: Lấy giá trị của phần tử ở đầu(front) của Queue. Lấy giá trị không làm
thay đổi Queue.
3.3. Thuật toán:
• Nhập khoảng nghiệm (a, b) sao cho f(a) < 0 và f(b) > 0.
• Lặp:
o c = (a + b) / 2
o Nếu f(c) > 0 → b = c
o Ngược lại a = c
• Xuất nghiệm: c
- Độ phức tạp của thuật toán:
• Giả sử f(x) liên tục và trái dấu trên (a,b). Khi đó trên (a,b) tồn tại một số lẻ
nghiệm thực của phương trình f(x)=0. Nghiệm là duy nhất nếu f’(x) tồn tại và không
đổi dấu trên (a,b).
• Đặt [a0, b0] = [a, b] và lập các khoảng lồng nhau [ai , bi ] (i=1, 2, 3, …).
[ai-1, (ai-1+ bi-1)/2 ] nếu f((ai-1+ bi-1)/2) >0
• [ai, bi] =
[(ai-1+ bi-1)/2, bi] nếu f((ai-1+ bi-1)/2) < 0
• Như vậy:
o Hoặc nhận được nghiệm đúng ở một bước nào đó:
- Gọi hàm readFile để đọc danh sách phần tử từ file DAYSO.IN hoặc hàm Input
để nhập danh sách phần tử từ bàn phím.
- Gọi hàm DeletevsWrite để xóa phần tử theo danh liên kết kiểu hàng đợi và ghi
kết quả vào file RESULT1.OUT.
- Gọi hàm Solution để tìm nghiệm gần đúng phương trình G(x)= ∑𝑀−1 𝑖
𝑖=0 𝑎𝑖 𝑥 theo
phương pháp chia đôi và ghi nghiệm vào file RESULT2.OUT.
4.2. Ngôn ngữ cài đặt:
2 2 -3 0.5 8.5 -0.5 3 -7 -1 6.5 -12 6 -3 0.5 8.5 -0.5 3 -7 -1 6.5 -12 6 1.500000
(0 3)
3 1 1.75 8.5 4.75 -4 4.75 2.5 -1.75 1 1.75 8.5 4.75 -4 4.75 2.5 -1.75 1 -0.249998
(-5, 1)
4 1 4 -8 0 7 -7 4 (-1 0) 4 -8 0 7 -7 4 -0.879005
• Có thể tìm ra nghiệm đúng và nghiệm gần đúng cho phương trình.
• Áp dụng trong nhiều trường hợp bài toán không có lời giải đúng hoặc nếu có
thì quá phức tạp.
• Sai số xuất hiện do sự sai lệch giữa giá trị nhận được với nghiệm thực của bài
toán không chênh lệch quá lớn.
- Vì vậy sử dụng thuật toán tìm nghiệm theo phương pháp chia đôi (Bisection) rất
hiệu quả, tiết kiệm thời gian và phù hợp với đề tài.
- Qua thời gian thực hiện, dưới sự hướng dẫn tận tình của Thầy Phạm Công Thắng
cùng sự giúp đỡ của quý thầy cô trong khoa, em đã cố gắng hoàn thành đồ án cơ sở theo
yêu cầu và thời gian quy định. Em đã thực hiện và rút ra kết luận dưới đây.
- Bài toán có thêm yêu cầu sử dụng file dữ liệu, giúp chúng ta:
• Phù hợp với thực tế: người dung không thể lúc nào cũng nhập dữ liệu mà sẽ
ghi dữ liệu đó vào file và gửi cho lập trình viên để chạy chương trình.
• Lưu trữ kết quả chương trình việc lâu dài, dễ kiểm tra.
- Sử dụng phương pháp tính nói chung và phương pháp chia đôi nói riêng có thể
giải đến kết quả bằng số cho các bài toán, nó cung cấp các giải thuật cho các bài toán
trong thực tế không có lời giải chính xác hoặc quá phức tạp.
• Là cầu nối giữa toán học lý thuyết và các ứng dụng của nó trong thực tế.
• Trong thời đại tin học hiện nay thì việc áp dụng các phương pháp tính càng
trở nên phổ biến nhằm tăng tốc độ tính toán.
5.2. Hướng phát triển:
- Phát triển chương trình thành các ứng dụng hỗ trợ tính toán.
- Nâng cấp khả năng tính toán, hoàn thiện thuật toán chi tiết hơn, cải thiện tính
linh động cho người sử dụng.
- Từng bước đưa chương trình đến rộng rãi với người dùng cần giải thuật.
PHỤ LỤC
Mã nguồn chương trình:
#include<stdio.h>
#include<conio.h>
#include<Windows.h>
#include<math.h>
#include<String.h>
#include<winbase.h>
#define MAX 100
struct node {
float data;
struct node * next;
};
typedef struct node node;
struct queue {
int count;
node * front;
node * rear;
};
typedef struct queue queue;
void initialize(queue * q) {
q -> count = 0;
q -> front = NULL;
q -> rear = NULL;
}
int isempty(queue * q) {
return (q -> rear == NULL);
}
void enqueue(queue * q, float value) {
node * tmp;
tmp = (struct node * ) malloc(sizeof(node));
tmp -> data = value;
tmp -> next = NULL;
if (!isempty(q)) {
q -> rear -> next = tmp;
q -> rear = tmp;
} else {
q -> front = q -> rear = tmp;
}
q -> count++;
}
int dequeue(queue * q) {
node * tmp;
tmp = q -> front;
q -> front = q -> front -> next;
q -> count--;
free(tmp);
}
void display(node * head) {
if (head == NULL) {
printf("\n");
} else {
printf("%f\t", head -> data);
display(head -> next);
}
}
void readFile(float a[], int * n, int * m) {
FILE * pFile;
pFile = fopen("DAYSO.IN", "r");
if (pFile == NULL) {
printf("\nKhong doc duoc File DAYSO.IN");
} else {
fscanf(pFile, "%d", & ( * n));
for(int i = 0; i < ( * n); i++) {
fscanf(pFile, "%f", & a[i]);
}
}
* m = * n - 1;
fclose(pFile);
}
void InputN(int *n) {
printf("\nNhap vao so luong phan tu cua day so: ");
scanf("%d", &(*n));
while ( *n < 7 || *n > MAX) {
printf("\nSo ban nhap vao khong hop le! Xin vui long nhap lai!\n ");
printf("N=");
scanf("%d", & ( * n));
}
}
void writeFile(float a[], int * n, int * m, queue * q) {
printf("%d\n", *n);
for(int i = 0; i < * n; i++) {
printf("Nhap a[%d]=", i);
scanf("%f", & a[i]);
}
* m = * n - 1;
}
void show(float a[], int * n, queue * q) {
for (int i = 0; i < * n; i++) {
enqueue(q, a[i]);
}
printf("Cau a: Danh sach lien ket hang doi la: \n");
display(q -> front);
}
void ShowLinkQueue(float a[], int * n, int * m, queue * q) {
for (int i = 0; i < * n; i++) {
enqueue(q, a[i]);
}
printf("Cau a: Danh sach lien ket hang doi la: \n");
display(q -> front);
}
void DeletevsWrite(float a[], int * n, int * m, queue * q) {
FILE * pFileOut;
pFileOut = fopen("RESULT1.OUT", "w+");
dequeue(q);
fputs("Cau b: Danh sach lien ket hang doi sau khi xoa la: \n", pFileOut);
printf("Cau b: Danh sach lien ket hang doi sau khi xoa la: \n");
display(q -> front);
for (int j = 0; j < *m; j++) {
fprintf(pFileOut, "%.6f ", a[j + 1]);
}
fclose(pFileOut);
}
float Fx(float a[], float x, int m) {
float sum = 0;
for (int j = 0; j < m; j++) {
printf("%10s",gach);
printf("%15.6f\n",Fx(a,x,m));
if(Fx(a,x,m)>0)
l=x;
else k=x;
}
while(fabs(k-l)>0.00001 && Fx(a,x,m)!=0);
printf("Vay nghiem gan dung la %.6f\n", x);
printf("Thay nghiem gan dung vao phuong trinh tong quat ta duoc ket qua la %.6f\n",
fabs(Fx(a, x, m)));
FILE * pFileOut1;
pFileOut1 = fopen("RESULT2.OUT", "w");
fputs("Cau c: Nghiem gan dung cua phuong trinh la:\n", pFileOut1);
fprintf(pFileOut1, "%f ", x);
fclose(pFileOut1);
}
int main() {
float x, y, h, k;
char Doc[5] = "D";
char Tay[5] = "T";
char Input[2];
float a[MAX];
int n, m, choose;
queue * q;
q = (struct queue * ) malloc(sizeof(struct queue));
int count = 0;
initialize(q);
do {
printf("=====================================MENU=================================
========\n");
printf("[1].Xuat ra man hinh danh sach lien ket hang doi lay tu file DAYSO.IN
hoac Nhap bang tay [D/T].\n");
printf("[2].Thuc hien xoa 1 phan tu(vao truoc ra truoc theo quy tac hang doi)
sau do ghi vao file RESULT1.OUT .\n");
printf("[3].Tim nghiem phuong trinh bang phuong phap chia doi va ghi vao file
RESULT2.OUT.\n");
printf("[4].Thoat.\n\n");
printf("Choose: ");
scanf("%d", & choose);
again: switch (choose) {
case 1:
{
initialize(q);
if (count = 0) break;
printf("[%s/%s] ", Doc, Tay);
scanf("%s", & Input);
if (strcmp(Doc, Input) == 0) {
readFile(a, & n, & m);
ShowLinkQueue(a, & n, & m, q);
} else {
InputN( & n);
writeFile(a, & n, & m, q);
show(a, & n, q);
}
}
count++;
break;
case 2:
{
DeletevsWrite(a, & n, & m, q);
}
break;
case 3:
{
Solution(a, x, m);
}
break;
case 4:
{
printf("Cam on quy thay co da xem !");
}
break;
default:
printf("Ban nhap so khong hop le. Vui long nhap lai:");
scanf("%d", & choose);
goto again;
}