Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 56 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
56
Dung lượng
2,92 MB
Nội dung
Bài 01 ÔN TẬP KỸ THUẬT LẬP TRÌNH MỤC TIÊU Hoàn tất thực hành này, sinh viên có thể: Hiểu sử dụng kiểu trỏ C++ Phân biệt truyền tham biến truyền tham trị Thao tác đọc/ghi tập tin văn Hiểu rõ lập trình đệ quy, viết chương trình đệ quy THỜI GIAN THỰC HÀNH Từ 6-15 tiết, gồm Con trỏ: 2-5 tiết Truyền tham biến truyền tham trị: 1-3 tiết Thao tác đọc/ghi tập tin văn bản: 2-4 tiết Lập trình đệ quy: 1-3 tiết Trang Tài liệu hướng dẫn thực hành môn Cấu trúc liệu giải thuật HCMUS 2010 CON TRỎ Con trỏ khái niệm đặc biệt C/C++, loại biến dùng để chứa địa Các thao tác với trỏ qua bước: Khai báo biến trỏ Khởi tạo trỏ dùng cấp phát vùng nhớ Truy xuất giá trị ô nhớ từ biến trỏ Hủy vùng nhớ xin cấp phát 1.1 Khai báo biến trỏ C++ *; Ví dụ: int* pa; // trỏ đến kiểu int DIEM *pd; // trỏ đến kiểu DIEM Để xác định địa ô nhớ: toán tử & Ví dụ: int a = 1; int* pa = &a; // trỏ trỏ đến ô nhớ biến a 1.2 Khởi tạo biến trỏ dùng cấp phát vùng nhớ (cấp phát động) Sử dụng toán tử new Ví dụ: int* pInt = new int; // xin cấp phát vùng nhớ cho số nguyên DIEM *pDiem = new DIEM; // xin cấp phát vùng nhớ cho biến kiểu cấu trúc DIEM Toán tử new sử dụng thể cấp phát vùng nhớ cho nhiều phần tử int* arr = new int[5]; // xin cấp phát vùng nhớ cho số nguyên Lưu ý: Để kiểm tra cấp phát vùng nhớ thành công hay không, ta dùng trỏ đặc biệt NULL NULL trỏ đặc biệt, gán cho biến trỏ kiểu liệu khác Ví dụ: hợp lệ Tài liệu hướng dẫn thực hành môn Cấu trúc liệu giải thuật HCMUS 2010 Trang DIEM* pDiem = NULL; int* pInt = NULL; Để kiểm tra cấp phát thành công, ta làm sau: DIEM* pDiem = NULL; // khai báo trỏ gán NULL pDiem = new DIEM; // xin cấp phát vùng nhớ if (pDiem == NULL) // pDiem NULL xin cấp phát không thành công printf(“Cap phat khong cong”); 1.3 Truy xuất giá trị ô nhớ từ biến trỏ 1.3.1 Đối với kiểu liệu (như kiểu int, float, …) Để xác định giá trị ô nhớ địa biến trỏ: toán tử * Ví dụ: Với khai báo biến a, pa int a = 1; int* pa = &a; // trỏ trỏ đến ô nhớ biến a câu lệnh printf("%d\n", *pa); xuất “1” Giải thích: int a = 1; Với khai báo này, ô nhớ cấp phát nội dung ô nhớ int* pa = &a; Sau khai báo này, biến pa giữ địa ô nhớ vừa cấp phát cho biến a Khi đó, *pa lấy nội dung ô nhớ trỏ đến biến pa, mà biến pa giữ địa ô nhớ cấp phát cho biến a Vậy *pa = a = 1.3.2 Đối với kiểu liệu cấu trúc (như kiểu SINHVIEN, DIEM, …) Để truy xuất thành phần kiểu cấu trúc, dùng -> Ví dụ: { Tài liệu hướng dẫn thực hành môn Cấu trúc liệu giải thuật HCMUS 2010 Trang struct DIEM Với kiểu cấu trúc DIEM định nghĩa sau int hoanhDo, tungDo; } ; DIEM *pDiem = new DIEM; Để truy xuất thành phần dùng pDiem->hoanhDo pDiem->tungDo 1.4 Hủy vùng nhớ xin cấp phát Để hủy vùng nhớ xin cấp phát, dùng toán tử delete Với khai báo int* pa = new int; int* pb = new int[5]; Cách hủy tương ứng delete pa; delete pb[]; Bài tập (code mẫu: ConTroCoBan) #include struct DIEM { int hoanhDo, tungDo; } ; void main() { // khoi tao cac bien gia tri int a = 1; DIEM d; d.hoanhDo = 1; d.tungDo = 2; // khai bao bien tro va tro den vung nho cua cac bien gia tri da co int *pa = &a; int *pb = pa; DIEM *pd = &d; // xac dinh dia chi o nho: toan tu & printf("Dia chi o nho: %d \n", &a); // truy xuat gia tri o nho tu bien tro: toan tu * printf("Gia tri a: %d \n", *pa); } Tài liệu hướng dẫn thực hành môn Cấu trúc liệu giải thuật HCMUS 2010 Trang tro: printf("Diem D: (%d,%d)\n", d.hoanhDo, d.tungDo);//doi voi bien gia tri: printf("Diem D: (%d,%d)\n", pd->hoanhDo, pd->tungDo);// doi voi bien -> delete pd; // truy xuat phan cau truc Biên dịch đoạn chương trình Nếu lệnh int a = 1; đổi thành int a = 10; Cho biết giá trị *pa Nếu dòng int *pa = &a; sửa lại thành int *pa; Cho biết kết biên dịch chương trình? Chương trình có báo lỗi thực thi không? Nếu có, cho biết lỗi Nếu trước dòng printf("Gia tri a: %d \n", *pa); ta thêm dòng code *pb = 2; Cho biết kết lệnh xuất printf("Gia tri a: %d \n", *pa); Giải thích có kết xuất 1.5 Con trỏ với mảng (cấp phát mảng động) Cách làm trước không sử dụng cấp phát động với mảng chiều int a[100]; // xin 100 ô nhớ cho mảng tối đa 100 phần tử int n; printf("Nhap so luong phan tu: "); scanf("%d", &n); for (int i = 0; i < n; i++) { printf("Nhap a[%d]: ",i); scanf("%d", &a[i]); } Cách làm có nhiều hạn chế như: cấp phát thừa trường hợp n nhập vào < 100 không cho phép n nhập vào lớn số lượng định trước cài đặt code (100) Để cấp phát mảng động (số lượng phần tử cấp phát với n nhập vào không giới hạn giá trị n), ta làm sau //dung vong lap de nhap cac gia tri a[i] Tài liệu hướng dẫn thực hành môn Cấu trúc liệu giải thuật HCMUS 2010 Trang //khai bao bien tro a va xin cap phat vung nho chua n so interger int* a = new int[n]; int n; printf("Nhap so luong phan tu: "); scanf("%d", &n); for (int i = 0; i < n; i++) { printf("Nhap a[%d]: ",i); scanf("%d", &a[i]); } Sau khai báo int* a = new int[n]; vùng nhớ chứa n số nguyên cấp phát, trỏ a đến phần tử dãy n số Các phần tử mảng truy xuất qua toán tử [] với mảng trước dùng Bài tập (code mẫu: ConTroVoiMang) Nhập mảng chiều số nguyên dùng cấp phát mảng động #include void main() { // MANG CHIEU int n; printf("Nhap so luong phan tu: "); scanf("%d", &n); //khai bao bien tro a va xin cap phat vung nho chua n so interger int* a = new int[n]; //dung vong lap de nhap cac gia tri a[i] for (int i = 0; i < n; i++) { printf("Nhap a[%d]: ",i); scanf("%d", &a[i]); } printf("a[0] = %d\n", a[0]); printf("*a = %d\n", *a); //xuat cac gia tri a[i] for (int i = 0; i < n; i++) { printf("a[%d] = %d\n",i, a[i]); } } Biên dịch đoạn chương trình Nhập vào vài mảng số nguyên, nhận xét kết lệnh xuất sau lần chạy Tài liệu hướng dẫn thực hành môn Cấu trúc liệu giải thuật HCMUS 2010 Trang Giải thích rút kết luận câu Sửa lại đoạn chương trình để nhập vào mảng số nguyên xuất tổng số mảng printf("a[0] = %d\n", a[0]); printf("*a = %d\n", *a); Viết chương trình cho phép nhập vào mảng chiều số nguyên dùng cấp phát động Gợi ý: Mảng chiều mxn số nguyên khai báo sau int** b = new int*[m]; b[i] (kiểu int*) mảng chiều n số nguyên Trang b[i] = new int[n]; Tài liệu hướng dẫn thực hành môn Cấu trúc liệu giải thuật HCMUS 2010 TRUYỀN THAM SỐ: TRUYỀN THAM BIẾN vs TRUYỀN THAM TRỊ Giả sử ta có đoạn chương trình: void BinhPhuong(int a) { a = a * a; } void main() { int a = 2; BinhPhuong(a); printf(“%d”, a); } với hàm BinhPhuong nhận vào tham số kiểu int tính bình phương số ( a = a * a) Ta mong muốn kết xuất Tuy nhiên, thực tế kết xuất lại Giải thích: Khi gọi thực hàm Funtciton(a), giá trị a truyền cho hàm, thân biến a Do đó, dù câu lệnh a = a * a; thực giá trị a hàm BinhPhuong có thay đổi ta truyền giá trị thân biến nên khỏi hàm BinhPhuong(), giá trị biến a thực câu lệnh in Cách truyền tham số a vào hàm BinhPhuong gọi cách truyền tham trị (chỉ truyền giá trị vào hàm, thao tác làm thay đổi giá trị biến bên hàm không ảnh hưởng đến giá trị biến kết thúc hàm) Tuy nhiên trường hợp này, ta muốn thay đổi giá trị biến a hàm BinhPhuong có tác dụng khỏi hàm Ta sửa lại đoạn chương trình sau void BinhPhuong(int& a) { a = a * a; } void main() { int a = 2; BinhPhuong(a); printf(“%d”, a); } kết xuất cách khai báo void BinhPhuong(int& a) // dùng toán tử & #include Tài liệu hướng dẫn thực hành môn Cấu trúc liệu giải thuật HCMUS 2010 Trang Bài tập (code mẫu: ThamBien_ThamTri) cho biết biến a truyền theo kiểu tham biến (truyền trực tiếp biến vào hàm, thay đổi giá trị biến bên hàm ảnh hưởng đến giá trị biến kể kết thúc hàm struct DIEM { int x, y; }; void TruyenThamTri(int a) { a = a * 10; } void TruyenThamBien(int &a) { a = a * 10; } void ThamTriConTro(DIEM* d) { d->x = d->x * 10; d->y = d->y * 10; } void ThamBienConTro(DIEM* &d, DIEM* p) { d->x = d->x * 10; d->y = d->y * 10; d = p; } void main() { // tham tri, tham bien voi bien du lieu int a = 1, b = 10; printf("a = %d\n", a); TruyenThamTri(a); printf("a sau ham TruyenThamTri = %d\n", a); TruyenThamBien(a); printf("a sau ham TruyenThamBien = %d\n", a); // bien tro DIEM* d2 = new DIEM; d2->x = 5; d2->y = 5; printf("Diem d2(%d, %d)\n", d2->x, d2->y); ThamTriConTro(d2); printf("d2 sau goi ham ThamTriConTro: (%d,%d)\n", d2->x, d2->y); printf("\n"); Biên dịch đoạn chương trình Cho biết kết lệnh in Tài liệu hướng dẫn thực hành môn Cấu trúc liệu giải thuật HCMUS 2010 Trang } DIEM* d1 = new DIEM; d1->x = 5; d1-> y = 5; d2->x = 5; d2->y = 5; printf("Diem d2(%d, %d)\n", d2->x, d2->y); ThamBienConTro(d2, d1); printf("d2 sau goi ham ThamBienConTro: (%d,%d)\n", d2->x, d2->y); printf("a sau ham TruyenThamTri = %d\n", a); printf("a sau ham TruyenThamBien = %d\n", a); Cho biết kết lệnh in printf("d2 sau goi ham ThamTriConTro: (%d,%d)\n", d2->x, d2->y); Nhận xét giá trị d2->x d2->y có bị thay đổi không? Nếu giá trị d2->x d2->y có bị thay đổi, giải thích khai báo hàm void ThamTriConTro(DIEM* d) biến d truyền theo kiểu tham trị (không sử dụng &) d2->x, d2->y lại bị thay đổi Gợi ý: d kiểu trỏ Cho biết kết lệnh in printf("d2 sau goi ham ThamBienConTro: (%d,%d)\n", d2->x, d2->y); Nhận xét giá trị d2->x d2->y có bị thay đổi không? Nếu giá trị d2->x d2->y không bị thay đổi, giải thích khai báo hàm void ThamBienConTro(DIEM* &d, DIEM* p) biến d truyền theo kiểu tham biến (sử dụng &) d2->x, d2->y lại không bị thay đổi Gợi ý Thay đổi d1->x = 5; d1-> y = 5; Trang 10 thành giá trị khác quan sát kết lệnh in để rút nhận xét Tài liệu hướng dẫn thực hành môn Cấu trúc liệu giải thuật HCMUS 2010 Áp dụng – Nâng cao Sinh viên tự cài đặt thêm chức cho phép người dùng nhập vào khóa x kiểm tra xem khóa x có nằm AVL hay không Cho dãy A sau: 12 15 17 21 23 25 27 a Tạo AVL từ dãy A Cho biết số phép so sánh cần thực để tìm phần tử 21 AVL vừa tạo b Tạo nhị phân tìm kiếm từ dãy A dùng lại đoạn code tạo thực hành trước) Cho biết số phép so sánh cần thực để tìm phần tử 21 nhị phân tìm kiếm vừa tạo c So sánh kết rút nhận xét? Cài đặt chương trình đọc số nguyên từ tập tin input.txt (không biết trước số lượng số nguyên tập tin) tạo AVL từ liệu đọc Cài đặt cân AVL node lưu thông tin sinh viên Tự tìm hiểu cài đặt chức xóa node khỏi AVL BÀI TẬP THÊM Viết chương trình cho phép tạo, tra cứu sửa chữa từ điển Anh-Việt (sinh viên liên hệ với GVLT để chép file từ điển Anh-Việt) Trang Cài đặt lại tập thêm NPTK cách dùng AVL Tài liệu hướng dẫn thực hành môn Cấu trúc liệu giải thuật HCMUS 2010 CÁC THUẬT TOÁN SẮP XẾP MỤC TIÊU Hoàn tất thực hành này, sinh viên có thể: - Hiểu thuật toán xếp: Selection Sort, Heap Sort, Quick Sort, Merge Sort Áp dụng thuật toán xếp để giải toán xếp đơn giản Áp dụng thuật toán xếp để giải toán xếp danh sách cấu trúc theo khóa So sánh, đánh giá thời gian chạy thuật toán với số lượng phần tử lớn Thời gian thực hành: từ 120 phút đến 400 phút TÓM TẮT Sắp xếp trình xử lý danh sách phần tử (hoặc mẫu tin) để đặt chúng theo thứ tự thỏa mãn tiêu chuẩn dựa nội dung thông tin lưu giữ phần tử Mức độ hiệu giải thuật phụ thuộc vào tính chất cấu trúc liệu cụ thể mà tác động đến Có nhiều giải thuật xếp: Selection sort, Insertion sort, Interchange sort, Bubble sort, Shaker sort, Binary Insertion sort, Shell sort, Heap sort, Quick sort, Merge sort, Radix sort… Selection sort • • Chọn phần tử nhỏ N phần tử ban đầu, đưa phần tử vị trí đầu dãy hành Xem dãy hành N-1 phần tử dãy ban đầu, vị trí thứ 2; lặp lại trình cho dãy hành đến dãy hành phần tử Heap sort Heap dãy phần tử aleft, aleft+1, , aright cho: ≥ a2i ≥ a2i+1, ∀i ∈ [left, right] (ai , a2i), (ai ,a2i+1): cặp phần tử liên đới Heap định nghĩa dùng trường hợp xếp tăng dần, xếp giảm dần phải đổi chiều quan hệ Ví dụ 1: Dãy số bố trí theo quan hệ so sánh tạo thành cấu trúc sau: Phần tử mức i phần tử lớn cặp phần tử tương ứng mức i+1 Trang Ví dụ 2: Loại bỏ khỏi Tài liệu hướng dẫn thực hành môn Cấu trúc liệu giải thuật Tiến hành nhiều lần việc loại bỏ phầần tử gốc tất phần tử ∞, xếp phần tử theo thứ tự ự loại bỏ có dãy xếp Quick sort Phân chia dãy thành đoạn sau: • • • • Đoạn thứ có thứ tự Nếu đoạn có phần ph tử chúng có thứ tự,, ddãy ban đầu nhi phần tử dãy ban đầu đ có thứ tự Ngược lại, đoạnn có nhiều đoạn 1, Để xếp đoạn n 3, ta lần l lượt tiến hành việc phân hoạch ng dãy theo phương pháp phân hoạch ch dãy ban đầu vừa trình bày … Với x phần tử tùy ý dãy thường chọn vị trí dãyy ban đầu đ Merge sort • • Phân hoạch dãy ban đầuu thành dãy liên tiếp mà dãy đãã có thứ th tự Làm giảm số dãy ng cách trộn tr cặp dãy hai dãy phụ thành m dãy dãy ban đầu NỘI DUNG THỰC HÀNH Cơ Sinh viên đọc kỹ phát biểu tậpp th thực theo hướng dẫn: Sử dụng thuật toán Selection Sort, Heap Sort, Quick Sort, Merge Sort để sắpp xếp x dãy số nguyên theo thứ tự tăng dần ph tử dãy nguyên A từ bàn phím Toàn Người dùng nhập chiềuu dài n phần dãy A lưu trữ mả ảng số nguyên Lần lượt sử dụng thuật toán Selection Sort, Heap Sort, Quick Sort, Merge Sort để xếp dãy A Chương trình in kết sắắp xếp theo thuật toán hình Phân tích Phân tích Dùng vòng lặp để tìm phầnn tử t nhỏ dãy hành Đảo phần tử đầu mảng Chương trình mẫu (CacThuatToanSapXep) Tài liệu hướng dẫn thực c hành môn Cấu trúc liệu giải thuật Trang - Selection sort #include void Swap(int &a, int &b) { int c = a; a = b; b = c; } void SelectionSort(int a[],int N ){ //Ghi chú: không sử dụng kí hiệu & hàm này? int min; //chỉ số phần tử nhỏ dãy hành for (int i=0; i