1. 程式人生 > >C語言 2-3樹

C語言 2-3樹

2-3樹簡介

2-3樹是最簡單的B-樹(或-樹)結構,其每個非葉節點都有兩個或三個子女,而且所有葉都在統一層上。

實現過程

在2-3樹中,一個結點只有一個值的我們稱為2-結點,有兩個值的稱為3-結點,在2-3樹中,一個結點最多隻有兩個值,即3-結點
這裡寫圖片描述

什麼時候我們認為2-3樹不平衡呢?就是任意一個結點到最後每個結點的距離都相等。
當結點變成4-結點的時候,總共會有6種情況:
這裡寫圖片描述
所以針對每一種情況,我們一一實現就可以實現2-3樹了。

程式碼實現

ADT :

typedef struct node {
    int a[3];  //a[2],作為4-結點時的快取
int num; //陣列a的長度:1,2,3 struct node *left_child; struct node *mid_child; struct node *right_child; struct node *tmp_child; //作為4-結點時的快取 struct node *parent; } Btree, *BtreePtr; void exchange(int *a, int *b); BtreePtr _node(const int key); //create a node void _sort(BtreePtr b); //sort a[]
BtreePtr _checkNum(BtreePtr p); //balance BtreePtr _insertBTree(BtreePtr b, const int key, const int pos); //insert key BtreePtr insertBTree(BtreePtr root, const int key, const int pos); //initial void freeTree(BtreePtr p); int BTreeSearch(const int *a, const int length, const int key) ;

完整程式碼:

#include <stdio.h>
#include <malloc.h> #include <memory.h> #define NUM(p) ((p==NULL)?0:p->num) typedef struct node { int a[3]; int num; //1,2,3 struct node *left_child; struct node *mid_child; struct node *right_child; struct node *tmp_child; struct node *parent; } Btree, *BtreePtr; void exchange(int *a, int *b) { int tmp = *a; *a = *b; *b = tmp; } BtreePtr _node(const int key) { BtreePtr p = (BtreePtr)malloc(sizeof(Btree)); if (p != NULL) { memset(p, 0, sizeof(p)); p->a[0] = key; p->num = 1; p->left_child = NULL; p->right_child = NULL; p->mid_child = NULL; p->tmp_child = NULL; p->parent = NULL; } else { puts("記憶體不足"); } return p; } void _sort(BtreePtr b) { int length = b->num; for (int i = 0; i < length; i++) { for (int j = i; j < length; j++) { if ((b->a[j]) < (b->a[i])) { exchange(&(b->a[j]), &(b->a[i])); } } } } BtreePtr _checkNum(BtreePtr p) { if (NUM(p) == 1) { //2-結點 if (NUM(p->left_child) == 3) { //case 2 p->a[1] = p->left_child->a[1]; p->num++; _sort(p); BtreePtr l = _node(p->left_child->a[0]); l->left_child = p->left_child->left_child; l->parent = p; BtreePtr r = _node(p->left_child->a[2]); r->left_child = p->left_child->mid_child; r->right_child = p->left_child->right_child; r->parent = p; p->left_child = l; p->mid_child = r; } else if (NUM(p->right_child) == 3) { //case 3 p->a[1] = p->right_child->a[1]; p->num++; _sort(p); BtreePtr l = _node(p->right_child->a[0]); l->left_child = p->right_child->left_child; l->parent = p; BtreePtr r = _node(p->right_child->a[2]); r->left_child = p->right_child->mid_child; r->right_child = p->right_child->right_child; r->parent = p; p->mid_child = l; p->right_child = r; } } else if (NUM(p) == 2) { //3-結點 if (NUM(p->left_child) == 3) { //case 4 p->a[2] = p->left_child->a[1]; p->num++; _sort(p); p->tmp_child = p->mid_child; p->mid_child = _node(p->left_child->a[2]); BtreePtr l = _node(p->left_child->a[0]); l->left_child = p->left_child->left_child; l->right_child = p->left_child->mid_child; l->parent = p; BtreePtr r = _node(p->left_child->a[2]); r->left_child = p->left_child->tmp_child; r->right_child = p->left_child->right_child; r->parent = p; p->left_child = l; } else if (NUM(p->right_child) == 3) { //case 5 p->a[2] = p->right_child->a[1]; p->num++; _sort(p); p->tmp_child = _node(p->right_child->a[2]); // BtreePtr l = _node(p->right_child->a[0]); l->right_child = p->right_child->left_child; l->right_child = p->right_child->mid_child; l->parent = p; BtreePtr r = _node(p->right_child->a[2]); r->right_child = p->right_child->tmp_child; r->right_child = p->right_child->right_child; r->parent = p; p->right_child = l; } else if (NUM(p->mid_child) == 3) { p->a[2] = p->mid_child->a[1]; p->num++; _sort(p); //p->tmp_child = p->mid_child; //p->mid_child = _node(p->left_child->a[2]); BtreePtr l = _node(p->mid_child->a[0]); l->left_child = p->mid_child->left_child; l->right_child = p->mid_child->mid_child; l->parent = p; BtreePtr r = _node(p->mid_child->a[2]); r->left_child = p->mid_child->tmp_child; r->right_child = p->mid_child->right_child; r->parent = p; p->mid_child = l; p->tmp_child = r; } } if (p->num == 3) { if (p->parent == NULL) { // case 1; BtreePtr t = p->left_child; p->left_child = _node(p->a[0]); p->left_child->left_child = t; p->left_child->right_child = p->mid_child; p->left_child->parent = p; t = p->right_child; p->right_child = _node(p->a[2]); p->right_child->left_child = p->tmp_child; p->right_child->right_child = t; p->right_child->parent = p; p->mid_child = NULL; p->tmp_child = NULL; p->a[0] = p->a[1]; p->num = p->num - 2; } } return p; } BtreePtr _insertBTree(BtreePtr b, const int key, const int pos) { if (b->left_child == NULL && b->right_child == NULL) { //底節點 b->a[b->num] = key; b->num++; _sort(b); } else { if (b->num == 1) { if (key < b->a[0]) { //num =1, 2 b->left_child = _insertBTree(b->left_child, key, pos); } else if (key > b->a[0]) { //num = 2 b->right_child = _insertBTree(b->right_child, key, pos); } } else if (b->num == 2) { if (key < b->a[0]) { //num =1, 2 b->left_child = _insertBTree(b->left_child, key, pos); } else if (key > b->a[1]) { //num = 2 b->right_child = _insertBTree(b->right_child, key, pos); } else { b->mid_child = _insertBTree(b->mid_child, key, pos); } } } b = _checkNum(b); return b; } BtreePtr insertBTree(BtreePtr root, const int key, const int pos) { if (root == NULL) { root = _node(key); } else { root = _insertBTree(root, key, pos); } return root; } void freeTree(BtreePtr p) { if (p->left_child != NULL) { freeTree(p->left_child); } if (p->right_child != NULL) { freeTree(p->right_child); } if (p->mid_child != NULL) { freeTree(p->mid_child); } free(p); p = NULL; } int BTreeSearch(const int *a, const int length, const int key) { BtreePtr root = NULL; for (int i = 0; i < length; i++) { root = insertBTree(root, a[i], i); } freeTree(root); return -1; } void main() { const int length = 8; int my_array[8] = { 7, 5, 9 ,11,10,6, 12, 13}; BTreeSearch(my_array, length, 7); }