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

bài giảng kỹ thuật lập trình chương 4 các cấu trúc dữ liệu tiên tiến nguyễn diệu hương

10 313 0

Đang tải... (xem toàn văn)

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 10
Dung lượng 454,33 KB

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

Nội dung

}; Lớp B_tree template struct B_node { // data members: int count; Record data[order − 1]; B_node *branch[order]; // constructor: B_node ; }; Giải thuật tìm kiếm template Error_code B_

Trang 1

Kỹ thuật lập trình

Chương 4 – Các cấu trúc

dữ liệu tiên tiến

1 Tìm kiếm ngoài – B-cây

(Kruse, Chương 11.3)

1.1 Định nghĩa

Lưu trữ ngoài

„Cho đến nay, ta luôn giả định là có thể lưu trữ toàn bộ một cấu trúc dữ liệu trong bộ nhớ trong

„Nếu dữ liệu là quá lớn không thể vừa với bộ nhớ trong?

‰ÆSử dụng bộ nhớ ngoài

„Vấn đề: đánh giá độ phức tạp về thời gian sử dụng O-lớn giả định mọi thao tác có thời gian như nhau

‰ÆKhông thể áp dụng với thao tác truy cập đĩa

Thời gian truy cập

„ Giả sử đĩa quay với tốc độ: 3600 RPM

‰Æmột vòng quay: 1/60 giây = 16.7ms

„ Trung bình cần nửa vòng/truy cập = 8ms

‰Æ1 giây = 120 lần truy cập = 25 triệu lệnh

‰1 phép truy cập đĩa = 200,000 lệnh

Thời gian truy cập

„Thời gian truy cập:

‰Bộ nhớ trong: μs

‰Đĩa cứng: ms

‰Đĩa mềm: s

„Đọc file:

‰Đọc theo từng trang / khối (block)

‰Block: 256-1024 từ

„ÆTìm kiếm ngoài: tối thiểu hóa số lần truy cập đĩa

Trang 2

Thời gian truy cập

„ Giả sử ta sử dụng một cây AVL để lưu trữ

toàn bộ thông tin chi tiết về người lái xe máy

tại VN (khoảng 20 triệu bản ghi)

„ Thu được cây rất cao:

hmin= log220,000,000 ~= 24

Æmất khoảng 0.2s

„ Giải pháp: sử dụng cây nhiều nhánh để giảm

độ cao

Cây tìm kiếm đa đường

„Cây tìm kiếm nhị phân:

‰Mỗi nút có nhiều nhất 2 con

‰Giá trị nút cha > mọi nút của cây con trái

< mọi nút của cây con phải

„Cây tìm kiếm đa đường cấp m

‰Mỗi nút có nhiều nhất m con

‰Một nút có k con và k-1 khóa

„ phân hoạch tất cả khóa trong cây con thành k tập con

„ (giải thích thêm: tham khảo trong Sedgewick hoặc Drozdek)

„Mục đích:

‰có chiều cao nhỏ nhất

„Điều kiện:

‰Không có cây con rỗng

‰Các nút lá cùng mức

‰Có ít nhất m/2 con

Để xây dựng cây có chiều cao nhỏ nhất:

„ Đảm bảo sao cho 0 có cây con rỗng xuất hiện trên

B-cây: Định nghĩa

„ Là cây tìm kiếm m-đường:

‰Tất cả nút lá có cùng mức

‰Nút giữa (trừ nút gốc) có: từ đến m nút

con

‰Số khóa của nút giữa = số con - 1,

‰Các khóa của nút giữa phân hoạch các khóa của

cây con như cây tìm kiếm

‰Nút gốc hoặc là nút lá hoặc có từ 2 đến m con

‰Nút lá chứa không nhiều hơn m - 1 khóa

m / 2 ⎤

Nên chọn m lẻ

Ví dụ: B-cây cấp 5

Trang 3

Ví dụ: B-cây cấp 5

1.2 Thao tác thêm

Thêm phần tử vào B-cây

1. Tìm khóa cần thêm

2. Nếu không tìm thấy, thêm khóa vào nút lá tại

vị trí kết thúc

3. Nếu nút lá đầy:

1. Tách thành 2 nút

2. Xác định nút trung vị và gửi lên trên để chèn vào

nút cha

3. Lặp lại bước 2-3 với khóa trung vị cho đến khi gặp

nút gốc

4. Nếu nút gốc đầy thì tách thành 2 nút con và

nút gốc mới

Ví dụ

„Thêm lần lượt dãy khóa sau vào một B-cây cấp 5 (ban đầu là cây rỗng):

a g f b k d h m j e s i r x c l n t u p

a g f b k d h m j e s i r x c l n t u p a g f b k d h m j e s i r x c l n t u p

Trang 4

a g f b k d h m j e s i r x c l n t u p

1.3 Cài đặt giải thuật tìm kiếm

Cài đặt giải thuật

„ Mô phỏng: trên bộ nhớ trong

‰Sử dụng con trỏ

„ Thực tế: thay con trỏ bằng địa chỉ của một

khối/trang của đĩa

Khai báo lớp B_tree

template <class Record, int order>

class B_tree {

B_node<Record, order> *root;

// Add private auxiliary functions here.

};

Lớp B_tree

template <class Record, int order>

struct B_node {

// data members:

int count;

Record data[order − 1];

B_node<Record, order> *branch[order];

// constructor:

B_node( );

};

Giải thuật tìm kiếm

template <class Record, int order>

Error_code B_tree<Record, order> ::

search_tree(Record &target)

/* Post: If there is an entry in the B-tree whose key

matches that in target, the parameter target is replaced by the corresponding Record from the B-tree and a code of success is returned

Otherwise a code of not_present is returned.

Uses: recursive_search_tree */

{

return recursive_search_tree(root, target);

}

Trang 5

template <class Record, int order>

Error_code B_tree<Record, order> :: recursive_search_tree

(B_node<Record, order> *current, Record &target)

/* Pre: current is either NULL or points to a subtree of

the B_tree

Post: If the Key of target is not in the subtree, a code of

not_present is returned Otherwise, a code of

success is returned and target is set to the

corresponding Record of the subtree.

Uses: recursive_search_tree recursively and

search_node */

recursive_search_tree {

Error_code result = not_present;

int position;

if (current != NULL) { result = search_node(current, target, position);

if (result == not_present)

result = recursive_search_tree(

current->branch[position], target);

else target = current->data[position];

}

return result;

}

search_node

template <class Record, int order>

Error_code B_tree<Record, order> :: search_node(

B_node<Record, order> *current, const Record &target, int

&position)

/* Pre: current points to a node of a B_tree.

Post: If the Key of target is found in *current, then a code of

success is returned,

the parameter position is set to the index of target, and the

corresponding

Record is copied to target Otherwise, a code of not_present is

returned,

and position is set to the branch index on which to continue the

search.

Uses: Methods of class Record */

search_node

„ {

„ position = 0;

„ while (position < >count && target >

current->data[position])

„ position ; // Perform a sequential search through the keys.

„ if (position < current->count && target == current->data[position])

„ return success;

„ else

„ return not_present;

„ }

1.3 Cài đặt giải thuật thêm

Thao tác thêm

„Đệ quy

„Tham số:

‰Đầu vào:

„ new_entry – bản ghi cần thêm

‰Đầu ra:

„ current: gốc của cây con hiện tại

„ median: bản ghi trung vị

„ right_branch: con trỏ tới nút nửa phải mới

Trang 6

template <class Record, int order>

Error_code B_tree<Record, order> :: insert(const

Record &new_entry)

/* Post: If the Key of new_entry is already in the

B_tree, a code of duplicate_error

is returned Otherwise, a code of success is returned and the Record

new_entry is inserted into the B-tree in such a way that

the properties

of a B-tree are preserved.

Uses: Methods of struct B_node and the auxiliary

function push_down */

{

Record median;

B_node<Record, order> *right_branch, *new_root;

Error_code result = push_down(root, new_entry, median,

right_branch);

if (result == overflow) { // The whole tree grows in height.

// Make a brand new root for the whole B-tree.

new_root = new B_node<Record, order>;

new_root->count = 1;

new_root->data[0] = median;

new_root->branch[0] = root;

new_root->branch[1] = right_branch;

root = new_root;

result = success;

}

return result;

}

Giải thuật đệ quy thêm vào cây con

template <class Record, int order>

Error_code B_tree<Record, order> :: push_down(

B_node<Record, order> *current,

const Record &new_entry,

Record &median, B_node<Record, order> * &right_branch)

/* Pre: current is either NULL or points to a node of a B_tree.

Post: If an entry with a Key matching that of new_entry is in the subtree to

which current points, a code of duplicate_error is returned Otherwise,

new_entry is inserted into the subtree: If this causes the height of the

subtree to grow, a code of overflow is returned, and the Record median is extracted to be reinserted higher in the B-tree, together with the subtree

right_branch on its right If the height does not grow, a code of success is

returned.

Uses: Functions push_down (called recursively), search_node, split_node, and

push_in */

{

Error_code result;

int position;

if (current == NULL) {

// Since we cannot insert in an empty tree, the recursion terminates.

median = new_entry;

right_branch = NULL;

result = overflow;

}

else { // Search the current node.

if (search_node(current, new_entry, position) == success)

result = duplicate_error;

else {

Record extra_entry;

B_node<Record, order> *extra_branch;

result = push_down(current->branch[position], new_entry,

extra_entry, extra_branch);

if (result == overflow) {

// Record extra_entry now must be added to current

if (current->count < order − 1) {

result = success;

push in(current, extra entry, extra branch, position);

Thêm khóa vào nút

Trang 7

template <class Record, int order>

void B_tree<Record, order> ::

push_in(B_node<Record, order> *current,

const Record &entry, B_node<Record, order>

*right_branch, int position)

/* Pre: current points to a node of a B_tree The node

*current is not full and

entry belongs in *current at index position.

Post: entry has been inserted along with its right-hand

branch right_branch into

*current at index position */

{

for (int i = current->count; i > position; i−−) { // Shift all later data to the right.

current->data[i] = current->data[i − 1];

current->branch[i 1] = current->branch[i];

}

current->data[position] = entry;

current->branch[position 1] = right_branch;

current->count ;

}

Tách đôi nút

template <class Record, int order>

void B_tree<Record, order> :: split_node(

B_node<Record, order> *current, // node to be split

const Record &extra_entry, // new entry to insert

B_node<Record, order> *extra_branch, // subtree on right of extra_entry

int position, // index in node where extra_entry goes

B_node<Record, order> * &right_half, // new node for right half of entries

Record &median) // median entry (in neither half)

/* Pre: current points to a node of a B_tree The node *current is full, but if there

were room, the record extra_entry with its right-hand pointer extra_branch

would belong in *current at position position, 0 position < order.

Post: The node *current with extra_entry and pointer extra_branch at position

position are divided into nodes *current and *right_half separated by a Record

median.

Uses: Methods of struct B_node, function push_in */

{

right_half = new B_node<Record, order>;

int mid = order/2; // The entries from mid on will go to right_half.

if (position <= mid) { // First case: extra_entry belongs in left half.

for (int i = mid; i < order − 1; i ) { // Move entries to right_half.

right_half->data[i − mid] = current->data[i];

right_half->branch[i 1 − mid] = current->branch[i 1];

}

current->count = mid;

right_half->count = order − 1 − mid;

push_in(current, extra_entry, extra_branch, position);

}

else { // Second case: extra_entry belongs in right half.

mid ; // Temporarily leave the median in left half.

for (int i = mid; i < order − 1; i ) { // Move entries to right_half.

right_half->data[i − mid] = current->data[i];

right_half->branch[i 1 − mid] = current->branch[i 1];

}

current->count = mid;

right_half->count = order − 1 − mid;

push_in(right_half, extra_entry, extra_branch, position − mid);

}

Tách đôi nút

TH1: position == 2, order == 5

(extra_entry nằm ở nửa trái)

Chuyển các phần tử sang phải

Trang 8

Thêm extra_entry và extra_branch Xóa median, dịch branch

TH2: position == 3, order == 5

(extra_entry thuộc nửa phải) Chuyển phần tử sang phải

Thêm extra_entry và extra_branch Xóa median, dịch branch

Trang 9

1.3 Xóa nút trên B-cây

Giải thuật

„Phần tử xóa nằm ở nút lá:

‰Nút lá có số phần tử > tối thiểu: xóa

‰Nút lá có số phần tử = tối thiểu: xét nút lá anh em kề

„ Nếu nút kề có số phần tử > tối thiểu: chuyển 1 phần tử lên nút cha, chuyển phần tử ở nút cha xuống nút lá có phần tử xóa.

„ Nếu nút kề có số phần tử = tối thiểu: phối hợp nút lá, nút kề và phần tử trung vị tại nút cha thành nút mới.

‰ Nếu nút cha bị có quá ít phần tử Æ lan truyền lên trên.

‰ Nút xóa nằm tại nút gốc, cây giảm chiều cao.

„Phần tử xóa nằm ở nút giữa:

ÆPhần tử kế tục nằm tại một nút lá: thay thế phần

tử kế tục với phần tử xóa => xóa tại nút lá

Trang 10

Kết quả

Ngày đăng: 19/10/2014, 18:20

TỪ KHÓA LIÊN QUAN

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