Cỏc phộp toỏn trờn B-tree

Một phần của tài liệu giáo trình cấu trúc dữ liệu 2 (Trang 92 - 103)

512 bytes/ record

2.2.2. Cỏc phộp toỏn trờn B-tree

Tỡm kiếm

Hỡnh 4.15

Xột node trong hỡnh 4.14, khoỏ caàntỡm là X. Giả sử nội dung của

node nằm trong bộ nhớ. Với m đủ lớnta sử dụng phương phỏp tỡm kiếm nhị phõn, nếu m nhỏ ta sử dụng phuơng phỏp tỡm kiếm tuần tự.

Nếu X khụng tỡm thấy sẽ cú ba trường hợp sau xảy ra:

i) Ki < X < Ki+1. Tiếp tục tỡm kiếm trõn cõy con Ci

ii) Km < X. Tiếp tục tỡm kiếm trờn Cm iii) X < K1. tiếp tục tỡm kiếm trờn C0

Quỏ trỡnh này tiếp tục cho đến khi node đỳngđược tỡm thấỵ Nếu đó đi đến node lỏ mà vẫn khụng tỡm thấy khoỏ, việc tỡm kiếm là thất

bạị

Phộp toỏn nodesearch

Trả về vị trớ nhỏ nhất của khúa trong nỳt current bắt đầu lớn hơn hay bằng k. Trường hợp k lớn hơn tất cả cỏc khúa trong nỳt current thỡ trả về vị trớ current-> numtrees-1

int nodesearch (pBNode current, int k) {

int i;

for(i=0;i< current->numtrees –1 && current- >key[i] < k; i++);

return (i);

}

Phộp toỏn nodesearchđược dựngđể tỡm khúa k cú trong nỳt current hay khụng. Nếu khúa k khụng cú trong nỳt current thỡ phộp toỏn này trả về vị trớ giỳp chỳng ta chọn nỳt con phự hợp của current để tiếp

tục tỡm khúa k trong nỳt con nàỵ

Phộp toỏn search

Tỡm khúa k trờn B-Treẹ Con trỏ current xuất phỏt từ gốc và đi xuống cỏc nhỏnh cõy con phự hợp để tỡm khúa k cú trong một nỳt current hay khụng.

Nếu cú khúa k tại nỳt current trờn cõy:

 Biến foucunrrent tra về giỏ trị TRUE

 Hàm search() trả về con trỏ chỉ nỳt current cú chứa khúa k

 Biến positionition trả về vị trớ của khúa k cú trong nỳt current

này

Nếu khụng cú khúa k trờn cõy:

Lỳc này current=NULL và q(nỳt cha của current) chỉ nỳt lỏ cú thể

thờm khúa k vào nỳt nàyđược.

 Biến foucunrrent trả về giỏ trị FALSE

 Hàm search() trả về con trỏ q là nỳt lỏ cú thờm nỳt k vào

 Biến positionition trả về vị trớ cú thể chốn khúa k vào nỳt lỏ q này

pBNode search(int k, int &positionition, int &foucunrrent) { int i; pBNode current, q; q = NULL; current = Root;

while (current !=NULL) {

i = nodesearch (current, k);

if(i< current->numtress–1 && k == current- >key[i]) //tim

thay

{

foucunrrent = TRUE;

positionition = i; // vi trớ tỡm thay khoa k

return(current); // node co chua khoa k

}q = current; q = current;

current = current ->Branch[i]; }

/*Khi thoat khoi vong lap tren la khong tim thay, luc nay current=NULL, q la node la co the them khoa k vao node nay, positionition la vi tri co the chen khoa k*/

foucunrrent = FALSE; positionition = i;

return (q); //tra ve node la

}

Phộp toỏn duyệt

Duyệt cỏc khúa của B-Tree theo thứ tự từ nhỏ đến lớn-bằng phương phỏpđệ qui

