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

Cấu trúc dữ liệu và giải thuật cao đẳng công nghệ thông tin

55 395 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

Cấu trúc

Nội dung

Tài liệu cung cấp nội dung và kiến thức cơ bản về cấu trúc dữ liệu giải thuật. Cách tính độ phức tạp giải thuật, các giải thuật sắp xếp cư bản, các giải thuật sắp xếp nâng cao, tìm kiếm tuần tự và tìm kiếm nhị phân, cấu trúc dữ liệu danh sách đặc biệt như stack, queue, ...

Bài giảng Cấu trúc liệu giải thuật CHƯƠNG 1: CÁC KHÁI NIỆM CƠ SỞ 1.1 Khái niệm thuật toán 1.1.1 Định nghĩa thuật toán Có nhiều định nghĩa cách phát biểu khác định nghĩa thuật toán Theo sách giáo khoa tiếng viết thuật toán “Introduction to Algorithms” (Second Edition Thomas H Cormen, Charles E Leiserson, Ronald L Rivest Clifford Stein) thuật toán định nghĩa sau: “một thuật toán thủ tục tính toán xác định (well-defined) nhận giá trị tập giá trị gọi input sinh ra vài giá trị tập giá trị gọi output” Nói cách khác thuật toán giống cách thức, qui trình để hoàn thành công việc cụ thể xác định (well-defined) Ví dụ đoạn mã chương trình tính phần tử dãy số Fibonaci cài đặt thuật toán cụ thể Thậm chí hàm đơn giản để cộng hai số thuật toán hoàn chỉnh, thuật toán đơn giản 1.1.2 Đặc trưng thuật toán Tính đắn: Thuật toán cần phải đảm bảo cho kết sau thực liệu đầu vào Đây nói đặc trưng quan trọng thuật toán Tính dừng: Thuật toán cần phải đảm bảo dừng sau số hữu hạn bước Tính xác định: Các bước thuật toán phải phát biểu rõ ràng, cụ thể, tránh gây nhập nhằng nhầm lẫn người đọc hiểu, cài đặt thuật toán Tính hiệu quả: thuật toán xem hiệu có khả giải hiệu toán đặt thời gian điều kiện cho phép thực tế đáp ứng yêu cầu người dùng Tính phổ quát: thuật toán gọi có tính phố quát (phổ biến) giải lớp toán tương tự Ngoài thuật toán theo định nghĩa nhận giá trị đầu vào gọi chung giá trị liệu Input Kết thuật toán (thường kết cụ thể tùy theo toán thuật toán cụ thể) gọi Output 1.2 Biểu diễn thuật toán Thường có bốn cách biểu diễn thuật toán, cách thứ mô tả bước thực thuật toán, cách thứ hai sử dụng sơ đồ giải thuật, cách thứ ba dùng mã giả, cách thứ dùng ngôn ngữ lập trình 1.2.1 Mô tả bước thực Để biểu diễn thuật toán người ta mô tả xác bước thực thuật toán, ngôn ngữ dùng để mô tả thuật toán ngôn ngữ tự nhiên ngôn ngữ lai ghép ngôn ngữ tự nhiên với ngôn ngữ lập trình gọi đoạn giả mã lệnh Ví dụ 1.1: mô tả thuật toán tìm ước số chung lớn hai số nguyên Input: Hai số nguyên a, b Output: Ước số chung lớn a, b Biên soạn Đỗ Văn Tuấn Trang Bài giảng Cấu trúc liệu giải thuật Thuật toán: Bước 1: Nếu a=b USCLN(a, b)=a Bước 2: Nếu a > b tìm USCLN a-b b, quay lại bước 1; Bước 3: Nếu a < b tìm USCLN a b-a, quay lại bước 1; 1.2.2 Sử dụng sơ đồ (lưu đồ) giải thuật (flowchart) Sử dụng ký hiệu hình khối để tạo thành mô tả mang tính hình thức (cách rõ ràng so với việc mô tả bước thực thuật toán) Đôi việc mô tả giải thuật hình vẽ rõ ràng dễ hiểu Toàn hình vẽ dùng để mô tả thuật toán gọi lưu đồ hay sơ đồ khối Cách biểu diễn giúp có nhìn tổng quát toàn trình xử lí vấn đề/bài toán theo thuật toán Để xây dựng lưu đồ, quy ước số kí hiệu hình vẽ sau:  Bắt đầu kết thúc thuật toán Begin End  Thực công việc A A  Gọi chương trình A A  Dữ liệu vào  Phép thử điều kiện B đú ng B sa i Hình 1.1: Các quy tắc ký hiệu vẽ lưu đồ thuật toán Biên soạn Đỗ Văn Tuấn Trang Bài giảng Cấu trúc liệu giải thuật Ví dụ 1.2: Dùng lưu đồ để biểu diễn giải thuật tính tổng n số nguyên Begin Đọc vào n S=0 i=0 S=S+i i=i+1 sa i i>n đún In S g End Hình 1.2: Lưu đồ thuật toán tính tổng n số nguyên 1.2.3 Mô tả thuật toán dùng mã giả Với thuật toán phức tạp, việc vẽ theo dõi sơ đồ khối thường không thuận tiện Trong số trường hợp người ta dùng ngôn ngưc giả mã(giả ngôn ngữ lập trình) để mô tả thuật toán Khi thể thuật toán mã giả, ta vay mượn cú pháp ngôn ngữ lập trình để thể thuật toán Tất nhiên, ngôn ngữ lập trình có thao tác xử lý, rẽ nhánh lặp Dùng mã giả vừa tận dụng khái niệm ngôn ngữ lập trình, vừa giúp người cài đặt dễ dàng nắm bắt nội dung thuật toán Tất nhiên mã giả ta dùng phần ngôn ngữ tự nhiên Các cấu trúc dùng ngôn ngữ giả mã bất kỹ ngôn ngữ Khác cấu trúc tuần tự, rẽ nhánh, cấu trúc lặp a Cấu trúc tuần: Liệt kê công việc, thao tác thứ tự Để hỗ trợ cho việc theo dõi thuận tiện thêm số thứ tự b Cấu trúc rẽ nhánh: + if(đk) ; + if(đk) ; Else ; Biên soạn Đỗ Văn Tuấn Trang Bài giảng Cấu trúc liệu giải thuật + switch(bt) { case ds1:; break; case ds2:; break; case ds3:; break; … case dsn:; break; } + switch(bt) { case ds1:; break; case ds2:; break; case ds3:; break; … case dsn:; break; default ; } c Cấu trúc lặp: + for(bt1; bt2; bt3) Trong đó: bt1: biểu thức khởi tạo biến điều khiển bt2: kiểm tra điều kiện biến điều khiển bt3: bước nhảy biến điều khiển + while ; + { ; }while; Ví dụ 1.3: Đoạn mã giả thuật toán giải phương trình bậc hai if delta = then xuất kết : phương trình có nghiệm kép -b/(2*a) else if Delta > then begin x1=(-b-sqrt(delta))/(2*a) x2=(-b+sqrt(delta))/(2*a) xuất kết : phương trình có hai nghiệm x1 x2 end else {trường hợp delta < } xuất kết : phương trình vô nghiệm 1.2.4 Biểu diễn thuật toán ngôn ngữ lập trình Theo cách sử dụng ngôn ngữ lập trình để biểu diễn thuật Biên soạn Đỗ Văn Tuấn Trang Bài giảng Cấu trúc liệu giải thuật toán Ví dụ 1.4: Thuật toán tính n! giai thừa int gt(int n) { if(n==0 || n==1) return 1; else return n*gt(n-1); } 1.3 Tính đắn hiệu thuật toán 1.3.1 Tính đắn giải thuật Khi thuật toán làm ra, ta cần phải chứng minh rằng, thuật toán đựoc thực cho ta kết với liệu vào hợp lệ Điều gọi chứng minh tính đắn thuật toán Việc chứng minh thuật toán đắn công việc không dễ dàng Trong nhiều trường hợp, đòi hỏi ta phải có trình độ khả tư toán học tốt Ví dụ 1.5: Tìm ước số chung lớn thuật toán Euclid Input : m, n nguyên dương Output : g, ước chung lớn m n Phương pháp : Bước : Tìm r, phần dư phép chia m cho n Bước : Nếu r = O, g  n (gán giá trị n cho g) dừng lại Trong trường hợp ngược lại (r ≠ 0), m  n, n  r quay lại bước Sau ta rằng, thực thuật toán Euclid, g ước chung lớn hai số nguyên dương m n Thật thực bước 1, ta có m=qn+r, q số nguyên Nếu r = n ước m hiển nhiên n (do g) ước chung lớn m n Nếu r ≠ 0, ước chung m n ước chung n r (vì r = m - qn) Ngược lại ước chung n r ước chung m n (vì m = qn + r) Do ước chung lớn n r ước chung lớn m n Vì vậy, thực lặp lại bước với thay đổi giá trị m n giá trị n r (các phép gán m , nr bước 2) r = 0, ta nhận giá trị g ước chung lớn giá trị m n ban đầu Phân tích thuật toán: Giả sử toán có số thuật toán giải Một câu hỏi xuất là, cần chọn thuật toán số thuật toán để áp dụng Việc phân tích thuật toán, đánh giá độ phức tạp nội dung phần sau 1.3.2 Tính hiệu giải thuật Khi giải vấn đề, cần chọn số thuật toán, thuật toán mà cho "tốt" Vậy ta cần lựa chọn thuật toán dựa sở nào? Thông thường ta dựa hai tiêu chuẩn sau đây: Thuật toán đơn giản, dễ hiểu, dễ cài đặt (dễ viết chương trình).(1) Biên soạn Đỗ Văn Tuấn Trang Bài giảng Cấu trúc liệu giải thuật Thuật toán sử dụng tiết kiệm nguồn tài nguyên máy tính, đặc biệt, chạy nhanh được.(2) Khi ta viết chương trình để sử dụng số lần giá thời gian viết chương trình vượt xa giá chạy chương trình tiêu chuẩn (1) quan trọng Nhưng có trường hợp ta cần viết chương trình (hoặc thủ tục, hàm) để sử dụng nhiều lần, cho nhiều người sử dụng, giá thời gian chạy chương trình vượt xa giá viết Chẳng hạn, thủ tục xếp, tìm kiếm sử dụng nhiều lần, nhiều người toán khác Trong trường hợp ta cần dựa tiêu chuẩn (2) Ta cài đặt thuật toán phức tạp, miễn chương trình nhận chạy nhanh chương trình khác Tiêu chuẩn (2) xem tính hiệu thuật toán Tính hiệu thuật toán bao gồm hai nhân tố Dung lượng không gian nhớ cần thiết để lưu giữ liệu vào, kết tính toán trung gian kết thuật toán.(1) Thời gian cần thiết để thực thuật toán (ta gọi thời gian chạy).(2) Chúng ta quan tâm đến thời gian thực thuật toán Vì vậy, nói đến đánh giá độ phức tạp thuật toán, có nghĩa ta nói đến đánh giá thời gian thực Một thuật toán có hiệu xem thuật toán có thời gian chạy thuật toán khác * Tại lại cần thuật toán có hiệu Kỹ thuật máy tính tiến nhanh, ngày máy tính lớn đạt tốc độ tính toán hàng trăm triệu phép tính giây Vậy có bõ công phải tiêu tốn thời gian để thiết kế thuật toán có hiệu không ? (ví dụ tính n! dựa vào đệ quy phương pháp Gauss) 1.4 Độ phức tạp thuật toán 1.4.1 Các tiêu chí đánh giá thuật toán Thông thường để đánh giá mức độ tốt, xấu so sánh thuật toán loại, dựa hai tiêu chuẩn: Thuật toán đơn giản, dễ hiểu, dễ cài đặt Dựa vào thời gian thực tài nguyên mà thuật toán sử dụng để thực liệu Trên thực tế thuật toán hiệu không dễ hiểu, cài đặt hiệu không dễ dàng thực hiểu cách nhanh chóng Và điều nghịch lý thuật toán hiệu khó hiểu, cài đặt phức tạp lại hiệu (không phải lúc đúng) Vì để đánh giá so sánh thuật toán người ta thường dựa độ phức tạp thời gian thực thuật toán, gọi độ phức tạp thuật toán (algorithm complexity) Về chất độ phức tạp thuật toán hàm ước lượng (có thể không xác) số phép tính mà thuật toán cần thực (từ dễ dàng suy thời gian thực thuật toán) liệu input có kích thước N N số phần tử mảng trường hợp toán xếp tìm kiếm, độ lớn số toán kiểm tra số nguyên tố chẳng Biên soạn Đỗ Văn Tuấn Trang Bài giảng Cấu trúc liệu giải thuật hạn 1.4.2 Đánh giá thời gian thực thuật toán Để minh họa việc đánh giá độ phức tạp thuật toán ta xem xét ví dụ thuật toán xếp chọn (selection sort) xếp đổi chỗ trực tiếp (exchange sort) sau: Cài đặt thuật toán xếp chọn: for(i=0;idata); q->head = q->tail = -1; q->cap = 0; } void push(queue *q, int d) { q->tail = (q->tail + 1) % MAX; q->data[q->tail] = d; if(q->cap==0) // neu hang doi rong thi sau push // ca head va tail deu chi vao phan tu q->head = q->tail; q->cap++; } void pop(queue *q) { q->head = (q->head + 1)%MAX; q->cap ; if(q->cap==0) q->head = q->tail = -1; } int front(const queue *q) { return q->data[q->head]; } int back(const queue *q) { return q->data[q->tail]; } int size(const queue *q) { return q->cap; } int empty(const queue *q) { return (q->cap==0)?(1):(0); } int full(const queue *q) { return (q->cap==MAX -1)?(1):(0); } 4.4.4 Ví dụ hoạt động hàng đợi với cài đặt mảng vòng tròn Ta giả sử mảng lưu phần tử hàng đợi E[0 3], biến head, tail lưu vị trí phần tử đầu cuối hàng đợi, cột Kết cột kết thực thao tác hàng đợi, dấu ? tương ứng với giá trị Thao tác head tail Queue Kết quả(trên hình) Khởi tạo -1 -1 push(55) 0 55 push(-7) 55 -7 push(16) 55 -7 16 pop() -7 16 push(-8) -7 16 -8 55 pop() 16 -8 55, -7 pop() 3 -8 55, -7, 16 push(11) -8 55 11 55, -7, 16 4.4.5 Ứng dụng hàng đợi Trong hệ điều hành: o Hàng đợi công việc tiến trình đợi để thực o Hàng đợi tiến trình chờ tín hiệu từ thiết bị IO o Các file gửi tới máy in Mô hệ thống hàng đợi thời thực tế o Các khách hàng cửa hàng tạp hóa, hệ thống ngân hàng o Các đơn đặt hàng công ty o Phòng cấp cứu o Các gọi điện thoại đặt hàng vé máy bay, đặt hàng khách hàng … Các ứng dụng khác: Thứ tự topo: với tập kiện, cặp (a, b) kiện a có độ ưu tiên cao so với kiện b (bài toán lập lịch), duyệt đồ thị theo chiều rộng (Breadth First Search) Bài tập: Hãy viết chương trình chuyển đổi biểu thức dạng infix (dạng thông thường) đơn giản (không chứa dấu ()) thành biểu thức dạng tiền tố (prefix) Ví dụ xem tập để sinh viên tự làm CHƯƠNG 5: THAO TÁC VỚI CẤU TRÚC CÂY 5.1 Xây dựng nhị phân tìm kiếm 5.1.1 Đồ thị (Graph) Trước xem xét khái niệm (tree) nhắc lại khái niệm đồ thị (graph) học học phần Toán rời rạc: Đồ thị G bao gồm hai hành phần chính: tập đỉnh V (Vertices) tập cung E(hay cạnh Edges), thường viết dạng G= Trong tập đỉnh V tập đối tượng loại, độc lập, chẳng hạn điểm mặt phẳng tọa độ, tập thành phố, tập trạng thái trò chơi, đối tượng thực người, … tất đỉnh đồ thị Tập cung E tập mối quan hệ hai đỉnh đồ thị, đỉnh điểm quan hệ khoảng cách, tập đỉnh thành phố quan hệ đường (có tồn đường trực tiếp thành phố hay không), đỉnh trạng thái trò chơi cạnh cách biến đổi (transform) để từ trạng thái sang trạng thái khác, trình chơi biến đổi từ trạng thái ban đầu tới trạng thái đích (có nghĩa tìm đường đi) Hình 5.1 Đồ thị có đỉnh cạnh, tham khảo từ wikipedia Có nhiều vấn đề liên quan tới đồ thị, phần chì nhắc lại số khái niệm liên quan Một đồ thị gọi đơn đồ thị (simple graph) đường hai đỉnh đồ thị bị lặp lại, ngược lại có đường bị lặp lại tồn khuyên (self-loop), dạng cung từ đỉnh đến đỉnh đó, đồ thị gọi đa đồ thị (multigraph) Giữa hai đỉnh u, v đồ thị có đường trực tiếp u, v gọi liền kề với nhau, cạnh (u, v) gọi liên thuộc với hai đỉnh u, v Đồ gọi đồ thị có hướng (directed graph) đường hai đỉnh đồ thị phân biệt hướng với nhau, quan hệ đỉnh gọi xác cung, ngược lại đồ không phân biệt hướng đỉnh cạnh nối hai đỉnh đồ thị gọi đồ thị vô hướng (undirected graph), ta nói tập E tập cạnh đồ thị Các cung hay cạnh đồ thj gán giá trị gọi trọng số (weight), đồ thị đồ thị có trọng số trọng số Ví dụ đồ thị mà đỉnh thành phố ta gán trọng số cung độ dài đường nối thành phố chi phí đường … Một đường (path) đồ thị dãy đỉnh v1, v2, …, vk, đỉnh vi, vi+1 liền kề với Đường có đỉnh đầu trùng với đỉnh cuối gọi chu trình (cycle) Giữa hai đỉnh đồ thị có đường trực tiếp chúng liền kề với nhau, có đường chúng (gián tiếp) hai đỉnh gọi liên thông (connected) với Một đồ thị gọi liên thông hai đỉnh liên thông với Nếu đồ thị không liên thông chia thành thành phần liên thông nhỏ 5.1.2 Cây (tree) Có nhiều cách định nghĩa khác định nghĩa khái niệm theo lý thuyết đồ thị (graph theory) Cây đồ thị vô hướng, trọng số, liên thông chu trình Ví dụ hình vẽ sau cây: Hình 5.2 Cây, tham khảo từ wikipedia Cấu trúc cấu trúc sử dụng rộng rãi sống hàng ngày máy tính, chẳng hạn cấu trúc tổ chức công ty phân cấp, cấu trúc web site tương tự: Hình 5.3 Cấu trúc web site wikipedia, tham khảo từ wikipedia Cấu trúc tổ chức thư mục hệ điều hành … Trong có nút đặc biệt gọi gốc (root), đỉnh gọi nút (nodes) Từ gốc xuống tất đỉnh liền kề với nó, đỉnh gọi gốc, đến lượt gốc lại có nút (child nodes) khác, quan hệ hai nút liền kề quan hệ cha con, nút cha (parent), nút (child), nút cha cha nút gọi tổ tiên (ancestor) nút Các nút phân biệt làm nhiều loại: nút có nút gọi nút (internal nodes hay inner nodes), nút nút gọi nút (leaf nodes) Các nút nút để thuận tiện trình cài đặt người ta coi nút có hai nút giả, rỗng (NULL) đóng vai trò lính canh, gọi nút (external nodes) Các nút phân chia thành tầng (level), nút gốc thuộc tầng (level 0), sau tầng tăng lên đơn vị so với tầng phía tầng cuối Độ cao (height) tính số tầng cây, độ cao định độ phức tạp (số thao tác) thực thao tác Mỗi nút tổng quát có nhiều nút con, nhiên nghiên cứu ngành khoa học máy tính cho thấy cấu trúc quan trọng cần nghiên cứu nhị phân (binary tree), là nút có nhiều hai nút Một tổng quát phân chia thành nhị phân Các nút nút nhị phân gọi nút trái (left child) nút phải (right child) Trong chương nghiên cứu số loại nhị phân ứng dụng rộng rãi nhất, tìm kiếm nhị phân BST (Binary Search Tree), biểu thức (expression tree hay syntax tree) cân (balanced tree) AVL 5.1.2.1 Cây nhị phân tìm kiếm a Định nghĩa Cây tìm kiếm nhị phân (TKNP) nhị phân mà khoá nút lớn hon khoá tất nút thuộc bên trái nhỏ hon khoá tất nút thuộc bên phải Minh hoạ TKNP có khoá số nguyên (với quan hệ thứ tự tập số nguyên) Qui uớc: Cung nhu tất cấu trúc khác, ta coi rỗng TKNP Nhận xét: Trên TKNP hai nút khoá Cây TKNP TKNP Khi duyệt trung tự (InOrder) TKNP ta duợc dãy có thứ tự tang Chẳng hạn duyệt trung tự ta có dãy: 5, 10, 15, 17, 20, 22, 30, 35, 42 b Cài dặt tìm kiếm nhị phân Có thể áp dụng cách cài dặt trình bày phần nhị phân để cài đặt TKNP Nhưng có nhiều khác biệt giải thuật thao tác TKNP tìm kiếm, thêm xoá nút TKNP để đảm bảo tính chất cuả TKNP Thông thuờng sử dụng trỏ để cài đặt TKNP typedef struct tree { int key; struct tree *left,*right; }BSTree; Để khởi tạo rỗng ta khai báo gốc gán cho gốc NULL: BSTree **root; *root = NULL; c Tìm kiếm nút có khoá cho truớc TKNP Ðể tìm kiếm nút có khoá x TKNP, ta tiến hành từ nút gốc cách so sánh khoá nút gốc với khoá x Nếu nút gốc NIL khoá x Nếu x khoá nút gốc giải thuật dừng ta dã tìm duợc nút chứa khoá x Nếu x lớn hon khoá nút gốc ta tiến hành (một cách dệ qui) việc tìm khoá x bên phải Nếu x nhỏ hon khoá nút gốc ta tiến hành (một cách dệ qui) việc tìm khoá x bên trái Ví dụ: tìm nút có khoá 30 TKNP So sánh 30 với khoá nút gốc 20, 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á nút gốc 35, 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 khóa nút gốc 22, 30 > 22 ta tìm kiếm 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 dến dây giải thuật dừng ta tìm duợc nút chứa khoá cần tìm Hàm duới dây trả kết trỏ trỏ tới nút chứa khoá x Null không tìm thấy khoá x TKNP Node* searchKey(Tree T, item x) // tim nut co key x { if (T!=NULL) { if (T->key == x) { Node *P = T; return P;} if (T->key > x) return searchKey(T->Left, x); if (T->key < x) return searchKey(T->Right, x); } return NULL; } d Thêm nút có khoá cho truớc vào tìm kiếm nhị phân Trong trình chèn giá trị vào TKNP, dã có x không thực chèn truờng hợp chua có ta chèn x vào cho thoả tính chất TKNP Giải thuật dệ qui cụ thể nhu sau: Ta tiến hành từ nút gốc cách so sánh khoá cuả nút gốc với khoá x Nếu nút gốc Null khoá x chua có cây, dó ta thêm nút chứa khoá x Nếu x khoá nút gốc giải thuật dừng, truờng hợp ta không thêm nút Nếu x lớn hon khoá nút gốc ta tiến hành (một cách dệ qui) giải thuật bên phải Nếu x nhỏ hon khoá nút gốc ta tiến hành (một cách dệ qui) giải thuật bên trái Ví dụ: thêm khoá 19 vào TKNP So sánh 19 với khoá nút gốc 20, 19 < 20 ta xét tiếp dến bên trái, tức có nút gốc có khoá là10 So sánh 19 với khoá nút gốc 10, 19 > 10 ta xét tiếp dến bên phải, tức có nút gốc có khoá 17 So sánh 19 với khoá nút gốc 17, 19 > 17 ta xét tiếp dến bên phải Nút bên phải Null, chứng tỏ khoá 19 chua có cây, ta thêm nút chứa khoá 19 nút bên phải nút có khoá 17 Hàm sau dây tiến hành việc thêm khoá vào TKNP // them mot nut moi vao cay, gia tri khoa cua nut moi luu bien toan cuc newkey void insert(BSTree **root) { if(*root==NULL) { *root=calloc(1,sizeof(BSTree)); (*root)->key = newkey; (*root)->left=NULL; (*root)->right=NULL; } else { if((*root)->key>newkey) insert(&((*root)->left)); else if((*root)->keyright)); else printf("\nError: Duplicate key"); } } e Xoá nút có khoá cho truớc tìm kiếm nhị phân Giả sử ta muốn xoá nút có khoá x, truớc hết ta phải tìm kiếm nút chứa khoá x Việc xoá nút nhu vậy, tất nhiên, ta phải bảo dảm cấu trúc TKNP không bị phá vỡ Ta có truờng hợp sau: Khi xóa bỏ nút X khỏi (dựa giá trị khóa), chia số trường hợp sau: - X nút lá: việc xóa nút không làm ảnh hưởng tới nút khác, ta việc xóa bỏ nút khỏi - X có nút (trái phải): ta đưa nút X lên thay cho nút X xóa bỏ X - Còn X nút có hai con, ta có hai lựa chọn, tìm nút hậu duệ nhỏ bên nhánh phải X (gọi Y), thay khóa Y lên X xóa bỏ Y Cách thứ hai tìm nút hậu duệ lớn bên nhánh trái X (gọi Z), thay khóa Z lên X xóa bỏ Z Các thao tác với Y Z lặp lại tương tự X Do nút thực bị xóa trường hợp thứ ba rơi vào trường hợp (là nút nút có con), đồng thời nút bị xóa có khóa nhỏ hai X nên cài đặt ta nên tránh sử dụng phương pháp, dẫn tới tình tính cân Việc cài đặt thuật toán xóa nút tìm kiếm nhị phân không đơn giản việc mô tả thuật toán xóa Trước hết ta xuất phát từ gốc để tìm nút chứa khóa cần xóa Trong trình điều quan trọng ta xác định rõ nút cần xóa (biến p đoạn mã chương trình bên dưới) nút lá, nút có con, nút có đầy đủ hai Dù trường hợp cần xác định nút cha nút p (nút q), p trái hay phải q Để xác định trường hợp ta sử dụng biến cờ f, f tương ứng với việc nút cần xóa gốc cây, f tương ứng với p phải q, f tương ứng với p trái q Giải thuật xoá nút có khoá key cho trước Cài đặt C thao tác xóa nút khỏi BST: // xoa bo mot khoa khoi cay void del(BSTree ** root, int key) { BSTree *p, *q, *r; int f=0; p = *root; q = NULL; while(p!=NULL&&p->key!=key) { q = p; if(p->keyright; } else { f = 2; p = p->left; } } 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 đòi hỏi phải duyệt từ gốc xuống thực nút tình xảy (duyệt qua nút tới nút lá), độ phức tạp thuật toán xóa tương đương với độ cao (tình tồi nhất) 5.2 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ách duyệt BST dựa thứ tự đến thăm nút gốc, nút trái, nút phải 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 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 a Duyệt thứ tự trước (NLR): - 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 preorder(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 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 thăm b Duyệt thứ tự (LNR): - Duyệt trái theo thứ tự - Thăm gốc - Duyệt phải theo thứ tự Kết 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 khóa duyệt theo thứ tự xuất theo thứ tự tăng dần c Duyệt thứ tự sau (LRN): - Duyệt trái theo thứ tự sau - Duyệt phải theo thứ tự sau - Thăm gốc Kết duyệt theo thứ tự sau: 1, 4, 7, 6, 3, 13, 14, 10, Trong cách duyệt này, gốc thăm sau 5.3 Cây cân AVL 5.3.1 Định nghĩa Cây AVL tìm kiếm nhị phân tự cân (self-balancing binary search tree), cấu trúc cân phát minh Trong AVL, độ cao hai nút nút sai khác nhiều 1, thuộc tính gọi thuộc tính cân độ cao (height – balanced) Các thao tác tìm kiếm, chèn phần tử mới, xóa bỏ phần tử khỏi có độ phức tạp O(log N) trường hợp trung bình trường hợp tồi Các thao tác làm ảnh hưởng tới tính chất cân thao tác chèn xóa bỏ khỏi nút, sau thao tác để điều chỉnh lại nút nhằm giữ cho cân bằng, cần thực thao tác quay (xoay – rotation) Thuật ngữ AVL đặt theo tên hai tác giả người Nga phát minh loại cấu trúc G.M Adelson – Velsky E.M Landis, báo hai người công bố vào năm 1962: “An algorithm for the organization of information” Nhân tố cân nút độ cao phải trừ độ cao trái Một nút có nhân tố cân bằng 1, -1 coi cân Một nút với nhân tố cân nhận giá trị khác xem không cân cần phải cân lại Nhân tố cân lưu nút tính dựa độ cao Hình 5.7 Cây AVL Cây AVL tương đối giống với loại cân khác, đỏ đen (Red Black Tree) thao tác số thao tác cần thực tìm kiếm, thêm, xóa phần tử khỏi Mặc dù đỏ đen có tính chất cân không chặt chẽ AVL hiệu tương đương nhau, số ứng dụng đòi hỏi thực thao tác tìm kiếm tập liệu lớn AVL tỏ chiếm ưu Tài liệu tham khảo [1] Đỗ Xuân Lôi(1998), Cấu trúc liệu giải thuật Nhà xuất Khoa học Kỹ thuật [2] Hồ Thuần, Hồ Cẩm Hà, Trần Thiên Thành(2008), Cấu trúc liệu, Phân tích thuật toán phát triển phần mềm, Nhà xuất giáo dục [3] Hồ Sĩ Đàm, Cấu trúc liệu giải thuật Nhà xuất Giáo dục (426 trang) [4] Giáo trình cấu trúc liệu – thuật toán, pts Đinh Mạnh Tường, [5] Giáo trình gải thuật, Nguyễn Văn Linh, ĐH Cần thơ 6] Bài giảng Thiết kế Đánh giá Thuật toán, Trần Xuân Sinh, NXB, ĐHQG, 2010 [7] Robert Lafore, Data Structures in Java [8] Niklaus wirth(1985), Algorithms and Data Structures [9] Wikipedia, “Từ điển bách khoa toàn thư trực tuyến tiếng Việt”, http://vi.wikipedia.org/wiki/ [10] Wikipedia, “Từ điển bách khoa toàn thư trực tuyến tiếng Anh”, http://en.wikipedia.org/wiki/Main_Page [11] Các tài liệu giảng website: http://csce.unl.edu/~cusack/Teaching/?page=notes [12] Thomas H.Cormen, Charles E.Leiserson, Ronald L.Rivest and Clifford Stein, “Introduction to Algorithms, Second Edition”, The MIT Press, 2001, 1180 pages [13] Jeff Cogswell, Christopher Diggins, Ryan Stephens, Jonathan Turkanis, Science Handbook, “C++ Cookbook”, O’Reilly, November 2005, 592 pages [14] 158488360X.Chapman Second Edition.pdf & Hall.CRC.Computer

Ngày đăng: 28/10/2016, 08:43

TỪ KHÓA LIÊN QUAN

w