算法10---二叉搜索樹存在重復數據插入的實現
當用TREE-INSERT將n個具有相同關鍵字的數據項插入到一棵初始為空的二叉查找樹中時,該算法的漸近性能如何?
我們可以對TREE-INSERT做一些改進,即在第5行的前面測試key[z] = key[x],在第11行的前面測試key[z] = key[y]。如果等式成立,我們對下列策略中的某一種加以實現。對每一種策略,請給出將n個具有相同關鍵字的數據插入一棵初始為空的二叉查找樹中的漸近性能(以下的策略是針對第5行的,比較的是z和x的關鍵字。將x換成y即可用於第11行)。
b)在結點x處設一個布爾標志b[x],並根據b[x]的不同值,置x為left[x]或right[x]。每當插入一個與x具有相同關鍵字的結點時,b[x]取TRUE或FALSE。
c)在結點x處設置一個列表,其中所有結點都具有與x相同的關鍵字,並將z插入到該列表中。
d)隨機地將置為left[x]或right[x]
思考:
b)每次測試到等式成立時,若b[x]為FLASE,插入到左子樹中,b[x]為TRUE時,插入到右子樹中,然后將b[x]取反。
c)使用一個鏈表,所有具有相同關鍵字的結點組成一個鏈表,結點中的一個指針指向這個鏈表。
d)使用rand()%2隨機地決定插入到左子樹中還是右子樹中。
代碼實現如下;首先是b方法
1 //二叉查找樹結點的結構 2 struct node 3 { 4 int key;//關鍵字 5 int data;//衛星數據 6 bool b; 7 node *left;//左孩子 8 node *right;//右孩子 9 node *p;//父結點 10 node(int x):key(x),data(x),b(0),left(NULL),right(NULL),p(NULL){}; //初始化 11 }; 12 //二叉查找樹的結構 13 struct tree 14 { 15 node *root; 16 tree():root(NULL){}//都是初始化的方法 17 }; 18 //二叉查找樹的插入 19 void Tree_Insert(tree *T, node *z) 20 { 21 //找到要插入的位置 22 node *x = T->root, *y = NULL; 23 //若x為空,x是要插入的位置,x的父是z->p 24 while(x != NULL) 25 { 26 y = x; 27 //等式成立時,由b決定插入到哪個子樹 28 if(z->key == x->key) 29 { 30 if(x->b == 0) 31 x = x->left; 32 else 33 x = x->right; 34 //對b取反 35 x->b = !x->b; 36 } 37 else if(z->key < x->key) 38 x = x->left; 39 else 40 x = x->right; 41 } 42 //修改指針,注意樹為空的情況 43 z->p = y; 44 if(y == NULL) 45 T->root = z; 46 else if(z->key == y->key) 47 { 48 if(y->b == 0) 49 y->left = z; 50 else y->right = z; 51 y->b = !y->b; 52 } 53 else if(z->key < y->key) 54 y->left = z; 55 else y->right = z; 56 }
C方法代碼實現如下
1 //二叉查找樹結點的結構 2 struct node 3 { 4 int key;//關鍵字 5 int data;//衛星數據 6 node *next;//指向具體相同關鍵字的鏈表 7 node *left;//左孩子 8 node *right;//右孩子 9 node *p;//父結點 10 node(int x):key(x),data(x),left(NULL),right(NULL),p(NULL),next(NULL){} 11 }; 12 //二叉查找樹的結構 13 struct tree 14 { 15 node *root; 16 tree():root(NULL){} 17 }; 18 //二叉查找樹的插入 19 void Tree_Insert(tree *T, node *z) 20 { 21 //找到要插入的位置 22 node *x = T->root, *y = NULL; 23 //若x為空,x是要插入的位置,x的父是z->p 24 while(x != NULL) 25 { 26 y = x; 27 //等式成立時,不繼續插入到子樹中,而是鏈入鏈表中 28 if(z->key == x->key) 29 { 30 z->next = x->next; 31 x->next = z; 32 return; 33 } 34 else if(z->key < x->key) 35 x = x->left; 36 else 37 x = x->right; 38 } 39 //修改指針,注意樹為空的情況 40 z->p = y; 41 if(y == NULL) 42 T->root = z; 43 //等式成立時,不是插入到子樹中,而是鏈入鏈表中 44 else if(z->key == y->key) 45 { 46 z->next = y->next; 47 y->next = z; 48 } 49 else if(z->key < y->key) 50 y->left = z; 51 else y->right = z; 52 }
d方法實現如下
1 //二叉查找樹結點的結構 2 struct node 3 { 4 int key;//關鍵字 5 int data;//衛星數據 6 node *left;//左孩子 7 node *right;//右孩子 8 node *p;//父結點 9 node(int x):key(x),data(x),left(NULL),right(NULL),p(NULL){} 10 }; 11 //二叉查找樹的結構 12 struct tree 13 { 14 node *root; 15 tree():root(NULL){} 16 }; 17 //二叉查找樹的插入 18 void Tree_Insert(tree *T, node *z) 19 { 20 //找到要插入的位置 21 node *x = T->root, *y = NULL; 22 //若x為空,x是要插入的位置,x的父是z->p 23 while(x != NULL) 24 { 25 y = x; 26 //若等式成立,隨機地決定插入到哪個子樹中 27 if(z->key == x->key) 28 { 29 if(rand()%2 == 0) 30 x = x->left; 31 else 32 x = x->right; 33 } 34 else if(z->key < x->key) 35 x = x->left; 36 else 37 x = x->right; 38 } 39 //修改指針,注意樹為空的情況 40 z->p = y; 41 if(y == NULL) 42 T->root = z; 43 else if(z->key == y->key) 44 { 45 if(rand()%2 == 0) 46 x = x->left; 47 else 48 x = x->right; 49 } 50 else if(z->key < y->key) 51 y->left = z; 52 else y->right = z; 53 }