{

int i;

if(proot == NULL) //dieu kien dung

return;

else // de qui

{

/* vong lap duyet nhanh cay con Branch[i] va in khoa key[i] cua node proor*/

for(i = 0; i < proot -> numtress-1; i++) {

traverse (proot ->Branch[i]); printf (“%8d”, proot -> key[i]); }

//duyet nhanh cay con cuoi cung cua node proot

traverse (proot -> Branch[proot -> numtrees-1]); }

}

Thờm vào

Trước khi đưa ra giải thuật thờm một phần tử mới vào B- Tree, ta xem tỡnh huống cụ thể qua cỏc vớ dụ sau :

Vớ dụ 1:

- Thờm x=22 vào B-Tree ở hỡnh 4.15ạ Khúa 22 chưa cú trong cõy, nhưng khụng thể thờm vào node C vỡ node Cđóđầỵ

- Do đú tỏch node C thành hai node : node mới D được

cấp phỏt và m+1 khúađược chia đều cho 2 node C và D, và khúaở giữa được chuyển lờn node cha A : Hỡnh 4.15b

a)

b)

Hỡnh 4.16

Như vậy, việc thờm một khúa mới vào B-Tree cú thể gõy ra việc

tỏch node và việc tỏch node cú thể lan truyền ngược lờn node cha, trong trường hợp đặc biệt lan truyền đến tận gốc của B-Tree

Vớ dụ 2 : Xem quỏ trỡnh tạo B-Tree từ dóy cỏc khúa sau :

20; 40 10 30 15; 35 7 26 18 22; 5; 4 13 46 27 8 32; 38 24 45 25 Sau khi thờm vào khúa 30 :

Hỡnh 4.17 a

Khi thờm vào 15 thỡ node này bị đầy, do đú trường hợp này tạo

thành hai node mới : phần tử ở giữa là 20 bị đẩy lờn tạo thành một

node mới, cỏc phần tử cũn lại chia cho hai node : node cũ chứa 10,

15 và node mới thứ hai chứa 30,40 10, 20, 30, 40 20 7, 10, 15, 18 26, 30, 35, 40 A B C 20, 7, 10, 15, 18 22, 26 , 35, 40 A B C D

Hỡnh 4.17 b

Thờm vào cỏc khúa 35, 7,26 và 18.Đến khi thờm khúa 22 cũng cú sự đầy node dẫn đến việc tỏch node:

Hỡnh 4.17 c

Thờm vào 5 cũng cú sự đầy node (node đang chứa bốn khúa 7, 10,

15, 18) dẫn đến việc tỏch node :

Hỡnh 4.17 d

Thờm vào cỏc khúa 42, 13, 46, 27 và 8.Đến khi thờm 32 cú sự tỏch

node :

Hỡnh 4.17 e

Thờm vào 38, 24 và 45. Thờm 25 vào cú sự tỏch node và cho thấy

sự lan truyền tỏch node ngược lờn về phớa gốc : 25 thờm vào node (22, 24 26, 27) làm node này bị tỏch và 25 được đưa lờn node cha (10, 20, 30, 40) làm node này bị tỏch thành hai node và khoỏ 25 được đưa lờn thành node gốc mớị

Hỡnh 4.17 f Phộp toỏn insert 25 10, 20 30, 40 5, 7, 8 13, 15, 18 22, 24 26, 27 32, 35, 38 42, 45, 48 20 10, 15 30, 40 20, 30 7, 10, 15, 18 22, 26 35, 40 10, 20, 30 5, 7 15, 18 22, 26 35, 40 10, 20, 30, 40 5, 7, 8 13, 15, 18 22, 26, 27 32, 35 42, 46

Thờm khúa k vào vị trớ positionition của nỳt lỏ s (s và positionition do phộp toỏn search() trả về)

 Nếu nỳt lỏ s chưađầy: gọi phộp toỏn insnode để chốn khúa k vào nỳt s

 Nếu nỳt lỏ s đóđầy: tỏch nỳt lỏ này thành hai nỳt nửa trỏi và nửa

phải

void insert (pBNode s, int k, int positionition)

