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

Kỹ thuật lập trình C/C++-Chương: Cấu trúc dữ liệu

21 10 0

Đ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 21
Dung lượng 264,14 KB

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

Nội dung

Cấu trúc dữ liệu (CTDL) là một cách tổ chức dữ liệu của bài toán. CTDL có thể do ngôn ngữ lập trình định nghĩa trước hoặc có thể do người sử dụng định nghĩa. Cấu trúc dữ liệu tốt thì thuật toán xử lý bài toán mới tối ưu.Cấu trúc dữ liệu là một 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...

Trang 1

Cấu trúc dữ liệu

Trang 2

Mở đầu: mảng động

 Mảng trong C có số phần tử cố định từ khi khai báo

 Mảng động là mảng có số phần tử thay đổi: bản chất là một con trỏ và một biến cho biết số phần tử

 int n = 5;

int* arr = (int*)malloc(n*sizeof( int ));

 Bài toán chèn phần tử vào mảng động:

arr1 = (int*)malloc((n+1)*sizeof(int));

memcpy(arr1, arr, pos*sizeof(int));

memcpy(arr1+pos+1, arr+pos, (n-pos)*sizeof(int));

Trang 3

 Ánh xạ (map), từ điển (dictionary), bảng băm (hash table)

 Tập hợp (set)

 Cây (tree)

Trang 4

Danh sách liên kết (DSLK)

 Là tập hợp các phần tử được móc nối với nhau bằng con trỏ:

 Một con trỏ trỏ đến phần tử đầu tiên (hoặc NULL nếu chưa có phần tử nào)

 Mỗi phần tử bao gồm 2 thành phần: dữ liệu, con trỏ next tới phần tử tiếp theo

 Con trỏ next của phần tử cuối cùng trỏ đến NULL

Trang 6

Thao tác với DSLK

 Các hàm cần viết:

Trang 8

LLIST llInsertHead(LLIST l, int data) {

Trang 9

LLIST llInsertTail(LLIST l, int data) {

Trang 10

Thêm phần tử vào sau một phần tử của DSLK

LLIST llInsertAfter(LLIST l, PELEM a, int data) {

Trang 11

Xoá phần tử đầu trong DSLK

Trang 13

Xoá phần tử sau một phần tử trong DSLK

LLIST llDeleteAfter(LLIST l, PELEM a) {

a

Trang 14

Duyệt DSLK

 Tìm đến phần tử thứ i của DSLK

PELEM llSeek(LLIST l, int i) {

for (; i>0 && l; i )

l = l->next;

return (PELEM)l;

}

 Gọi hàm với mỗi phần tử của DSLK

typedef void (*LLCALLBACK)(int, void*);

void llForEach(LLIST l, LLCALLBACK func, void* user) {

for (; l; l=l->next)

func(l->data, user);

}

Trang 17

Đặc điểm của DSLK

 Ưu/nhược điểm so với mảng động:

+ Linh hoạt: thêm/bớt phần tử dễ dàng, sắp xếp và thay đổi thứ tự phần tử mà không cần di chuyển trong bộ nhớ

+ Không cần cấp phát một vùng nhớ lớn và liên tục

– Cần thêm bộ nhớ phụ cho các biến con trỏ

– Không truy cập tới phần tử bất kỳ thứ i được như mảng,

mà phải duyệt từ đầu tới

 Ngoài dạng cơ bản, có rất nhiều biến thể của DSLK: DSLK kép, DSLK có thứ tự, hàng đợi, ngăn xếp,

DSLK vòng,… và cũng có nhiều cách cài đặt khác nhau tuỳ thuộc vào bài toán cụ thể

Trang 18

Ngăn xếp (stack)

 Ngăn xếp là trường hợp riêng của

DSLK, chỉ có hai thao tác:

 push: thêm phần tử vào đầu danh sách

 pop: lấy giá trị đồng thời xoá phần tử đầu

danh sách

 thuộc loại danh sách LIFO (last in, first out)

 Ứng dụng:

 Tính toán biểu thức (ký pháp Ba Lan ngược)

 Thực hiện việc gọi hàm trong ngôn ngữ lập

trình

 Giải đệ quy

 Dữ liệu undo

Pop Push

Trang 19

Hàng đợi (queue)

 Hàng đợi là trường hợp riêng của DSLK,

chỉ có hai thao tác:

 thuộc loại danh sách FIFO (first in, first out)

 Để lập trình hàng đợi, thường dùng hai con

trỏ: một tới đầu danh sách để thêm, một tới

cuối danh sách để lấy phần tử

Trang 20

DSLK kép (doubly linked list)

 Trong DSLK thông thường, mỗi phần tử chỉ có một con trỏ next tới phần tử kế tiếp  gọi là DSLK đơn, chỉ duyệt

DS được một chiều

 DSLK kép: mỗi phần tử có thêm con trỏ prev tới phần tử

ở trước  có thể duyệt được hai chiều

data

next prev

data

next prev

data

next prev list

Trang 21

Bài tập

1. Khai báo DSLK kép và viết các hàm: thêm/xoá phần tử đầu

2. Viết các hàm Pop(), Push() của ngăn xếp và Enqueue(),

Dequeue() của hàng đợi dựa trên DSLK và nhận xét hàm nào

không hiệu quả

3. Tính giá trị trung bình các giá trị của một DSLK bằng hai cách:

duyệt danh sách, và sử dụng hàm llForEach()

4. Viết hàm llConvert(int* arr, int count) chuyển dữ liệu từ mảng sang

DSLK, không dùng các hàm đã viết

5. Viết hàm llReverse(LLIST l) đảo ngược thứ tự DSLK, không cấp

phát thêm phần tử mới

6. Như bài trên nhưng dùng phương pháp đệ quy

7. Có hai DSLK l1 và l2, viết hàm llInsertListAfter(l1, l2, p) để chèn l2

vào l1 ở sau vị trí của phần tử p

Ngày đăng: 08/05/2021, 19:21

TÀI LIỆU CÙNG NGƯỜI DÙNG

TÀI LIỆU LIÊN QUAN

🧩 Sản phẩm bạn có thể quan tâm

w