Báo cáo project i giải thuật và lập trình c
Báo cáo Project I Trường đại học Bách Khoa Hà Nội Viện Công nghệ thông tin & truyền thông ***** Báo cáo Project I: Giải thuật lập trình C Sinh viên thực hiện: Giảng viên hướng dẫn: Nguyễn Hồng Quang Phạm Ngọc Hưng Hà Nội, tháng 12/2011 Lời cảm ơn Trước vào bài, em xin chân thành cảm ơn thầy cô môn Kỹ thuật máy tính, viện Công nghệ thông tin truyền thông định hướng em với chủ đề Giải thuật lập trình C, đặc biệt, góp ý, bảo thầy Phạm Ngọc Hưng thầy Nguyễn Hồng Quang giúp đỡ em nhiều trình hoàn thành đề tài Bài viết không tránh khỏi thiếu sót, kính mong thầy cô bạn góp ý để viết hoàn thiện hơn, xin chân thành cảm ơn./ Giải thuật lập trình C Báo cáo Project I Giải thuật lập trình C Báo cáo Project I Bài 1: Giải thuật xếp I Đề bài: Tìm hiểu giải thuật xếp dãy (8 giải thuật): - Sắp xếp kiểu chọn (Selection Sort) - Sắp xếp bọt (Bubble Sort) - Sắp xếp kiểu chèn (Insertion Sort) - Sắp xếp kiểu phân đoạn (Quick sort) - Sắp xếp kiểu vun đống (Heap Sort) - Sắp xếp trộn (Merge Sort) - Sắp xếp phép đếm phân phối (Distribution Counting) - Sắp xếp số (Radix Sort): Theo kiểu hoán vị khóa (Radix Exchange Sort) xếp số trực tiếp (Straight Radix Sort) II Trình bày thuật toán: Sắp xếp chèn (Insertion Sort): Ý tưởng thuật toán sau: + Bắt đầu danh sách có thứ tự rỗng + Lần lượt chèn thêm phần tử xếp vào danh sách có thứ tự đó, trình chèn phải đảm bảo danh sách thứ tự + Kết thúc thuật toán ta thu danh sách thứ tự + Khi sử dụng mảng để lưu trữ ta cần dùng mảng A B, mảng B dùng lưu trữ phần tử ban đầu dãy, mảng A dùng để lưu trữ kết trình xếp Thời gian tính Độ phức tạp thuật toán trường hợp cài đặt mảng O(n2) Code void Chen(int a[], int n) { int i, j, end; for(i=1; i=0)&&(a[j]>end)) { a[j+1]=a[j]; j ; } a[j+1]=end; } } Thực chương trình: Giải thuật lập trình C Báo cáo Project I Sắp xếp lựa chọn (Select Sort): Ý tưởng thuật toán sau: Tìm phần tử nhỏ đưa vào vị trí thứ Phần tử nhỏ thứ hai đưa vào vị trí thứ Phần tử nhỏ thứ ba đưa vào vị trí thứ Giải thuật lập trình C Báo cáo Project I ………… Lặp: (dãy có n phần tử lưu mảng) Bước 1: - Chọn phần tử bé từ dãy nguồn - Đổi chỗ cho phần tử A[1] Bước i: - Chọn phần tử bé từ dãy nguồn lại a[i],a[i+1], ,a[n] - Đổi chỗ cho a[i] Độ phức tạp thuật toán O(n2) Code void Chon(int a[], int n) { int min; for(int i=0;ikeyright; } else { f = 2; p = p->left; } } Giải thuật lập trình C Báo cáo Project I 61 if(p!=NULL) { if(p->right==NULL) { if(f==1) { q->right=p->left; free(p); } else if(f==2) { q->left=p->left; free(p); }else { *root = p->left; free(p); } }else { q = p->right; r = NULL; while(q->left) { r = q; q = q->left; } p->key = q->key; if(r==NULL) p->right = q->right; else r->left = q->right; free(q); } } } Mặc dù việc xóa không phải đòi hỏi phải duyệt từ gốc xuống thực hiện ở một nút tình có thể xảy (duyệt qua nút tới một lá), đó độ phức tạp của thuật toán xóa tương đương với độ cao của (tình tồi nhất) 1.3.5 Tìm kiếm Việc tìm kiếm nhị phân tìm kiếm giống ta thêm một nút mới vào Dựa khóa tìm kiếm key ta xuất phát từ gốc, gọi nút xét X Nếu khóa của X bằng với key, thì kết thúc trả X Nếu X là một nút thì kết trả NULL (cũng chính X) Nếu khóa của X nhỏ key thì ta lặp lại thao tác tìm kiếm với nút phải của X, ngược lại thì tiến hành tìm kiếm với nút trái của X Độ phức tạp của thuật toán bằng với độ phức tạp của thuật toán chèn một nút mới vào Giải thuật lập trình C Báo cáo Project I 62 Cài đặt của thuật toán để lại tập dành cho bạn độc giả 1.3.6 Duyệt Duyệt (tree travel) thao tác duyệt qua (đến thăm) tất nút Có nhiều cách để duyệt cây, chẳng hạn duyệt theo chiều sâu (DFS), duyệt theo chiều rộng (BFS), ở ta phân chia các cách duyệt một BST dựa thứ tự đến thăm nút gốc, nút trái, nút phải của gốc Cụ thể có ba cách duyệt BST: duyệt thứ tự trước, thứ tự giữa, thứ tự sau Để minh họa kết quả của các cách duyệt ta xét ví dụ sau: Hình 5.6 Cây tìm kiếm nhị phân, tham khảo từ wikipedia Duyệt thứ tự trước (pre-order traversal): Thăm gốc (visit root) Duyệt trái theo thứ tự trước Duyệt phải theo thứ tự trước Cụ thể thuật toán cài đặt sau: // duyet theo thu tu truoc void pre_order(BSTree *node) { if(node!=NULL) { visit(node); // ham tham mot nut, don gian la in gia tri khoa pre_order(node->left); pre_order(node->right); } } Kết quả duyệt theo thứ tự trước: 8, 3, 1, 6, 4, 7, 10, 14, 13 Trong cách duyệt theo thứ tự trước, gốc của được thăm đầu tiên Duyệt thứ tự (in-order traversal): Duyệt trái theo thứ tự Giải thuật lập trình C Báo cáo Project I 63 Thăm gốc Duyệt phải theo thứ tự Kết quả duyệt theo thứ tự trước: 1, 3, 4, 6, 7, 8, 10, 13, 14 Một điều dễ nhận thấy là các khóa của duyệt theo thứ tự xuất hiện theo thứ tự tăng dần Duyệt thứ tự sau (post-order traversal): Duyệt trái theo thứ tự sau Duyệt phải theo thứ tự sau Thăm gốc Kết quả duyệt theo thứ tự sau: 1, 4, 7, 6, 3, 13, 14, 10, Trong cách duyệt này, gốc được thăm sau cùng Nhận xét: - Khi duyệt trung tự (InOrder) BST ta dãy có thứ tự tăng Cài đặt bằng C của hai cách duyệt sau dành cho bạn độc tập 1.3.7 Cài đặt BST Cây TKNP, trước hết, nhị phân Do đó, ta có thể áp dụng cách cài đặt trình bày phần nhị phân Sẽ không có khác biệt việc cài đặt cấu trúc liệu cho TKNP so với nhị phân, tất nhiên, có khác biệt giải thuật thao tác TKNP tìm kiếm, thêm hoặc xoá nút TKNP để đảm bảo tính chất cuả TKNP Một cách cài đặt TKNP thường gặp cài đặt bằng trỏ Mỗi nút của mẩu tin (record) có ba trường: trường chứa khoá, hai trường hai trỏ trỏ đến hai nút (nếu nút vắng mặt ta gán trỏ bằng NIL) Khai báo sau typedef KeyType; typedef struct Node { KeyType Key; Node* Left,Right; }typedef Node* Tree; Khởi tạo TKNP rỗng Ta cho trỏ quản lý nút gốc (Root) của bằng NULL void MakeNullTree(Tree *Root) { (*Root)=NULL; } Tìm kiếm nút có khóa cho trước TKNP Ðể tìm kiếm nút có khoá x TKNP, ta tiến hành từ nút gốc bằng cách so sánh khoá của nút gốc với khoá x - Nếu nút gốc bằng NULL thì không có khoá x - Nếu x bằng khoá của nút gốc thì giải thuật dừng ta tìm nút chứa khoá x - Nếu x lớn khoá của nút gốc thì ta tiến hành (một cách đệ qui) việc tìm khoá x bên phải - Nếu x nhỏ khoá của nút gốc thì ta tiến hành (một cách đệ qui) việc tìm khoá x bên trái Giải thuật lập trình C Báo cáo Project I 64 Ví dụ: tìm nút có khoá 30 trong hình III.15 - So sánh 30 với khoá nút gốc 20, vì 30 > 20 ta tìm tiếp bên phải, tức có nút gốc có khoá 35 - So sánh 30 với khoá của nút gốc 35, vì 30 < 35 ta tìm tiếp bên trái, tức có nút gốc có khoá 22 - So sánh 30 với khoá của nút gốc 22, vì 30 > 22 ta tìm tiếp bên phải, tức có nút gốc có khoá 30 - So sánh 30 với khoá nút gốc 30, 30 = 30 đến giải thuật dừng ta tìm nút chứa khoá cần tìm - Hàm dưới trả kết trỏ trỏ tới nút chứa khoá x hoặc NULL nếu không tìm thấy khoá x TKNP Tree Search(KeyType x,Tree Root) { if (Root == NULL) return NULL; //không tìm thấy khoá x else if (Root->Key == x) /* tìm thấy khoá x */ return Root; else if (Root->Key < x) //tìm tiếp bên phải return Search(x,Root->right); else //tìm tiếp bên trái return Search(x,Root->left); } Thêm nút có khóa cho trước vào TKNP Theo dịnh nghĩa tìm kiếm nhị phân ta thấy tìm kiếm nhị phân không có hai nút có khoá Do đó, nếu ta muốn thêm nút có khoá x vào TKNP trước hết ta phải tìm kiếm để xác dịnh có nút chứa khoá x chưa Nếu có thì giải thuật kết thúc (không làm gì cả!) Ngược lại, thêm nút mới chứa khoá x Việc thêm khoá vào TKNP việc tìm kiếm thêm nút, tất nhiên, phải đảm bảo cấu trúc TKNP không bị phá vỡ Giải thuật cụ thể sau: Ta tiến hành từ nút gốc bằng cách so sánh khóa cuả nút gốc với khoá x - Nếu nút gốc bằng NULL thì khoá x chưa có cây, đó ta thêm nút mới chứa khoá x - Nếu x bằng khoá của nút gốc thì giải thuật dừng, trường hợp ta không thêm nút - Nếu x lớn khoá của nút gốc thì ta tiến hành (một cách đệ qui) giải thuật bên phải - Nếu x nhỏ khoá của nút gốc thì ta tiến hành (một cách đệ qui) giải thuật bên trái Thủ tục sau dây tiến hành việc thêm khoá vào TKNP void InsertNode(KeyType x,Tree *Root ) { if (*Root == NULL) { /* thêm nút mới chứa khoá x */ (*Root)=(Node*)malloc(sizeof(Node)); (*Root)->Key = x; (*Root)->left = NULL; Giải thuật lập trình C Báo cáo Project I 65 (*Root)->right = NULL; } else if (x < (*Root)->Key) InsertNode(x,Root->left); else if (x>(*Root)->Key) InsertNode(x,Root->right); } Xóa nút có khóa cho trước khỏi TKNP Giả sử ta muốn xoá nút có khoá x, trước hết ta phải tìm kiếm nút chứa khoá x Việc xoá nút vậy, tất nhiên, ta phải bảo đảm cấu trúc TKNP không bị phá vỡ Ta có trường hợp hình III.17: Hình III.17 Ví dụ giải thuật xóa nút - Nếu không tìm thấy nút chứa khoá x thì giải thuật kết thúc - Nếu tìm gặp nút N có chứa khoá x, ta có ba trường hợp sau (xem hình III.17) - Nếu N ta thay nó NULL - N có nút ta thay nó nút của nó - N có hai nút ta thay nó nút lớn trái của nó (nút cực phải của trái) hoặc nút bé phải của nó (nút cực trái của phải) Trong giải thuật sau, ta thay x khoá của nút cực trái của bên phải rồi ta xoá nút cực trái Việc xoá nút cực trái của bên phải roi vào hai trường hợp Giải thuật xoá nút có khoá nhỏ Hàm dưới dây trả khoá của nút cực trái, dồng thời xoá nút KeyType DeleteMin (Tree *Root ) { KeyType k; if ((*Root)->left == NULL) { k=(*Root)->key; (*Root) = (*Root)->right; return k; } else return DeleteMin(Root->left); } Thủ tục xóa nút có khoá cho trước TKNP void DeleteNode(key X, Tree *Root) { if ((*Root)!=NULL) if (x < (*Root)->Key) DeleteNode(x,Root->left) else if (x > (*Root)->Key) DeleteNode(x,Root->right) else if ((*Root)->left==NULL)&&((*Root)->right==NULL) (*Root)=NULL; else if ((*Root)->left == NULL) (*Root) = (*Root)->right ; Giải thuật lập trình C Báo cáo Project I 66 else if ((*Root)->right==NULL) (*Root) = (*Root)->left; else (*Root)->Key = DeleteMin(Root->right); } Giải thuật lập trình C Báo cáo Project I 67 Thay cho lời kết Trước kết thúc báo cáo, lần nữa, em xin chân thành cảm ơn thầy cô môn Kỹ thuật máy tính, đặc biệt nhiệt tình thầy Nguyễn Hồng Quang thầy Phạm Ngọc Hưng giúp đỡ em nhiều trình hoàn thành chủ đề Đây chủ đề không song nhờ nó, em nắm vững cấu trúc liệu giải thuật thường gặp phần kỹ lập trình C em cải thiện nhiều Đây hành trang quan trọng bước đường học tập tới em, giúp em dễ dàng tiếp thu kiến thức công cụ ngôn ngữ lập trình khác qua so sánh đối chiếu với ngôn ngữ C Và em tin rằng, ngày không xa tới đây, em vững bước đường đời với kiến thức quý báu thầy cô dày công vun đắp, hy vọng em nhận ủng hộ nhiệt tình từ phía thầy cô, chúc thầy cô sức khỏe thành đạt./ Giải thuật lập trình C [...]... cac phan tu trong mang mang a[] for(int i= 0 ;ipNext; } // Hoán vị n i dung hai phần tử Hoanvi(min->Info, p->Info); p = p->pNext; } } Phương án 2: thay đ i m i liên kết Thay vì hoán đ i giá trị, ta sẽ tìm c ch thay đ i trình tự m c n i c a c c phần tử sao cho... đó: Gi i thuật và lập trình C Báo c o Project I 20 - Vx = {tập hợp c thứ tự c c phần tử kiểu T đư c m c n i v i nhau theo trình tự tuyến tính}; - Ox = {c c thao t c trên danh sách liên kết như: tạo danh sách; tìm một phần tử trong danh sách; chèn một phần tử vào danh sách; hủy một phần tử kh i danh sách; sắp xếp danh sách…} Ví dụ: Hồ sơ c c h c sinh c a một trường đư c tổ ch c thành danh sách gồm nhiều .. .Báo c o Project I Gi i thuật lập trình C Báo c o Project I B i 1: Gi i thuật xếp I Đề b i: Tìm hiểu gi i thuật xếp dãy (8 gi i thuật) : - Sắp xếp kiểu chọn (Selection Sort) - Sắp... tin sinh viên chương trình in menu lựa chọn Gi i thuật lập trình C Báo c o Project I 41 Danh sách sinh viên theo tên xếp lo i Lựa chọn tìm số i n tho i sinh viên theo tên lớp Gi i thuật lập trình. .. trình C Báo c o Project I 42 Sau th c xếp danh sách sinh viên theo i m trung bình giảm dần Màn hình c nh báo chọn thêm sinh viên vào danh sách xếp Gi i thuật lập trình C Báo c o Project I 43 Thực