1. Trang chủ
  2. » Luận Văn - Báo Cáo

bài tập lớn kết thúc học phần môn cấu trúc dữ liệu và thuật toán

43 0 0
Tài liệu đã được kiểm tra trùng lặp

Đ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

Nội dung

1.1.Các thao tác trên danh sách liên kếtDanh sách liên kết là 1 cấu trúc dữ liệu có kiểu tuần tự, mỗi phần tử trong danh sách liên kết có chứa thông tin, qua đó ta có thể truy cập tới ph

Trang 1

TRƯỜNG ĐẠI HỌC PHENIKAAKHOA KHOA HỌC CƠ BẢN

BÀI TẬP LỚN KẾT THÚC HỌC PHẦNMôn Cấu trúc dữ liệu và thuật toán

Lớp Cấu trúc dữ liệu và thuậttoán_1.1(13.14FS).2_LT

Trang 2

1.1.Các thao tác trên danh sách liên kết

Danh sách liên kết là 1 cấu trúc dữ liệu có kiểu tuần tự, mỗi phần tử trong danh sách liên kết có chứa thông tin, qua đó ta có thể truy cập tới phần tử này.

Danh sách liên kết có thể được xem như là 1 sự bố trí tuần tự các phần tử trong 1 tập Bắt đầu từ 1 nút, ta coi đó là phần tử đầu tiên trong danh sách Từ nút này, theo liên kết mà nó trỏ tới, ta có nút thứ 2, được coi là phần tử thứ 2 trong danh sách, v.v cứ tiếp tục như vậy cho đến hết danh sách Nút cuối cùng có thể có liên kết là một liên kết null, tức là không trỏ tới nút nào, hoặc nó có thể trỏ về nút đầu tiên để tạo thành 1 vòng.

• Các thao tác trên danh sách liên kết

- Tạo, cấp phát, và giải phóng bộ nhớ cho 1 nút

listnode p; // Khai báo biến p

p = (listnode)malloc(sizeof(struct node));//cấp phát bộ nhớ cho p free(p); //giải phóng bộ nhớ đã cấp phát cho nút p;

Trang 3

- Chèn một nút vào đầu danh sách

B1 Tạo và cấp phát bộ nhớ cho một nút mới ,đc trỏ tới bởi q

B2 Sau khi gán các giá trị thích hợp cho phần tử của nút mới, cho con trỏ tiếp của nút mới trỏ đến phần tử đầu tiên của nút.

B3 Để p trỏ đến đầu nút danh sách ,ta cần cho p trỏ đến nút mới tạo

void Insert_Begin(listnode *p, int x){ listnode q;

q = (listnode)malloc(sizeof(struct node)); q-> item = x;

q-> next = *p; *p = q;

}

Trang 4

- Chèn một nút vào cuối danh sách

B1 Dịch chuyển con trỏ tới nút cuối của danh sách Để làm được việc này, ta phải khai báo một biến con trỏ mới r Ban đầu, biến này, cùng vớip, trỏ đến đầu danh sách Lần lượt dịch chuyển r theo các nút kế tiếp chotới khi đến cuối danh sách

B2 Cho con trỏ tiếp của nút cuối (được trỏ tới bởi r) trỏ đến nút mới tạo là q, và con trỏ tiếp của q trỏ tới null

void Insert_End(listnode *p, int x){listnode q, r;

q = (listnode)malloc(sizeof(struct node)); q-> item = x;

q->next = NULL;

if (*p==NULL) *p = q; else{

r = *p;

while (r->next != NULL) r = r->next; r->next = q;

Trang 5

} }

- Chèn một nút vào trước nút r trong danh sách

B1 Cho con trỏ tiếp của nút mới trỏ đến nút kế tiếp của nút r.

B2 Cho con trỏ tiếp của nút r trỏ đến q

void Insert_Middle(listnode *p, int position, int x){ int count=1, found=0;

listnode q, r; r = *p;

while ((r != NULL)&&(found==0)){ if (count == position){

q = (listnode)malloc(sizeof(struct node)); q-> item = x;

Trang 6

r-> next = q; found = 1; }

count ++; r = r-> next; }

if (found==0)

printf(“Khong tim thay vi tri can chen !”); }