{

pBNode current, right_half, f, extra_branch; int positionition, extra_entry, median;

//khoi dong cac tri truoc khi vao vong lap tach cac node day current

current = s; extra_entry = k;

extra_branch = NULL; // vi current la node la nen gan

// extra_branch la NULL

positionition = positionition; f = father (current);

// Vong lap tach cac node day current

while (f != NULL && current -> numtrees == Order) {

split(current, extra_entry, extra_branch, positionition, right_half, median);

// Gan lai cac tri sau lan tach node truoc

current = f;

extra_entry = median; extra_branch = right_half;

positionition = nedesearch (f, median); f = father (current);

}

// Truong hop node current chua day va current khong phai la node goc

if(current - > numtrees < Order) {

//chen extra_entry va extra_branch tai vi tri positionition cua node current

insnode (current, extra_entry, extra_branch, positionition);

return; }

//Truong hop node current la node goc bi day, tach node goc nay va tao node goc moi

split (current, extra_entry, extra_branch, positionition, right_half, median);

Root = makeroot (median); // tao node goc moi

// Gan lai hai nhanh cay con cua node goc moi la current va right_half

Root -> Branch[0] = current; Root -> Branch[1] = right_half;

}

Khi thờm một khúa vào B-Tree chỳng ta cú thể viết nhưsau: printf(“\n Noi dung khoa moi: ”);

scanf(“%d”, &k);

// truong hop B-Tree bi rong khi tao node goc

if(Root == NULL)

Root = makeroot(k); else

{

s = search(k, &positionition, &timthay);if(timthay) if(timthay)

printf(“Bi trung khoa, khong them khoa %d vao

B-Tree duoc”, k); else

insert (s, k, positionition); }

Phộp split

Tỏch node đầy current, phộp toỏn nàyđược gọi bởi phộp toỏn Insert

 current là nỳt đầy bị tỏch, sau khi tỏch xong nỳt current chỉ

cũn lại một nửa số khúa bờn trỏi

 extra_entry, extra_branch và positionition là khúa mới,

nhỏnh cõy con và vị trớ chốn vào nỳt current

 Nỳt right_half là nỳt nửa phải cú được sau lần tỏch, nỳt

right_half chiếm một nửa số khúa bờn phải

medianlà khúa ngay chớnh giữa sẽ đượcchốn vào nỳt cha

void split (pBNode current, int extra_entry, pBNode

extra_branch, int positionition, pBNode &right_half, int &median)

{

pBNode current;

current = new pBNode; //cap phat node nua phai /*truong hop chen extra_entry va extra_branch vao node nua phai*/

if(positionition > Order/2) {

copy(current, Order/2+1, Order – 2, current);

insnode (current, extra_entry, extra_branch,

positionition- Order/2 -1);

current->numtrees = Order/2+1; /*so nhanh cay con con lai cua node nua trai*/

median = current -> key[Order/2]; right_half = current;

return; }

// truong hop extra_entry la median

if(positionition == Order/2) {

copy(current, Order/2, Order-2, current);

current->numtrees = Order/2+1; /*so nhanh cay con con lai cua node nua trai*/

/*Dieu chinh lai node con dau tien cua node nua phai*/

current -> Branch[0] = extra_branch; median = current -> key[Order/2]; right_half = current;

return; }

/* Truong hop chen extra_entry va extra_branch vao node nua trai*/

if(positionition < Order/2) {

copy(current, Order/2, Order-2, current);

current->numtrees = Order/2; /*so nhanh cay con con lai cua node nua trai*/

median = current -> key[Order/2- 1]; insnode(current,extra_entry,extra_branch, positionition); right_half = current; return; } } Phộp toỏninsnode

Chốn khúa extra_entry vào vị trớ positionition của nỳt chưa đầy current, và chốn nhỏnh cõy con extra_branch vào vị trớ bờn phải cuả khúa extra_entry

void insnode (pBNode current, int extra_entry, pBNode extra_branch, int positionition)

