二叉排序树
二叉排序树其实就是二分法,平均时间复杂度为O(nlogn),以下是本人硬着头皮造的轮子。
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 5 typedef struct bst_node { 6 int data; 7 struct bst_node *lchild, *rchild; 8 } bst_node; 9 10 /*last_pnode为查找得到的最后一个node指针,成功则指向查找值node,失败则指向查找值得父亲node*/ 11 int find_bst_data(bst_node *node, bst_node **last_pnode, int data) 12 { 13 if (node == NULL) 14 return -1; 15 if (data == node->data) { 16 return 0; 17 } else if (data < node->data) { 18 if (node->lchild == 0) 19 return -1; 20 *last_pnode = node->lchild; 21 } else { 22 if (node->rchild == 0) 23 return -1; 24 *last_pnode = node->rchild; 25 } 26 return find_bst_data(*last_pnode, last_pnode, data); 27 } 28 29 int insert_bst_data(bst_node **root_pnode, int data) 30 { 31 bst_node *last_node = *root_pnode; 32 bst_node *new_node; 33 /*在树找不到结果,则插入数据*/ 34 if (find_bst_data(*root_pnode, &last_node, data)) { 35 new_node = (bst_node *)malloc(sizeof(bst_node)); 36 memset(new_node, 0, sizeof(*new_node)); 37 38 if (*root_pnode == NULL) { 39 /*若树还没创建则创建新树*/ 40 *root_pnode = new_node; 41 } else if (data < last_node->data) { 42 last_node->lchild = new_node; 43 } else { 44 last_node->rchild = new_node; 45 } 46 new_node->data = data; 47 return 0; 48 } 49 return -1; 50 } 51 52 53 int delete_bst_ops(bst_node **pnode) 54 { 55 bst_node *pre_node, *temp_node; 56 if ((*pnode)->rchild == NULL) { 57 temp_node = (*pnode); 58 (*pnode) = (*pnode)->lchild; 59 free((void *)temp_node); 60 61 } else if ((*pnode)->lchild == NULL) { 62 temp_node = (*pnode); 63 (*pnode) = (*pnode)->rchild; 64 free((void *)temp_node); 65 } else { 66 temp_node = (*pnode); 67 pre_node = (*pnode)->lchild; 68 while (pre_node->rchild != NULL) { 69 temp_node = pre_node; 70 pre_node = pre_node->rchild; 71 } 72 //若前驱节点(前驱不是右子树)等于目标左子树节点则不执行,直接把目标右子树的节点给前驱 73 if (temp_node != (*pnode)) { 74 temp_node->rchild = pre_node->lchild; 75 pre_node->lchild = (*pnode)->lchild; 76 } 77 pre_node->rchild = (*pnode)->rchild; 78 free((void *)(*pnode)); 79 *pnode = pre_node; 80 } 81 return 0; 82 83 } 84 85 86 /*这里为什么不用find_bst_data而自己写递归删除函数?因为要找到树的目标节点的真实存储空间, 87 如果用find_bst_data则不能对树真实节点修改,若要使用find_bst_data需要在函数里添加父节点指针的参数。 88 */ 89 int delete_bst_data(bst_node **pnode, int data) 90 { 91 if (*pnode == NULL) 92 return -1; 93 if (data == (*pnode)->data) { 94 delete_bst_ops(pnode); 95 return 0; 96 } else if (data < (*pnode)->data) { 97 delete_bst_data(&(*pnode)->lchild, data); 98 } else { 99 delete_bst_data(&(*pnode)->rchild, data); 100 } 101 } 102 103 //中序遍历 104 void in_order_traverse(bst_node *node, int *i) 105 { 106 if (node == NULL) 107 return; 108 in_order_traverse(node->lchild, i); 109 printf("%5d", node->data); 110 if (++(*i) % 10 == 0) 111 printf("\n"); 112 in_order_traverse(node->rchild, i); 113 } 114 115 void swap(int *x, int *y) 116 { 117 int t; 118 t = *x; 119 *x = *y; 120 *y = t; 121 } 122 123 #define B_SIZE 100 124 int main(int argc, char const **argv) 125 { 126 127 int i; 128 int n; 129 int buff[B_SIZE]; 130 bst_node *bst_root = NULL; 131 srand(time(0)); 132 for (i = 0; i < B_SIZE; i++) { 133 *(buff + i) = i; 134 } 135 136 for (n = B_SIZE; n > 0; n--) { 137 /*随机生成索引,并且和末尾索引的数据交换位置,形成真正的随机且不重复的数据*/ 138 swap(buff + rand() % n, buff + n - 1); 139 } 140 141 printf("-------------the raw data-------------\n"); 142 for (i = 0; i < B_SIZE; i++) { 143 printf("%5d", *(buff + i)); 144 if ((i + 1) % 10 == 0) 145 printf("\n"); 146 } 147 for (i = 0; i < B_SIZE; i++) { 148 insert_bst_data(&bst_root, buff[i]); 149 } 150 printf("-------------the processed data-------------\n"); 151 i = 0; 152 in_order_traverse(bst_root, &i); 153 delete_bst_data(&bst_root, 0); 154 delete_bst_data(&bst_root, 50); 155 delete_bst_data(&bst_root, 100); 156 printf("-------------the deleted data-------------\n"); 157 i = 0; 158 in_order_traverse(bst_root, &i); 159 return 0; 160 }
以上程序随机生成100个0-99的数,程序不能插入相同的数,修改insert_bst_data这个函数就可以。
查找和增加数据都是比较简单,实现起来就需要依靠c的指针功底。(用全局变量毫无压力)
删除数据需要找到目标数的前驱(或使用后驱),把前驱node替代目标node,若前驱有左子树需要把左子树替代自己的位置。