- Xóa một nút ở đầu danh sách

B1 Dùng một con trỏ tạm q trỏ đến đầu danh sách

B2 Dịch chuyển con trỏ p qua phần tử đầu tiên đến phần tử kế tiếp

Trang 7

B3 Ngắt liên kết của biến tạm q với nút tiếp theo, giải phóng bộ nhớ Cho q.

void Remove_Begin(listnode *p){ listnode q;

if (*p == NULL) return; q = *p;

*p = (*p)-> next; q-> next = NULL; free(q);

}

Trang 8

- Xóa một nút ở cuối danh sách

B1 Dịch chuyển con trỏ tới nút gần cuối của danh sách Để làm được việc này, ta phải dùng 2 biến tạm là q và r Lần lượt dịch chuyển q và r từ đầu danh sách tới cuối danh sách, trong đó q luôn dịch chuyển sau r một nút Khi r tới nút cuối cùng thì q là nút gần cuối cùng nhất

B2 Cho con trỏ tiếp của nút gần cuối cùng nhất (đang được trỏ bởi q) trỏtới null Giải phóng bộ nhớ cho nút cuối cùng (đang được trỏ bởi r)

void Remove_End(listnode *p){ listnode q, r;

if (*p == NULL) return; if ((*p)-> next == NULL){ Remove_Begin(*p);

return;

Trang 9

q-> next = NULL; free(r);

Trang 10

B3 Ngắt liên kết của nút q và giải phóng bộ nhớ cho q

void Remove_Middle(listnode *p, int position){ int count=1, found=0;

listnode q, r; r = *p;

while ((r != NULL)&&(found==0)){ if (count == position){

q = r-> next;

r-> next = q-> next; q-> next = NULL; free (q);

found = 1; }

count ++; r = r-> next;

Trang 11

}

if (found==0)

printf(“Khong tim thay vi tri can xoa !”); }

- Duyệt toàn bộ danh sách

Thao tác duyệt danh sách cho phép duyệt qua toàn bộ các phần tử của danh sách, từ phần tử đầu tiền cho tới phần tử cuối cùng

Để thực hiện thao tác này, ta cần một biến tạm r trỏ tới đầu danh sách Từ vị trí này, theo liên kết của các nút, thực hiện duyệt qua từng phần tử trong danh sách Trong quá trình duyệt, tại mỗi nút ta có thể thực hiện các thao tác cần thiết như lấy thông tin phần tử, sửa thông tin, so sánh, v.v

r = p;

while (r-> next != null){

//thực hiện các thao tác cần thiết r = r-> next;

Trang 12

Chương trình chạy:

#include <stdio.h>#include <string.h>#include <stdlib.h>#include <stdbool.h>

struct node {

int data; int key;

struct node *next;};

Trang 13

struct node *head = NULL;struct node *current = NULL;

//hien thi danh sachvoid printList(){

struct node *ptr = head; printf("\n[ ");

//bat dau tu phan dau danh sach while(ptr != NULL)

{

printf("(%d,%d) ",ptr->key,ptr->data); ptr = ptr->next;

}

printf(" ]");

Trang 14

//chen link tai vi tri dau tienvoid insertFirst(int key, int data){

//tao mot link

struct node *link = (struct node*) malloc(sizeof(struct node));

link->key = key; link->data = data;

//tro link nay toi first node cu link->next = head;

//tro first toi first node moi head = link;

}

Trang 15

//xoa phan tu dau tienstruct node* deleteFirst(){

//luu tham chieu toi first link struct node *tempLink = head;

//danh dau next toi first link la first head = head->next;

//tra ve link bi xoa return tempLink;}

//kiem tra list co trong hay khongbool isEmpty()

Trang 16

return head == NULL;}

int length(){

int length = 0;

struct node *current;

for(current = head; current != NULL; current = current->next){

length++; }

return length;}

Trang 17

//tim mot link voi key da chostruct node* find(int key){

//bat dau tim tu first link struct node* current = head;

//neu list la trong if(head == NULL)

return NULL; }