{

int i;

/*doi cac nhanh cay con va cac khoa tu vi tri positionition tro ve sau xuong mot vi tri*/

for(i = current->numtress – 1; i >=

positionition+1; i--)

{

current -> Branch[i+1] = current ->

Branch[i];

current -> key[i] = current -> key[i - 1]; }

// gan khoa extra_entry vao vi tri positionition

current -> key[positionition] = extra_entry;

// Gan nhanh extra_branch la nhanh cay con ben phai cua khoa extra_entry

current -> Branch[positionition + 1] =

extra_branch;

//tang so nhanh cay con cua node current len 1

current -> numtrees +=1; }

Hỡnh 4.18-Thao tỏc InsNode

Hỡnh 4.19Tỏch một Node đầy

Chộp cỏc khúa (và nhỏnh cõy con) từ vị trớ first đến vị trớ fast của nỳt current (nỳt nửa trỏi) sang nỳt right_half (nửa nỳt phải) . Phộp toỏn nàyđược gọi bởi phộp toỏn split

void copy(pBNode current, int first, int last, NODPTR right_half)

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ ++++++++++++++++++++++++++++++++++++++++++++++++++*/ {

int i;

// copy cac khoa tu node current qua node right_half

for(i = first; i < last, i++)

right_half->key[i-first]=current -> key[i];

// copy cac nhanh cay con tu node current qua right_half

for(i = first; i < last+1, i++)

right_half->Branch[i-first]=current -> Branch[i];

right_half ->numtrees = last – first +2 // so

nhanh cay con cua node right_half

}

Phộp toỏn loại bỏ

pBNode remove(const int &key)

