Bài tiểu luận môn: Cấu trúc dữ liệu và giải thuật
Mục lục
Phần I: Mở đầu
I. Giới thiệu đề tài
Trong khoa học máy tính, cấu trúc dữ liệu là cách lưu dữ liệu trong máy
tính sao cho nó có thể được sử dụng một cách hiệu quả. Thông thường, một cấu
trúc dữ liệu được chọn cẩn thận sẽ cho phép thực hiện thuật toán hiệu quả hơn.
Việc chọn cấu trúc dữ liệu thường bắt đầu từ chọn một cấu trúc dữ liệu trừu tượng.
Một cấu trúc dữ liệu được thiết kế tốt cho phép thực hiện nhiều phép toán, sử dụng
càng ít tài nguyên, thời gian xử lý và không gian bộ nhớ càng tốt. Các cấu trúc dữ
liệu được triển khai bằng cách sử dụng các kiểu dữ liệu, các tham chiếu và các
phép tốn trên đó được cung cấp bởi một ngơn ngữ lập trình.
Trong đó nổi trội lên là hai cấu trúc dữ liệu đó là Stack (ngăn xếp) và Queue
(hàng đợi). Stack và Queue có ứng dụng rất nhiều kể cả trong thuật toán lẫn trong
thực tế. Hàng ngày chúng ta thường xuyên làm việc và tiếp xúc với các biểu thức,
toán hạng, toán tử… và máy tính cũng vậy. Tuy nhiên máy tính khơng thể nào hiểu
được ngơn ngữ và cách viết của con người, vì vậy để máy tính hiểu được các biểu
thức thì chúng ta phải chuyển chúng về một dạng mà máy tính có thể thực hiện
được. Vì vậy em xin chọn đề tài “Ứng dụng ngăn xếp (Stack) và hàng đợi (Queue)
để viết chương trình biến đổi biểu thức trung tố thành tiền tố và hậu tố” để làm bài
tiểu luận.
GVHD: Trịnh Thị Phú
Sinh vên thực hiện: Hoàng Năng Hưng
1
Bài tiểu luận môn: Cấu trúc dữ liệu và giải thuật
II. Mục đích yêu cầu của đề bài
1. Mục đích
Đề tài này giúp em củng cố, nâng cao kiến thức về môn học cấu trúc dữ liệu
và giải thuật. Từ đó hiểu sâu hơn và vận dụng vào trong các bài tốn số liệu thực tế
đồng thời thơng qua việc làm đề tài này giúp em biết được các phương pháp
nghiên cứu một vấn đề nhỏ nào đó.
2. Yêu cầu
Dùng ngơn ngữ lập trình C/C++ để cài đặt chương trình. Với dữ liệu được
nhập vào từ bàn phím.
III. Phương pháp nghiên cứu
+ Tham khảo tài liệu: cấu trúc dữ liệu và giải thuật, trên mạng…
+ Tìm hiểu thực tiễn, thực tế, quy cách, nhu cầu của bài toán.
+ Xin ý kiến, hướng dẫn của giáo viên hướng dẫn.
Phần II: Nội dung
I. Ngăn xếp (Stack)
•
Ngăn xếp (Stack) là một danh sách có thứ tự mà phép chèn và xóa được
thực hiện tại đầu cuối của danh sách và người ta gọi đầu cuối này là đỉnh
(top) của stack. Với nguyên tắc vào sau ra trước, danh sách kiểu LIFO (last
- in - first - out).
• Có 2 cách lưu trữ Stack:
+ Bằng mảng.
+ Bằng danh sách liên kết.
• Các thao tác cơ bản trên Stack:
Push: Đưa một phần tử vào đỉnh của Stack.
Pop: Lấy từ đỉnh của Stack một phần tử.
Peek: Xem đỉnh của Stack chứa nội dung là gì?
GVHD: Trịnh Thị Phú
Sinh vên thực hiện: Hoàng Năng Hưng
2
Bài tiểu luận môn: Cấu trúc dữ liệu và giải thuật
•
Một số ứng dụng của Stack:
Ứng dụng trực tiếp:
Ứng dụng nổi bật của Stack là Stack cho chương trình sử dụng Stack để gọi
hàm.
Trong trình duyệt WEB, các trang đã xem được lưu trong
stack.
Trong trình soạn thảo văn bản, thao tác Undo được lưu
trong stack.
Ứng dụng gián tiếp:
Cấu trúc dữ liệu bổ trợ cho thuật toán khác.
Một thành phần của cấu trúc dữ liệu khác.
II. Hàng đợi (Queue)
•
Hàng đợi là kiểu danh sách tuyến tính mà phép bổ sung được thực hiện ở 1
đầu, gọi là lối sau (rear) và phép loại bỏ thực hiện ở 1 đầu khác gọi là lối
trước (front). Nguyên tắc vào trước ra trước, danh sách kiểu FIFO (first - in
- first - out).
• Có 2 cách lưu trữ tương tự như Stack:
+ Bằng mảng.
+ Bằng danh sách liên kết.
• Ứng dụng của Queue
Ứng dụng trực tiếp
Danh sách hàng đợi.
Quản lý truy cập tới các tài nguyên dùng chung (ví dụ máy in).
Multiprogramming.
Ứng dụng gián tiếp
Cấu trúc dữ liệu phụ trợ cho các thuật toán.
Một phần của CTDL khác.
III. Ứng dụng của Stack và Queue trong ký pháp Ba Lan
1. Khái niệm:
GVHD: Trịnh Thị Phú
Sinh vên thực hiện: Hoàng Năng Hưng
3
Bài tiểu luận môn: Cấu trúc dữ liệu và giải thuật
Prefix: Biểu thức tiền tố được biểu diễn bằng cách đặt toán tử lên trước các
toán hạng. Cách biểu diễn này còn được biết đến với tên gọi “ký pháp Ba Lan” do
nhà toán học Ba Lan Jan Łukasiewicz phát minh năm 1920. Với cách biểu diễn
này, thay vì viết x + y như dạng trung tố, ta sẽ viết + x y. Tùy theo độ ưu tiên của
toán tử mà chúng sẽ được sắp xếp khác nhau, bạn có thể xem một số ví dụ ở phía
sau phần giới thiệu này.
Postfix: Ngược lại với cách Prefix, biểu thức hậu tố tức là các toán tử sẽ
được đặt sau các toán hạng. Cách biểu diễn này được gọi là “ký pháp nghịch đảo
Ba Lan” hoặc được viết tắt là RPN(Reverse Polish notation), được phát minh vào
khoảng giữa thập kỷ 1950 bởi một triết học gia và nhà khoa học máy tính Charles
Hamblin người Úc.
Ví dụ:
2. Chuyển đổi dạng Infix(trung tố) sang Postfix(hậu tố)
Thuật toán:
Bước 1: Đọc một thành phần của biểu thức E (dạng Infix biểu diễn
bằng xâu, đọc từ trái qua phải). Giả sử thành phần đọc được là x
Bước 1.1: Nếu x là tốn hạng thì viết nó vào bên phải biểu thức E1 (xâu
lưu
kết quả của Postfix)
Bước 1.2: Nếu x là dấu ‘(’ thì đẩy nó vào Stack.
Bước 1.3: Nếu x là một trong các phép toán +, -, *, / thì
Bước 1.3.1: Xét phần tử y ở đỉnh Stack.
Bước 1.3.2: Nếu Pri(y) >= Pri(x) là một phép tốn thì loại y ra khỏi
GVHD: Trịnh Thị Phú
Sinh vên thực hiện: Hoàng Năng Hưng
4
Bài tiểu luận môn: Cấu trúc dữ liệu và giải thuật
Stack và viết y vào bên phải của E1 và quay lại bước 1.3.1
Bước 1.3.3: Nếu Pri(y) < Pri(x) thì đẩy x vào Stack.
Bước 1.4: Nếu x là dấu ‘)’ thì
Bước 1.4.1: Xét phần tử y ở đầu của Stack.
Bước 1.4.2: y là phép tốn thì loại y ra khỏi Stack, viết y vào bên
phải E1 và quay trở lại 1.4.1
Bước 1.4.3: Nếu y là dấu ‘(’ loại y ra khỏi Stack.
Bước 2: Lập lại bước 1 cho đến khi toàn bộ biểu thức E được đọc qua
Bước 3: Loại phần tử ở đỉnh Stack và viết nó vào bên phải E1. Lặp lại bước này
cho đến khi Stack rỗng.
Bước 4: Tính giá trị của biểu thức dưới dạng hậu tố
Ví dụ: Cho biểu thức: E = a * (b + c) – d / e
3. Tính giá trị biểu thức dạng Postfix(hậu tố)
Thuật toán:
Bước 1: Đọc lần lượt các phần tử của biểu thức E1 (từ trái qua phải). Nếu gặp tốn
hạng thì đẩy nó vào Stack. Nếu gặp phép tốn thì lấy hai phần tử liên tiếp trong
Stack thực hiện phép toán, kết quả được đẩy vào trong Stack.
Bước 2: Lập lại bước 1 cho đến khi hết tất cả các phần tử trong biểu thức E1. lúc
GVHD: Trịnh Thị Phú
Sinh vên thực hiện: Hoàng Năng Hưng
5
Bài tiểu luận môn: Cấu trúc dữ liệu và giải thuật
đó đỉnh của Stack chứa giá trị của
biểu thức cần tính
Bước 3: Kết thúc.
Ví dụ: tính giá trị của biểu thức sau: 4 5 + 2 3 + * 6 + 8 7 + /
Giả thuật được trình bày như sau:
4. Chuyển đổi dạng Infix(trung tố) sang Prefix(tiền tố)
Thuật toán:
Ý tưởn: Sử dụng Stack và Queue và Stackkq.
Bước 1: Đọc một thành phần của biểu thức E (dạng Infix biểu diễn bằng xâu, đọc
từ phải qua trái). Giả sử thành phần đọc được là x:
Bước 1.1: Nếu x là toán hạng thì đưa nó vào Queue.
Bước 1.2: Nếu x là dấu ‘)’ thì đẩy nó vào Stack.
Bước 1.3: Nếu x là một trong các phép toán +, -, *, / thì:
Bước 1.3.1: Kiểm tra xem stack có rỗng khơng? Nếu rỗng, đẩy
vào Stack, nếu không rỗng, sang bước 1.3.2.
Bước 1.3.2: Lấy phần tử y ở đỉnh Stack.
Bước 1.3.3: Nếu Pre(y)>=Pre(x), đưa tất cả các phần tử trong
Queue vào Stackkq, đưa y vào Stackkq, đưa x vào Stack.
Bước 1.3.4: Nếu Pre(y)
Bước 1.4: Nếu x là dấu ‘(’ thì:
Bước 1.4.1: Đưa tất cả các phần tử trong Queue vào Stackkq,
Bước 1.4.2: Xét phần tử y ở đầu của Stack.
GVHD: Trịnh Thị Phú
Sinh vên thực hiện: Hoàng Năng Hưng
6
Bài tiểu luận môn: Cấu trúc dữ liệu và giải thuật
Bước 1.4.3: y là phép tốn thì loại y ra khỏi Stack, đưa y vào
Stackkq, quay về bước 1.4.2.
Bước 1.4.3: Nếu y là dấu ‘)’ loại y ra khỏi Stack.
Bước 2: Lập lại bước 1 cho đến khi toàn bộ biểu thức E được duyệt.
Bước 3: Đưa tất cả các phần tử trong Queue vào Stackkq, tất cả phần tử trong
Stack và Stackkq.
Bước 4: Lấy từng phần tử trong Stackkq ra, đó là kết quả dạng Prefix.
Bước 5: Tính giá trị của biểu thức dưới dạng tiền tố.
Ví dụ: Cho biểu thức sau hãy chuyển về dạng Prefix:
E=a*b+c/d
Giải thuật được trình bày như sau:
5. Tình giá trị biểu thức dạng Prefix(tiền tố)
Thuật toán:
Bước 1: Đọc lần lượt các phần tử của biểu thức E1 (từ phải qua trái)
Bước 1.1: Nếu gặp tốn hạng thì đẩy nó vào Stack.
Bước 1.2: Nếu gặp phép tốn thì lấy hai phần tử liên tiếp trong Stack
thực hiện phép toán, kết quả được đẩy vào trong Stack.
Bước 2: Lập lại bước 1 cho đến khi hết tất cả các phần tử trong biểu thức E1. Lúc
đó đỉnh của Stack chứa giá trị của biểu thức cần tính.
Bước 3: Kết thúc.
Ví dụ: tính giá trị của biểu thức sau: /+7 8 + 6 * + 3 2 + 5 4
Giả thuật được trình bày như sau:
GVHD: Trịnh Thị Phú
Sinh vên thực hiện: Hoàng Năng Hưng
7
Bài tiểu luận môn: Cấu trúc dữ liệu và giải thuật
IV. Chương trình đầy đủ
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
#define OPERAND
0
#define OPERATOR
1
#define PARENT_OPEN 2
#define PARENT_CLOSE 3
#define ERROR
1000000
typedef struct _Item{
float value;
int type;
} Item;
// stack
typedef struct _STACKNODE{
Item item;
struct _STACKNODE *next;
} STACKNODE;
typedef struct _STACK{
STACKNODE *top;
int size;
} STACK;
void InitStack(STACK *stack){
stack ->top = NULL;
stack ->size = 0;
}
GVHD: Trịnh Thị Phú
Sinh vên thực hiện: Hoàng Năng Hưng
8
Bài tiểu luận môn: Cấu trúc dữ liệu và giải thuật
int IsStackEmpty(STACK *stack){
return (stack ->size == 0);
}
void PushStack(STACK *stack, Item item){
if(stack ->top == NULL){
stack ->top = (STACKNODE
*)malloc(sizeof(STACKNODE));
stack ->top ->item = item;
stack ->top ->next = NULL;
}
else{
STACKNODE *t = (STACKNODE
*)malloc(sizeof(STACKNODE));
t ->item = item;
t ->next = stack ->top;
stack ->top = t;
}
stack ->size++;
}
Item PopStack(STACK *stack){
if(stack ->size > 0){
STACKNODE *t = stack ->top;
stack ->top = stack ->top ->next;
Item item = t ->item;
free(t);
stack ->size--;
return item;
}
}
Item PeekStack(STACK *stack){
if(stack ->size > 0)
return stack ->top ->item;
}
// queue
typedef struct _QUEUENODE{
Item item;
struct _QUEUENODE *next;
struct _QUEUENODE *prev;
} QUEUENODE;
typedef struct _QUEUE{
_QUEUENODE *front, *rear;
int size;
} QUEUE;
GVHD: Trịnh Thị Phú
Sinh vên thực hiện: Hoàng Năng Hưng
9
Bài tiểu luận môn: Cấu trúc dữ liệu và giải thuật
void InitQueue(QUEUE *queue){
queue ->front = NULL;
queue ->rear = NULL;
queue ->size = 0;
}
int IsQueueEmpty(QUEUE *queue){
return (queue ->size == 0);
}
void PushQueue(QUEUE *queue, Item item){
if(queue ->front == NULL && queue ->rear == NULL){
queue ->front = (QUEUENODE
*)malloc(sizeof(QUEUENODE));
queue ->front ->item = item;
queue ->front ->next = NULL;
queue ->front ->prev = NULL;
queue ->rear = queue ->front;
}
else{
QUEUENODE *t = (QUEUENODE
*)malloc(sizeof(QUEUENODE));
t ->item = item;
t ->next = queue ->front;
t ->prev = NULL;
queue ->front ->prev = t;
queue ->front = t;
}
queue->size++;
}
Item PopQueue(QUEUE *queue){
if(queue ->size != 0){
QUEUENODE *t = queue->rear;
if(queue ->rear == queue->front){
queue ->rear = NULL;
queue ->front = NULL;
}
else{
queue ->rear = queue ->rear ->prev;
queue ->rear ->next = NULL;
}
queue ->size--;
Item i = t ->item;
free(t);
return i;
GVHD: Trịnh Thị Phú
Sinh vên thực hiện: Hoàng Năng Hưng
10
Bài tiểu luận môn: Cấu trúc dữ liệu và giải thuật
}
}
Item PeekQueue(QUEUE *queue)
{
if(queue->size > 0)
return queue->front->item;
}
int DocSo(char str[], int &i){
int len = strlen(str);
int j = 0;
char t[20];
while(i < len){
if(str[i] >= '0' && str[i] <= '9'){
t[j++] = str[i];
}
else{
t[j++] = '\0';
break;
}
i++;
}
return atoi(t);
}
void Tach(char str[], QUEUE *queue){
int len = strlen(str);
int i = 0;
Item item;
while(i < len){
if(str[i] == '+' || str[i] == '-' || str[i] == '*' || str[i] == '/'){
item.value = str[i];
item.type = OPERATOR;
PushQueue(queue, item);
}
else if(str[i] == '('){
item.value = str[i];
item.type = PARENT_OPEN;
PushQueue(queue, item);
}
else if(str[i] == ')'){
item.value = str[i];
item.type = PARENT_CLOSE;
PushQueue(queue, item);
}
else if(str[i] >= '0' && str[i] <= '9'){
GVHD: Trịnh Thị Phú
Sinh vên thực hiện: Hoàng Năng Hưng
11
Bài tiểu luận môn: Cấu trúc dữ liệu và giải thuật
item.value = DocSo(str, i);
item.type = OPERAND;
PushQueue(queue, item);
i--;
}
i++;
}
}
// do uu tien
int priority(int optr){
if(optr == '(' || optr == ')')
return 1;
if(optr == '+' || optr == '-')
return 2;
if(optr == '*' || optr == '/')
return 3;
return 0;
}
// chuyen tu bieu thuc trung to sang hau to
void Convert(QUEUE *queue, QUEUE *output){
int size = queue ->size;
QUEUENODE *i;
Item item;
STACK stack;
InitStack(&stack);
for(i = queue ->rear; i != NULL; i = i ->prev){
item = i ->item;
switch(item.type){
case OPERAND:{
PushQueue(output, item);
}
break;
case OPERATOR:{
while(priority(item.value) <=
priority(PeekStack(&stack).value) && stack.size > 0){
Item iTemp = PopStack(&stack);
PushQueue(output, iTemp);
}
PushStack(&stack, item);
}
break;
case PARENT_OPEN:{
PushStack(&stack, item);
GVHD: Trịnh Thị Phú
Sinh vên thực hiện: Hoàng Năng Hưng
12
Bài tiểu luận môn: Cấu trúc dữ liệu và giải thuật
}
break;
case PARENT_CLOSE:{
item = PopStack(&stack);
while(item.type != PARENT_OPEN){
PushQueue(output, item);
item = PopStack(&stack);
}
}
break;
}
}
while(stack.size > 0) {
item = PopStack(&stack);
PushQueue(output, item);
}
}
void Print(QUEUE *queue){
QUEUENODE *i;
Item item;
for(i = queue ->rear; i != NULL; i = i ->prev){
item = i ->item;
switch(item.type){
case OPERAND:
printf("%d ", (int)item.value);
break;
case OPERATOR:
case PARENT_OPEN:
case PARENT_CLOSE:
printf("%c ", (int)item.value);
break;
}
}
printf("\n");
}
// tinh gia tri cua bieu thuc hau to
float Calculate(QUEUE *queue){
float result = 0;
STACK stack;
InitStack(&stack);
QUEUENODE *i;
Item item;
for(i = queue ->rear; i != NULL; i = i ->prev){
item = i ->item;
GVHD: Trịnh Thị Phú
Sinh vên thực hiện: Hoàng Năng Hưng
13
Bài tiểu luận môn: Cấu trúc dữ liệu và giải thuật
if(item.type == OPERAND)
PushStack(&stack, item);
else{ //OPERATOR
if(stack.size < 2)
return ERROR;
float a = PopStack(&stack).value;
float b = PopStack(&stack).value;
switch((int)item.value){
case '+':
result = a + b;
break;
case '-':
result = b - a;
break;
case '*':
result = a * b;
break;
case '/':
if(a == 0)
result = 0;
else
result = b / a;
}
item.value = result;
item.type = OPERAND;
PushStack(&stack, item);
}
}
return PopStack(&stack).value;
}
// chuyen bieu thuc trung to sang tien to
void Convert2(QUEUE *queue, QUEUE *output){
int size = queue ->size;
QUEUENODE *i;
Item item;
STACK stack;
InitStack(&stack);
for(i = queue ->front; i != NULL; i = i ->next){
item = i ->item;
switch(item.type){
case OPERAND:{
PushQueue(output, item);
}
break;
GVHD: Trịnh Thị Phú
Sinh vên thực hiện: Hoàng Năng Hưng
14
Bài tiểu luận môn: Cấu trúc dữ liệu và giải thuật
case OPERATOR:{
while(priority(item.value) <
priority(PeekStack(&stack).value) && stack.size > 0){
Item iTemp = PopStack(&stack);
PushQueue(output, iTemp);
}
PushStack(&stack, item);
}
break;
case PARENT_OPEN:{
item = PopStack(&stack);
while(item.type != PARENT_CLOSE){
PushQueue(output, item);
item = PopStack(&stack);
}
}
break;
case PARENT_CLOSE:{
PushStack(&stack, item);
}
break;
}
}
while(stack.size > 0){
item = PopStack(&stack);
PushQueue(output, item);
}
}
void Print2(QUEUE *queue){
QUEUENODE *i;
Item item;
for(i = queue ->front; i != NULL; i = i ->next){
item = i ->item;
switch(item.type){
case OPERAND:
printf("%d ", (int)item.value);
break;
case OPERATOR:
case PARENT_OPEN:
case PARENT_CLOSE:
printf("%c ", (int)item.value);
break;
}
GVHD: Trịnh Thị Phú
Sinh vên thực hiện: Hoàng Năng Hưng
15
Bài tiểu luận môn: Cấu trúc dữ liệu và giải thuật
}
printf("\n");
}
// tinh gia tri cua bieu thuc tien to
float Calculate2(QUEUE *queue){
float result = 0;
STACK stack;
InitStack(&stack);
QUEUENODE *i;
Item item;
for(i = queue ->rear; i != NULL; i = i ->prev){
item = i ->item;
if(item.type == OPERAND)
PushStack(&stack, item);
else{ //OPERATOR
if(stack.size < 2)
return ERROR;
float a = PopStack(&stack).value;
float b = PopStack(&stack).value;
switch((int)item.value){
case '+':
result = a + b;
break;
case '-':
result = a - b;
break;
case '*':
result = a * b;
break;
case '/':
if(b == 0)
result = 0;
else
result = a / b;
}
item.value = result;
item.type = OPERAND;
PushStack(&stack, item);
}
}
return PopStack(&stack).value;
}
int main()
{
GVHD: Trịnh Thị Phú
Sinh vên thực hiện: Hoàng Năng Hưng
16
Bài tiểu luận môn: Cấu trúc dữ liệu và giải thuật
char str[100];
float t;
QUEUE infix, postfix, prefix;
InitQueue(&infix);
InitQueue(&postfix);
InitQueue(&prefix);
printf("\nNhap bieu thuc trung to: ");
gets(str);
Tach(str, &infix);
Convert(&infix, &postfix);
printf("\nBieu thuc hau to la: ");
Print(&postfix);
t = Calculate(&postfix);
if(t == ERROR)
printf("\nBieu thuc loi!");
else
printf("\nGia tri bieu thuc: %0.2f", t);
printf("\n");
Convert2(&infix, &prefix);
printf("\nBieu thuc tien to la: ");
Print2(&prefix);
t = Calculate2(&prefix);
if(t == ERROR)
printf("\nBieu thuc loi!");
else
printf("\nGia tri bieu thuc: %0.2f", t);
getch();
return 0;
}
Kết quả như sau:
GVHD: Trịnh Thị Phú
Sinh vên thực hiện: Hoàng Năng Hưng
17
Bài tiểu luận môn: Cấu trúc dữ liệu và giải thuật
Nhận xét: vẫn cịn rất nhiều cách khác thuật tốn khác để có thể áp dụng chuyển
1 biểu thức trung tố sang hậu tố và tiền tố, tính giá trị của biểu thức tiền tố và hậu
tố. Thế nhưng đây là cách đầy đủ và rõ ràng nhất. Nó áp dụng rất tốt cho nhưng
người đang lập trình. Bởi vì nó bao gồm đầy đủ, sử dụng cả Stack và Queue.
Phần III: Kết luận
Thơng qua việc tìm hiểu về ứng dụng của Stack và Queue để để viết
chương trình biến đổi biểu thức trung tố thành tiền tố, hậu tố và tính giá trị của
biểu thức tiền tố và hậu tố em đã rút ra được rất nhiều điều. Từ cách xác định được
giải thuật đến tư duy logic và chương trình đã chạy thành cơng trên phần mềm
Devcpp++ 5.11 bằng ngôn ngữ C/C++. Rút ra được cách làm một bài tiểu luận
đúng và chuẩn.
Có được kết quả trên là nhờ có sự dạy dỗ chu đáo của cơ giáo Trịnh Thị Phú
trong q trình truyền thụ kiến thức mơn học cấu trúc dữ liệu và giải thuật, đồng
thời cô cũng là người hướng dẫn tận tình trong suốt quá trình thực hiện đề tài tiểu
luận mơn học này.
GVHD: Trịnh Thị Phú
Sinh vên thực hiện: Hoàng Năng Hưng
18
Bài tiểu luận môn: Cấu trúc dữ liệu và giải thuật
Em xin chân thành cám ơn cơ!
Thanh Hóa, ngày….tháng 11 năm 2015
Giáo viên hướng dẫn
Sinh viên thực hiện
Ths. Trịnh Thị Phú
Hồng Năng Hưng
TÀI LIỆU THAM KHẢO
[1] Giáo trình cấu trúc dữ liệu và giải thuật, Đỗ Xuân Lôi, NXB Đại học Quốc Gia
Hà Nội.
[2] Lập trình C căn bản, Hanoi Aptech Computer Education Center.
[3] Gs. Phạm Văn Ất. Kỹ thuật lập trình C cơ sở và nâng cao, NXB Giao thông
vận tải Hà Nội – 2006.
GVHD: Trịnh Thị Phú
Sinh vên thực hiện: Hoàng Năng Hưng
19
Bài tiểu luận môn: Cấu trúc dữ liệu và giải thuật
GVHD: Trịnh Thị Phú
Sinh vên thực hiện: Hoàng Năng Hưng
20