数据结构-各类树
2017-12-30 18:42
183 查看
树中最基本的是二叉树,其中左边结点是左子树,右边结点是右子树。在二叉树的基础上再加上左子树小于根结点,右子树大于根节点这个约束的话,就成了二叉查找树。一颗好的二叉查找树可以在O(lgn)里完成查找。
对于查找树的操作,主要时删除操作比较麻烦,删除时需考虑3种情况,
删除的是叶子节点(直接删即可)。
删除的节点有一边有子树(将删除结点的子树接到删除结点的父节点即可)
删除结点有两个子树(有多种处理方法,但实际原理都一样,就是找出大小最接近删除结点的结点来替换它,可以往左也可往右找,比如往右找的话,就得在右子树中找最小的那个,也就是从右子树的中序遍历的第一个)。
下面是二叉树一些基本操作的demo:
二叉树只是具有查找的性质,但是很容易出现树变形,比如极端情况下全是右子树或是左子树的话,就变成一个链表了,加速查找的意义也没有了,所以二叉树需要一些维护,使其保持树的良好特性。
对于维持树平衡也有很多方法,各有特点,其中最基本的操作是旋转,通过旋转使偏移的树结构恢复。SBT的话有它自己的一个特别操作。
其中红黑树的效率比较高,但是编程复杂度也比较高,下面是算法导论中红黑树的demo:
对于查找树的操作,主要时删除操作比较麻烦,删除时需考虑3种情况,
删除的是叶子节点(直接删即可)。
删除的节点有一边有子树(将删除结点的子树接到删除结点的父节点即可)
删除结点有两个子树(有多种处理方法,但实际原理都一样,就是找出大小最接近删除结点的结点来替换它,可以往左也可往右找,比如往右找的话,就得在右子树中找最小的那个,也就是从右子树的中序遍历的第一个)。
下面是二叉树一些基本操作的demo:
typedef struct treeNode { void *key; struct treeNode *parent; struct treeNode *left; struct treeNode *right; }treeNode; typedef struct bsTree { int(*cmp)(const void *, const void *); struct treeNode *root; }bsTree,tree; //cmp_int和print_key用于方便以后更改key类型的函数指针 int cmp_int(const void *p1, const void *p2) { const int *pa = (int *)p1; const int *pb = (int *)p2; if (*pa < *pb) return -1; if (*pa == *pb) return 0; return 1; } void print_key(const void *key) { const int *p = (int *)key; printf("%d ", *p); } void treeNode_init(struct treeNode *p, void *key) { p->key = key; p->left = NULL; p->right = NULL; p->parent = NULL; } bsTree *tree_create(int(*cmp)(const void *, const void *)) { bsTree *t = (bsTree *)malloc(sizeof(bsTree)); t->cmp = cmp; t->root = NULL; return t; } int insert_node(bsTree *t, struct treeNode *in) { struct treeNode *y = NULL, *x = t->root; //y指向插入结点的父节点 while (x != NULL) { y = x; if (t->cmp(in->key, x->key) < 0) { x = x->left; } else { x = x->right; } } in->parent = y; if (y == NULL) { t->root = in; } else { if (t->cmp(in->key, y->key) < 0) { y->left = in; } else { y->right = in; } } return 1; } int delete_node(bsTree *t, struct treeNode *del) { struct treeNode *x, *y; //删除的节点有3种情况 if (del == NULL) { printf("该节点不存在\n"); return -1; } if ( del->right == NULL) { del->parent->left = del->left; if (del->left != NULL) { del->left->parent = del->parent; } free(del); } else { y = del; 4000 //x用以指向最终和del替换的结点 //y用以判断del的右子树是否还有左子树 x = del->right; //有两个情况需要知道,del的右结点是否有左子树, 若有,那么将最左子树的右子树接到它的父节点的左边 while (x->left != NULL) { y = x; //y指针变化则有左子树 x = x->left; } del->key = x->key; //替换待删除结点,最后再释放x if (y != del) { y->left = x->right;//有左子树的话需对左子树的右子树处理 x->right->parent = y; } else { y->right = x->right; x->right->parent = y; } free(x); } return 0; } //递归中序遍历,参数为开始访问的节点和访问其中节点的处理函数。 void midorder(struct treeNode *x, void (*handle)(const void *)) { if (x != NULL) { midorder(x->left, handle); handle(x->key); midorder(x->right, handle); } } void preorder(struct treeNode *x, void (*handle)(const void *)) { if (x != NULL) { handle(x->key); preorder(x->left, handle); preorder(x->right, handle); } } void postorder(struct treeNode *x, void (*handle)(const void *)) { if (x != NULL) { preorder(x->left, handle); preorder(x->right, handle); handle(x->key); } } int main() { tree *t = tree_create(cmp_int); for (int i = 0; i < 10; i++) { struct treeNode *node = (treeNode *)malloc(sizeof(treeNode)); int *p = (int *)malloc(sizeof(int)); *p = i; treeNode_init(node, p); insert_node(t, node); } printf("中序遍历:\n"); midorder(t->root, print_key); return 0; }
二叉树只是具有查找的性质,但是很容易出现树变形,比如极端情况下全是右子树或是左子树的话,就变成一个链表了,加速查找的意义也没有了,所以二叉树需要一些维护,使其保持树的良好特性。
对于维持树平衡也有很多方法,各有特点,其中最基本的操作是旋转,通过旋转使偏移的树结构恢复。SBT的话有它自己的一个特别操作。
其中红黑树的效率比较高,但是编程复杂度也比较高,下面是算法导论中红黑树的demo:
#include<stdio.h> #include<string.h> #include<stdlib.h> typedef struct red_black_tree_type *tree; enum color_enum{ color_red, color_black }; struct tree_node{ void*key; enum color_enum color; struct tree_node *parent; struct tree_node *left; struct tree_node *right; }; struct red_black_tree_type{ int(*comp)(const void*, const void*); struct tree_node *root; struct tree_node *nil; }; void tree_node_ini(struct tree_node *p, void* key) { p->key = key; p->parent = NULL; p->left = NULL; p->right = NULL; p->color = color_black; } void tree_left_rotate(tree t, struct tree_node *x) { struct tree_node *y = x->right; x->right = y->left; if (y->left != t->nil) { y->left->parent = x; } y->parent = x->parent; if (x->parent == t->nil) { t->root = y; } else { if (x == x->parent->left) { x->parent->left = y; } else { x->parent->right = y; } } y->left = x; x->parent = y; } void tree_right_rotate(tree t, struct tree_node *x) { struct tree_node *y = x->left; x->left = y->right; if (y->right != t->nil) { y->right->parent = x; } y->parent = x->parent; if (x->parent == t->nil) { t->root = y; } else { if (x == x->parent->left) { x->parent->left = y; } else { x->parent->right = y; } } y->right = x; x->parent = y; } tree tree_create(int(*comp)(const void*, const void*)) { tree t = (tree )malloc(sizeof(struct red_black_tree_type)); t->comp = comp; t->nil = (tree_node *)malloc(sizeof(struct tree_node)); tree_node_ini(t->nil, NULL); t->root = t->nil; return t; } void tree_destroy_all_node(tree t, struct tree_node *x, void(*free_key)(void*)) { if (x != t->nil) { tree_destroy_all_node(t, x->left, free_key); tree_destroy_all_node(t, x->right, free_key); free_key(x->key); free(x); } } void tree_destroy(tree t, void(*free_key)(void*)) { tree_destroy_all_node(t, t->root, free_key); free(t->nil); free(t); } void tree_inorder_walk(tree t, struct tree_node*x, void(*handle)(const void*)) { if (x != t->nil) { tree_inorder_walk(t, x->left, handle); handle(x->key); printf(""); tree_inorder_walk(t, x->right, handle); } } struct tree_node*tree_search(tree t, struct tree_node *x, void*key) { if (x == t->nil || t->comp(key, x->key) == 0) { return x; } if (t->comp(key, x->key)<0) { return tree_search(t, x->left, key); } else { return tree_search(t, x->right, key); } } void tree_count_leaf(tree t, struct tree_node *x, struct tree_node *leaf_array[], int*num) { if (x != t->nil) { if (x->left == t->nil&&x->right == t->nil) { leaf_array[++*num] = x; } tree_count_leaf(t, x->left, leaf_array, num); tree_count_leaf(t, x->right, leaf_array, num); } } void tree_black_height(tree t, struct tree_node *x, struct tree_node *leaf_node, int*black_height) { if (x->color == color_black) { ++*black_height; } if (x == t->nil) { return; } if (t->comp(leaf_node->key, x->key)<0) { tree_black_height(t, x->left, leaf_node, black_height); } else { tree_black_height(t, x->right, leaf_node, black_height); } } struct tree_node *tree_minimum(tree t, struct tree_node *x) { while (x != t->nil&&x->left != t->nil) { x = x->left; } return x; } struct tree_node *tree_successor(tree t, struct tree_node *x) { if (x->right != t->nil) { return tree_minimum(t, x->right); } struct tree_node *y = x->parent; while (y != t->nil&&x == y->right) { x = y; y = y->parent; } return y; } void tree_insert_fixup(tree t, struct tree_node *z) { struct tree_node *y = t->nil; while (z->parent->color == color_red) { if (z->parent == z->parent->parent->left) { y = z->parent->parent->right; // 情况1:z 的叔叔 y 是红色的 if (y->color == color_red) { z->parent->color = color_black; y->color = color_black; z->parent->parent->color = color_red; z = z->parent->parent; } else { //情况2:z的叔叔y是黑色的,z是右孩子 if (z == z->parent->right) { z = z->parent; tree_left_rotate(t, z); } //情况3:z的叔叔y是黑色的,z是左孩子 z->parent->color = color_black; z->parent->parent->color = color_red; tree_right_rotate(t, z->parent->parent); } } else { y = z->parent->parent->left; if (y->color == color_red) { z->parent->color = color_black; y->color = color_black; z->parent->parent->color = color_red; z = z->parent->parent; } else { if (z == z->parent->left) { z = z->parent; tree_right_rotate(t, z); } z->parent->color = color_black; z->parent->parent->color = color_red; tree_left_rotate(t, z->parent->parent); } } } t->root->color = color_black; } void tree_insert(tree t, struct tree_node *z) { struct tree_node *y = t->nil; struct tree_node *x = t->root; while (x != t->nil) { y = x; if (t->comp(z->key, x->key)<0) { x = x->left; } else { x = x->right; } } z->parent = y; if (y == t->nil) { t->root = z; } else { if (t->comp(z->key, y->key)<0) { y->left = z; } else { y->right = z; } } z->left = t->nil; z->right = t->nil; z->color = color_red; tree_insert_fixup(t, z); } void tree_delete_fixup(tree t, struct tree_node *x) { struct tree_node *w = t->nil; while (x != t->root&&x->color == color_black) { if (x == x->parent->left) { w = x->parent->right; //情况1:x的兄弟w是红色的 if (w->color == color_red) { w->color = color_black; x->parent->color = color_red; tree_left_rotate(t, x->parent); w = x->parent->right; } else { //情况2:x的兄弟w是黑色的,而且w的两个孩子都是黑色的 if (w->left->color == color_black &&w->right->color == color_black) { w->color = color_red; x = x->parent; } d11b else { //情况3:x的兄弟w是黑色的,w的左孩子是红的,右孩子是 //黑的 if (w->right->color == color_black) { w->left->color = color_black; w->color = color_red; tree_right_rotate(t, w); w = x->parent->right; } // 4:x w , w //情况 的兄弟 是黑色的而且 的右孩子是红色的 w->color = x->parent->color; x->parent->color = color_black; w->right->color = color_black; tree_left_rotate(t, x->parent); x = t->root; } } } else { w = x->parent->left; if (w->color == color_red) { w->color = color_black; x->parent->color = color_red; tree_right_rotate(t, x->parent); w = x->parent->left; } else { if (w->right->color == color_black &&w->left->color == color_black) { w->color = color_red; x = x->parent; } else { if (w->left->color == color_black) { w->right->color = color_black; w->color = color_red; tree_left_rotate(t, w); w = x->parent->left; } w->color = x->parent->color; x->parent->color = color_black; w->left->color = color_black; tree_right_rotate(t, x->parent); x = t->root; } } } } x->color = color_black; } void swap(void*a, void*b, size_t elem_size) { if (a == NULL || b == NULL || a == b) return; char *temp = (char *)malloc(elem_size); /*vs不支持c99变长数组*/ memcpy(temp, a, elem_size); memcpy(a, b, elem_size); memcpy(b, temp, elem_size); } struct tree_node *tree_delete(tree t, struct tree_node *z) { struct tree_node *y; struct tree_node *x; if (z->left == t->nil || z->right == t->nil) { y = z; } else { y = tree_successor(t, z); } if (y->left != t->nil) { x = y->left; } else { x = y->right; } x->parent = y->parent; if (y->parent == t->nil) { t->root = x; } else { if (y == y->parent->left) { y->parent->left = x; } else { y->parent->right = x; } } if (y != z) { /*要删除的结点y是z的后继,交换z和y结点的内容*/ swap(&z->key, &y->key, sizeof(void*)); } if (y->color == color_black) { tree_delete_fixup(t, x); } return y; } int cmp_int(const void *p1, const void *p2) { const int *pa = (int *)p1; const int *pb = (int *)p2; if (*pa<*pb) return-1; if (*pa == *pb) return 0; return 1; } void print_key(const void *key) { const int *p = (int *)key; printf("%-2d", *p); } int main() { tree t = tree_create(cmp_int); for (int i = 0; i<10; i++) { struct tree_node *node = (tree_node *)malloc(sizeof(struct tree_node)); int*ip = (int *)malloc(sizeof(int)); *ip = i; tree_node_ini(node, ip); tree_insert(t, node); } printf("中序遍历结果:\n"); tree_inorder_walk(t, t->root, print_key); printf("\n"); int k = 2; struct tree_node *result = tree_search(t, t->root, &k); printf("查找关键字:%d的结果:%s\n", k, result != t->nil ? "成功" : "失败"); struct tree_node *del_node = tree_delete(t, result); free(del_node->key); free(del_node); result = tree_search(t, t->root, &k); printf("删除关键字:%d的结果:%s\n", k, result == t->nil ? "成功" : "失败"); printf("查看黑高度:\n"); struct tree_node *left_array[100]; int num = -1; /*统计叶子结点*/ tree_count_leaf(t, t->root, left_array, &num); for (int i = 0; i<num; i++) { /*黑高度不包括自身,所以初始值为-1*/ int black_height = -1; tree_black_height(t, t->root, left_array[i], &black_height); /*测试黑高度,从根到叶的路径上,黑结点数是一样的*/ printf(" 根到叶子 :%d 的黑高度 :%d\n", *(int*)left_array[i]->key, black_height); } printf("中序遍历结果:\n"); tree_inorder_walk(t, t->root, print_key); printf("\n"); /*遍历树,释放结点的key*/ tree_destroy(t, free); return 0; }
相关文章推荐
- Python实现各类数据结构和算法----归并排序
- 【数据结构和算法】全面剖析树的各类遍历方法
- Python实现各类数据结构和算法---折半查找
- 数据结构-各类排序算法总结(一)
- 数据结构:各类迷宫问题详解(c语言版)
- 数据结构各类排序算法分析
- 【数据结构】Java实现各类经典排序算法——选择排序、冒泡排序
- 数据结构-各类排序算法总结(二)
- 数据结构—各类‘排序算法’实现(下)
- 数据结构-各类排序算法总结(三)
- 数据结构复习(1):内部排序--各类排序算法(C程序)
- 【数据结构和算法】全面剖析树的各类遍历方法
- 数据结构—各类‘排序算法’实现(上)
- 【数据结构】Java实现各类经典排序算法——插入排序、希尔排序
- 各类数据结构的特点
- 各类数据结构的特点
- 【数据结构】Java实现各类经典排序算法——快速排序、归并排序
- C/C++ 网络编程: 各类协议数据结构
- Python实现各类数据结构和算法---计数排序
- 【数据结构】Java实现各类经典排序算法——桶排序、堆排序