350 likes | 544 Vues
Xin vui lòng yên lặng. Chương 1: Các kiểu dữ liệu cơ bản và cấu trúc. Định nghĩa và các phép toán trên danh sách đặc. Định nghĩa Cách biểu diễn và các phép toán trên danh sách đặc Khởi tạo danh sách Thêm một phần tử vào danh sách Loại bỏ một phần tử của danh sách
E N D
Định nghĩa và các phép toán trên danh sách đặc • Định nghĩa • Cách biểu diễn và các phép toán trên danh sách đặc • Khởi tạo danh sách • Thêm một phần tử vào danh sách • Loại bỏ một phần tử của danh sách • Tìm kiếm một phần tử của danh sách • Duyệt danh sách
1. Mảng (Array) – Định nghĩa • Định nghĩa: Mảng là cấu trúc bao gồm các thành phần cùng kiểu dữ liệu, mỗi thành phần được gọi là phần tử và xác định qua chỉ số. Trong C/C++ khai báo: elem a[spt]; Trong đó elem là kiểu phần tử (element type); spt là số phần tử. Ví dụ: int a[10]; //mảng a gồm 10 phần tử kiểu int float b[20]; //mảng b gồm 20 phần tử kiểu float
Tổ chức lưu trữ • Mảng được quản lý bằng một địa chỉ trong bộ nhớ máy tính và các phần tử được bố trí tuần tự liên tiếp theo chỉ số • Chính vì vậy dãy dữ liệu lưu trữ trong mảng còn được gọi là danh sách đặc 0 1 2 9 a
0 1 2 3 9 a Truy xuất • Truy xuất mảng: Truy xuất qua các phần tử của mảng theo chỉ số i. Trong C/C++: <tên mảng>[i] Bằng cách tính địa chỉ: @a + i * sizeof(elem) Ví dụ: a[3] truy xuất đến địa chỉ: 1000+3*2 1000 1006
Ví dụ • Viết đoạn chương trình cộng dồn n giá trị của mảng vào a[0] for (i=1; i<n; i++) a[0] = a[0]+a[i]; Viết lại t = a[0]; for (i=1; i<n; i++) t = t+a[i]; a[0] = t;
0 1 2 3 0 1 a a[0] a[1] a[2] Mảng nhiều chiều • Là mảng bao gồm các phần tử có kiểu là mảng vd: int a[3][4]; Vd: viết hàm tìm max của mảng số nguyên
int max( int a[ ], int n) { int m = a[0]; for (int i=1; i<n; i++) if (a[i]>m) m = a[i]; return m; }
0 1 2 3 0 1 b b[0] b[1] b[2] void main() { int b[3][4] = { { 7, 12, 6, 8}, { 32, 17, 21, 23}, { 1, 5, 35, 32}}; int a[] = {9, 7, 18, 6, 1, 3, 2, 5, 11, 4}; printf("\nMax cua b: %d", max(b[0], 12)); printf("\nMax cua a: %d", max(a, 10)); printf("\nMax : %d", max(a+5, 5)); }
*pa Con trỏ? • Con trỏ: Là kiểu dữ liệu dang địa chỉ bộ nhớ máy tính • Biến con trỏ: Lưu trữ địa chỉ của vùng nhớ máy tính • Khai báo: <type> *<pointer_var> Ví dụ: float *pa, a, b; pa
*pa Các phép toán • Toán tử &: Lấy địa chỉ của 1 đối tượng &<object> Ví dụ: float *pa, a, b; pa = &a; a pa
a *pa pa Các phép toán • Toán tử *: Truy xuất đến vùng nhớ mà con trỏ trỏ đến *<pointer> Ví dụ: float *pa, a, b; pa = &a; *pa = 5; 5
pa 0 1 2 3 9 a Mảng và con trỏ • Mảng được quản lý bằng địa chỉ • Con trỏ lưu địa chỉ Vì vậy, trong một số tình huống con trỏ được đồng nhất với mảng và ngược lại Ví dụ: int a[10], *pa; pa = a;
pa 0 1 2 3 9 a 5 Mảng và con trỏ - tt *pa = 5; a[0]=5 pa = &a[5]; *pa = 7; a[5]=7 pa 0 1 2 3 9 a 7 5
Phép toán +, -, ++, -- • Phép +/-: Tăng hay giảm n đơn vị trỏ <pointer> = <pointer> + n <pointer> += n n là số nguyên • Phép ++/--: Tăng hay giảm 1 đơn vị trỏ <pointer> ++ ++<pointer> Ví dụ: pa = a;
pa pa 0 1 2 3 9 0 1 2 3 9 a 5 a 5 Ví dụ: pa = a; pa = pa+3;
pa 0 1 2 3 9 a 5 *pa=1; a[3]=1 *(pa+4) = 2 a[7]=2 *(a+4) = 9 a[4]=9 pa[5] = 6 a[8]=6 a++; // Sai, a không thay đổi được 1 9 2 6
Cấp phát/thu hồi bộ nhớ • Cấp phát bộ nhớ động • C: hàm malloc() (void *)malloc(int size) Cấp vùng nhớ có size byte trả về địa chỉ của vùng nhớ được cấp phát • C++: toán tử new new <type>[size] [size] là thành phần nhiệm ý Cấp vùng nhớ có size phần tử trả về địa chỉ của vùng nhớ được cấp phát Ví dụ cấp phát mảng 10 phần tử nguyên int *pa = new int[10];
Cấp phát/thu hồi bộ nhớ - tt • Thu hồi bộ nhớ • C: hàm free() void free(<pointer>) • C++: toán tử delete delete [size]<type> [size] là thành phần nhiệm ý Thu hồi vùng nhớ mà con trỏ trỏ đến Ví dụ thu hồi vùng nhớ mà con trỏ pa trỏ đến delete pa [10]int;
0 1 3 4 7 8 2 5 6 #7 N H O C T I Chuỗi ký tự (String) • Định nghĩa: Là 1 dãy các ký tự chọn lọc • Cài đặt: Dựa trên mảng các ký tự, có 2 cách cài đặt • Cách 1: Sử dụng byte đầu tiên để lưu chiều dài chuỗi (Pascal sử dụng cách này). Ví dụ chuỗi “TIN HOC” S[8]=‘A’ S=“TIN HOC” S[2]=‘A’ S=“TAN HOC”
Cách 2: Sử dụng 1 ký tự đặc biệt làm ký tự kết thúc chuỗi (C/C++ sử dụng cách này). Ví dụ chuỗi “TIN HOC” ‘\0’: kí tự có mã ASCii là 0 S[1]=‘A’ S=“TAN HOC” 0 1 3 4 7 8 2 5 6 N H O C \0 T I
Các thao tác trên chuỗi • Sao chép chuỗi (strcpy) • So sánh chuỗi (strcmp) • Chiều dài chuỗi (strlen) • Ghép chuỗi (strcat) • Tìm kiếm vị trí chuỗi trong chuỗi (strstr) • …..
VD sao chép chuỗi void strcpy(char s1[], char s2[]) { int i = 0; while (s2[i] != ‘\0’) { s1[i] = s2[i]; i++; } s1[i] = ‘\0’; }
VD sao chép chuỗi – viết lại void strcpy(char s1[], char s2[]) { int i = 0; while (s1[i] = s2[i]) i++; }
VD sao chép chuỗi – viết lại lần cuối void strcpy(char *s1, char *s2) { while (*s1++ = *s2++); } • Ghép s2 vào cuối s1 void strcat(char *s1, char *s2) { while (*s1) s1++; while (*s1++ = *s2++); }
Ghép chuỗi – viết theo bản 2 void strcat(char s1[], char s2[]) { int i = 0, j=0; while (s1[i]) i++; while (s1[i++] = s2[j++]); }
Đổi chuỗi thành số int atoi(char *s) { int P = 0; while (*s) P = P*10 + *s++ -’0’; return P; }
So sánh 2 chuỗi int strcmp(char *s1, char *s2) { while (*s1 == *s2 && *s1) { s1++; s2++; } return *s1-*s2; }
Trừu tượng hóa dữ liệu • Thiết kế 1 cấu trúc dữ liệu cần đạt được tính trừu tượng hóa dữ liệu: • Dữ liệu phải được đóng gói: Người lập trình chỉ biết kiểu dữ liệu qua tên gọi và ngữ nghĩa của nó mà không quan đến tổ chức vật lý • Che chắn tốt: Người lập trình chỉ truy xuất đến nó thông qua các thao tác (hàm) mà kiểu dữ liệu cung cấp. • Người thiết kế phải thiết kế kiểu dữ liệu tổng quát nhất
Ví dụ: Thiết kế kiểu tập hợp #define MAX … // do người sử dụng xác định #define N (MAX/8+1) typedef unsigned char taphop[N]; //============== Tao tap rong ========= void taprong(taphop s) { int i; for (i=0; i<N; i++) s[i] = 0; }
//========== Dua phan tu x vao tap hop s void thempt(taphop s, int x) { s[x/8] = s[x/8] | (1<<(x%8)); } //========== Loai phan tu x ra khoi tap hop s void loaipt(taphop s, int x) { unsigned char k = 1<<(x%8); s[x/8] = s[x/8] & ~k; }
//========== Kiem tra phan tu x thuoc tap hop s int thuocve (taphop s, int x) { return s[x/8] & (1<<(x%8)); } //========== Hội 2 tap hop void hoi(taphop a, taphop b, taphop c) { int i; for (i=0; i<N; i++) c[i] = a[i] | b[i]; } Các hàm này lưu vào tập tin “TAPHOP.CPP” và không compile
#include <iostream.h> #include <iomanip.h> #define MAX 10000 #include "TAPHOP.CPP" void main() { int n, i, k; taphop s; cout<<"\nNhap n:"; cin>>n; taprong(s); for (i=2; i<=n; i++) thempt(s, i); i = 2; while (i*i<=n) { k = i*i; while (k<=n) { loaipt(s, k); k = k+i; } do i++; while (!thuocve(s, i)); } cout<<"\nKet qua:\n"; for (i=2; i<=n; i++) if (thuocve(s, i)) cout<<setw(4)<<i; } Ví dụ: Tìm các số nguyên tố<=n