//duyet qua list

while(current->key != key){

//neu day la last node

if(current->next == NULL){

Trang 18

return NULL; }else {

//di chuyen toi next link current = current->next; }

//bat dau tu first link

struct node* current = head; struct node* previous = NULL;

Trang 19

//neu list la trong if(head == NULL){ return NULL; }

//duyet qua list

while(current->key != key){

//neu day la last node

if(current->next == NULL){ return NULL;

Trang 20

return current;}

// ham sap xep

Trang 21

void sort(){

int i, j, k, tempKey, tempData ; struct node *current;

struct node *next;

int size = length(); k = size ;

for ( i = 0 ; i < size - 1 ; i++, k ) { current = head ;

next = head->next ;

for ( j = 1 ; j < k ; j++ ) {

if ( current->data > next->data ) { tempData = current->data ;

Trang 22

next->data = tempData ;

tempKey = current->key; current->key = next->key; next->key = tempKey; }

current = current->next;

next = next->next; }

} }

// ham dao nguoc list

void reverse(struct node** head_ref) { struct node* prev = NULL;

struct node* current = *head_ref;

Trang 23

struct node* next;

while (current != NULL) { next = current->next; current->next = prev; prev = current;

current = next; }

*head_ref = prev;}

main() {

insertFirst(1,10); insertFirst(2,20); insertFirst(3,30);

Trang 24

insertFirst(4,1); insertFirst(5,40); insertFirst(6,56);

printf("Danh sach ban dau: ");

//in danh sach printList();

while(!isEmpty()){

struct node *temp = deleteFirst(); printf("\nGia tri bi xoa:");

printf("(%d,%d) ",temp->key,temp->data); }

printf("\nDanh sach sau khi da xoa gia tri: "); printList();

Trang 25

insertFirst(1,10); insertFirst(2,20); insertFirst(3,30); insertFirst(4,1); insertFirst(5,40); insertFirst(6,56);

printf("\nPhuc hoi danh sach: "); printList();

}else {

Trang 26

printf("Khong tim thay phan tu."); }

}else {

printf("Khong tim thay phan tu."); }

Trang 27

printf("\n"); sort();

printf("Danh sach sau khi duoc sap xep: "); printList();

reverse(&head);

printf("\nDanh sach sau khi bi dao nguoc: "); printList();

1.2 Các thao tác trên hàng đợi

- Thao tác khởi tạo hàng đợi

Thao tác này thực hiện việc gán giá trị 0 cho biến head, giá trị MAX -1 cho biến tail, và giá

trị 0 cho biến count, cho biết hàng đợi đang ở trạng thái rỗng void QueueInitialize(queue *q){

Trang 28

q-> head = 0; q-> tail = MAX-1; q-> count = 0; return;

}

- Thao tác kiểm tra hàng đợi rỗng

Hàng đợi rỗng nếu có số phần tử nhỏ hơn hoặc bằng 0 int QueueEmpty(queue q){

return (q.count <= 0); }

- Thao tác thêm 1 phần tử vào hàng đợi

void Put(queue *q, int x){ if (q-> count == MAX) printf(“Hang doi day !”); else{

if (q->tail == MAX-1 ) q->tail=0;

else

(q->tail)++;

q->node[q->tail]=x; q-> count++;

Trang 29

} return;}

Để thêm phần tử vào cuối hàng đợi, điểm cuối tăng lên 1 (nếu điểm cuốiđã ở vị trí cuối mảng thì quay vòng điểm cuối về 0) Trước khi thêm phần tử vào hàng đợi, cần kiếm tra xem hàng đợi đã đầy chưa (hàng đợi đầy khi giá trị biến count = MAX).

- Lấy phần tử ra khỏi hàng đợi

Để lấy phần tử ra khỏi hàng đợi, tiến hành lấy phần tử tại vị trí điểm đầu và cho điểm đầu tăng lên 1 (nếu điểm đầu đã ở vị trí cuối mảng thì quay vòng điểm đầu về 0) Tuy nhiên, trước khi làm các thao tác này, ta phải kiểm tra xem hàng đợi có rỗng hay không

int Get(queue *q){ int x;

if (QueueEmpty(*q)) printf("Hang doi rong !"); else{

x = q-> node[q-> head]; if (q->head == MAX-1 ) q->head=0;

else

(q->head)++; q-> count ;

Trang 30

return x; }

- Cài đặt hàng đợi bằng danh sách liên kết

Để cài đặt hàng đợi bằng danh sách liên kết, ta cũng sử dụng 1 danh sách liên kết đơn và 2 con trỏ head và tail lưu giữ nút đầu và nút cuối của danh sách Việc bổ sung phần tử mới sẽ được tiến hành ở cuối danh sách và việc lấy phần tử ra sẽ được tiến hành ở đầu danh sách.

Khai báo 1 hàng đợi bằng danh sách liên kết như sau: struct node {

Khai báo tương tự như ngăn xếp, tuy nhiên, hàng đợi sử dụng 2 biến là hea và tail để lưu giữ điểm đầu và điểm cuối của hàng Khi đó, các thao tác trên hàng đợi được cài đặt như sau:

Trang 31

-Thao tác khởi tạo hàng đợi

Thao tác này thực hiện việc gán giá trị null cho nút đầu và cuối của hàngđợi, cho biết hàng

đợi đang ở trạng thái rỗng

void QueueInitialize(queue *q){ q-> head = q-> tail = NULL; return;

}

Thao tác kiểm tra hàng đợi rỗng

Hàng đợi rỗng nếu nút đầu trỏ đến NULL int QueueEmpty(queue q){

return (q.head == NULL); }

Thao tác thêm 1 phần tử vào hàng đợi void Put(queue *q, int x){

queuenode p;

p = (queuenode) malloc (sizeof(struct node)); p-> item = x;

p-> next = NULL; q-> tail-> next = p;

q-> tail = q-> tail-> next;

if (q-> head == NULL) q-> head = q-> tail; return;

Trang 32

Để thêm phần tử vào cuối hàng đợi, tạo và cấp phát bộ nhớ cho 1 nút mới Gán giá trị thích hợp cho nút này, sau đó cho con trỏ tiếp của nút cuối hàng đợi trỏ đến nó Nút này bây giờ trở thành nút cuối của hàng đợi Nếu hàng đợi chưa có phần tử nào thì nó cũng chính là nút đầu của hàng đợi.

- Lấy phần tử ra khỏi hàng đợi

Để lấy phần tử ra khỏi hàng đợi, tiến hành lấy phần tử tại vị trí nút đầu và cho nút đầu chuyển về nút kế tiếp Tuy nhiên, trước khi làm các thao tác này, ta phải kiểm tra xem hàng đợi có rỗng hay không

int Get(queue *q){ queuenode p;

if (QueueEmpty(*q)){ printf("Ngan xep rong !"); return 0;

1.3.Các thao tác trên ngăn xếp

Trang 33

- Thao tác khởi tạo ngăn xếp

Thao tác này thực hiện việc gán giá trị -1 cho biến top, cho biết ngăn xếpđang ở trạng thái rỗng

void StackInitialize(stack *s){ s-> top = -1;

return; }

- Thao tác kiểm tra ngăn xếp rỗng

int StackEmpty(stack s){ return (s.top = = -1); }

- Thao tác kiểm tra ngăn xếp đầy

int StackFull(stack s){ return (s.top = = MAX-1);}

- Thao tác bổ sung 1 phần tử vào ngăn xếp

void Push(stack *s, int x){ if (StackFull(*s)){

printf(“Ngan xep day !”); return;

}else{ s-> top ++;

s-> nut[s-> top] = x;

Trang 34

} }

-Thao tác lấy 1 phần tử ra khỏi ngăn xếp

int Pop(stack *s){ if (StackEmpty(*s)){

printf(“Ngan xep rong !”); }else{

return s-> nut[s-> top ]; }

- Thao tác khởi tạo ngăn xếp

Thao tác này thực hiện việc gán giá trị null cho nút đầu ngăn xếp, cho biết ngăn xếp đang ở trạng thái rỗng

void StackInitialize(stack *s){ s-> top = NULL;

return; }

- Thao tác kiểm tra ngăn xếp rỗng

int StackEmpty(stack s){ return (s.top == NULL); }

Trang 35

-Thao tác bổ sung 1 phần tử vào ngăn xếp

void Push(stack *s, int x){ stacknode p;

p = (stacknode) malloc (sizeof(struct node)); p-> item = x;

p-> next = s->top; s->top = p;

return;}

- Thao tác lấy 1 phần tử ra khỏi ngăn xếp

int Pop(stack *s){ stacknode p;

if (StackEmpty(*s)){ printf("Ngan xep rong !"); }else{

p = s-> top;

s-> top = s-> top-> next; return p->item;

} }

Trang 36

1.4 Duyệt cây nhị phân

- Duyệt thứ tự trước

void PreOrder (treenode root ) { if (root !=NULL) {

printf(“%d”, root.item); PreOrder(root.left); PreOrder(root.right); }

- Duyệt thứ tự sau

void PostOrder (treenode root ) { if (root !=NULL) {

Trang 37

PreOrder(root.left); PreOrder(root.right); printf(“%d”, root.item); }

chúng tôi đã tìm thấy phần tử Trong tìm kiếm nhị phân, chúng tôi

bắt đầu với phần tử 'n' trong không gian tìm kiếm và sau đó nếu

phần tử ở giữa không phải là phần tử mà chúng tôi đang tìm kiếm,

chúng tôi giảm không gian tìm kiếm thành 'n / 2'và chúng tôi tiếp

tục giảm không gian tìm kiếm cho đến khi chúng tôi tìm thấy bản ghi mà chúng tôi đang tìm kiếm hoặc chúng tôi chỉ nhận được một phần tử trong không gian tìm kiếm và được thực hiện với toàn bộ việc giảm bớt này

Thao tác tìm kiếm trong cây tìm kiếm nhị phân sẽ rất giống

Trang 38

sẽ làm là chúng ta sẽ bắt đầu từ gốc và sau đó chúng ta sẽ so sánh giá trị được tìm kiếm với giá trị của gốc nếu nó bằng nhau, chúng ta đã hoàn thành việc tìm kiếm nếu nó ít hơn chúng ta biết rằng chúng ta cần phải chuyển đến cây con bên trái vì trong cây tìm kiếm nhị phân, tất cả các phần tử trong cây con bên trái nhỏ hơn và tất cả các phần tử trong cây con bên phải lớn hơn Tìm kiếm một phần tử trong cây tìm kiếm nhị phân về cơ bản là quá trình này, trong đó ở mỗi bước, chúng ta sẽ đi theo hướng sang trái hoặc phải và do đó ở mỗi bước, chúng ta loại bỏ một trong các cây con Nếu cây cân bằng, chúng ta gọi là cây cân bằng nếu đối với tất cả các nút, sự khác biệt giữa chiều cao của cây con bên tráivà bên phải không lớn hơn một, chúng ta sẽ bắt đầu với không

gian tìm kiếm làcác nút 'n' và khi chúng ta loại bỏ một trong các cây con, chúng ta sẽ loại bỏ các nút 'n / 2' để không gian tìm kiếmcủa chúng ta sẽ giảm xuống còn 'n / 2' và sau đó trong bước tiếp theo, chúng ta sẽ giảm không gian tìm kiếm xuống 'n / 4' và

chúng tôi sẽ tiếp tục giảm như vậy cho đến khi chúng tôi tìm thấy phần tử hoặc cho đến khi không gian tìm kiếm của chúng tôi giảmxuống chỉ còn một nút Tìm kiếm ở đây cũng là tìm kiếm nhị phânvà đó là lý do tại sao có tên là cây tìm kiếm nhị phân.

• Chèn một nút vào BST

Cho BST, thao tác chèn phải có kết quả là BST• Làm sao biết vị trí đặt nút 'D'?

Ngày đăng: 25/07/2024, 16:09

w