/*++++++++++++++++++++++++++++++++++++++++++++++++++++Kết quả: Nếu tỡm thấy khúa key sẽ xoỏ khúa này và trả về địa chỉ Kết quả: Nếu tỡm thấy khúa key sẽ xoỏ khúa này và trả về địa chỉ

node chứa key, nếu khụng tỡm thấy trả về NULL

Sử dụng hàmđệ quy recursive_remove()

++++++++++++++++++++++++++++++++++++++++++++++++++++*/{ {

PBNode result = recursive_remove(root, key);

if (root != NULL && root->numtress == 0) {

pDNode old_root = root; root = root->branch[0];

delete old_root; }

return result; }

Hỡnh 4.20-Loại bỏ trờn B-tree

pBNode recursive_remove(pBNode current, const int &key)

/*++++++++++++++++++++++++++++++++++++++++++++++++++++c current hoặc rỗng hoặc là con trỏ đến cõy con.

Hàm này Thực hiện xoỏ key nếu tỡm thấy khoỏ key, ngược lại trả về NULL

Sử dụng cỏc hàm nodesearch(), copy_in_predecessor(), recursive_remove (recursively), remove_dată)và restore().

++++++++++++++++++++++++++++++++++++++++++++++++++++*/{ {

int positionition; PBNode result;

if (current == NULL) return NULL; else

{

if (search(current, key, positionition)) {

// Tỡm thấy key trong node current.

if (current->branch[positionition] != NULL)

{ // khụng phải là node lỏ

copy_in_predecessor(current, positionition);

result=recursive_remove(current- >branch[positionition],current- >data[positionition]);

}

else remove_data(current,

positionition);//Xoỏ tại node lỏ

}

else result = recursive_remove(current- >branch[positionition], key);

if (current->branch[positionition] != NULL)

if (current->branch[positionition]->numtress <(order - 1)/2)

restore(current, positionition); }

return result; }

void remove_datăpBNode current,int positionition)

/*+++++++++++++++++++++++++++++++++++++++++++++++++++Xúa tại vị trớ positionition trờn node lỏ current. Xúa tại vị trớ positionition trờn node lỏ current. +++++++++++++++++++++++++++++++++++++++++++++++++++*/ {

for (int i = positionition; i < current->numtress - 1; i++)

current->data[i] = current->data[i + 1]; current->numtress --;

}

void copy_in_predecessor(pBNode current, int positionition)

/*+++++++++++++++++++++++++++++++++++++++++++++++++++Tại vị trớ positionition trờn node current(current Tại vị trớ positionition trờn node current(current khụng phải là lỏ ) sẽ được thay bởi khoỏ key cực phải của cõy con bờn trỏi của current)

+++++++++++++++++++++++++++++++++++++++++++++++++++*/

{

pBNode leaf = current->branch[positionition]; while (leaf->branch[leaf->numtress ] != NULL)

leaf = leaf->branch[leaf->numtress ]; current->data[positionition]=leaf->data[leaf- >numtress-1];

}

void restore(pBNode current,int positionition)

/*++++++++++++++++++++++++++++++++++++++++++++++++++Sữ dụng cỏc hàm: move_left, move_right, combine. Sữ dụng cỏc hàm: move_left, move_right, combine. ++++++++++++++++++++++++++++++++++++++++++++++++++*/ { if(positionition==current->numtress) //Trường hợp nhỏnh cực phải if(current->branch[positionition-1]->numtress>(order- )/ 2)

move_right(current, positionition - 1); else

combine(current, positionition); else if (positionition == 0) // Trường hợp nhỏnh cực trỏi if (current->branch[1]->numtress > (order - 1) / 2) move_left(current, 1); else combine(current, 1); else //cỏc trường hợp khỏc: nhỏnh giữa if(current->branch[positionition-1]->numtress>(order- 1)/ 2)

move_right(current, positionition - 1);

else if(current->branch[positionition+1]-

>numtress>(order- 1) / 2)

move_left(current, positionition + 1); else

combine(current, positionition); }

void move_left(pBNode current,int positionition)

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ ++++++++++++++++++++++++++++++++++++++++++++++++++*/ {pBNode left_branch = current->branch[positionition - 1];

pBNode right_branch = current->branch[positionition]; left_branch->data[left_branch->numtress ] = current- >data[positionition - 1]; left_branch->branch[++left_branch->numtress ] = right_branch->branch[0]; current->data[positionition - 1] = right_branch- >data[0]; right_branch->numtress --;

for (int i = 0; i < right_branch->numtress ; i++) {

right_branch->data[i]=right_branch->data[i + 1];

right_branch->branch[i]=right_branch-branch[i+1]; }

right_branch->branch[right_branch->numtress + 1]; }

void move_right(pBNode current,int positionition)

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ ++++++++++++++++++++++++++++++++++++++++++++++++++*/ {

pBNode right_branch = current->branch[positionition + 1];

pBNode left_branch = current->branch[positionition]; right_branch->branch[right_branch->numtress + 1] =

right_branch->branch[right_branch->numtress ]; for (int i = right_branch->numtress ; i > 0; i--)

{ right_branch->data[i]=right_branch->data[i - 1]; right_branch->data[i]=right_branch->data[i - 1]; right_branch->branch[i]=right_branch->branch[i-1]; } right_branch->numtress ++; right_branch->data[0] = current- >data[positionition]; right_branch- >branch[0]=left_branch-branch[left_branch- >numtress - -]; current->data[positionition]= left_branch- >data[left_branch->numtress ]; }

void combine(pBNode current,int positionition)

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ ++++++++++++++++++++++++++++++++++++++++++++++++++*/ {

int i;

pBNode left_branch = current->branch[positionition - 1];

pBNode right_branch = current->branch[positionition]; left_branch->data[left_branch->numtress ] = current- >data[positionition - 1];

left_branch->branch[++left_branch->numtress ] =

right_branch->branch[0];

for (i = 0; i < right_branch->numtress ; i++) { left_branch->data[left_branch->numtress]= right_branch->data[i]; left_branch->branch[++left_branch->numtress ] = right_branch->branch[i + 1]; } current->numtress --;

for (i = positionition - 1; i < current->numtress ; i++) { current->data[i] = current->data[i + 1]; current->branch[i + 1] = current->branch[i + 2]; } delete right_branch; } Hỡnh 4.21-move_right, combine

Một phần của tài liệu giáo trình cấu trúc dữ liệu 2 (Trang 92 - 103)