📄 dic_avltree_search.c
字号:
/* AVL树的检索算法*/
#include<stdio.h>
#include<stdlib.h>
enum { FALSE, TRUE };
typedef int KeyType;
struct AVLNode;
typedef struct AVLNode * PAVLNode;
struct AVLNode {
KeyType key; /* 结点的关键码 */
/*DataType value; 结点的其它信息 */
int bf; /* 结点的平衡因子 */
PAVLNode llink, rlink; /* 分别指向结点的左、右子女 */
};
typedef struct AVLNode *AVLTree;
typedef AVLTree * PAVLTree;
PAVLNode creatNode(KeyType key) {
PAVLNode node;
node = (PAVLNode)malloc(sizeof(struct AVLNode));
if (node != NULL) {
node->key = key; node->bf = 0;
node->llink = node->rlink = NULL;
}
return node;
}
PAVLNode lL(PAVLNode a, PAVLNode b) {
a->bf = 0; a->llink = b->rlink;
b->bf = 0; b->rlink = a; /* b指向调整后的子树的根结点 */
return b;
}
PAVLNode rR(PAVLNode a, PAVLNode b) {
a->bf = 0; a->rlink = b->llink;
b->bf = 0; b->llink = a;
return b;
}
PAVLNode lR(PAVLNode a, PAVLNode b) {
PAVLNode c = b->rlink;
a->llink = c->rlink; b->rlink = c->llink;
c->llink = b; c->rlink = a;
switch (c->bf){
case 0:
a->bf = 0; b->bf = 0; break; /* LR(0)型调整 */
case 1:
a->bf = 1; b->bf = 0; break; /* 新结点插在*c的左子树中,LR(L)型调整 */
case -1:
a->bf = 0; b->bf = -1; break;/* 新结点插在*c的右子树中,LR(R)型调整 */
}
c->bf = 0;
return c;
}
PAVLNode rL(PAVLNode a, PAVLNode b){
PAVLNode c = b->llink;
a->rlink = c->llink; b->llink = c->rlink;
c->llink = a; c->rlink = b;
switch(c->bf){
case 0:
a->bf = 0; b->bf = 0; break;/* *c本身就是插入结点,RL(0)型调整 */
case 1:
a->bf = 0; b->bf = 1; break;/* 插在*c的左子树中,RL(L)型调整 */
case -1:
a->bf = -1; b->bf = 0; break; /* 插在*c的右子树中,RL(R)型调整 */
}
c->bf = 0;
return c;
}
void avlSearchInsert(PAVLTree ptree, KeyType key){
PAVLNode node_a, node_b, parent_a, p, q, r,node;
int d;
if(*ptree == NULL) { /* 原来AVL树为空 */
*ptree = creatNode(key); return;
}
node_a = *ptree; parent_a = NULL; p = node_a; q = NULL;
while(p != NULL) { /* 寻找插入位置及最小不平衡子树 */
if(key == p->key) return; /* AVL树中已经有关键码为key的结点 */
r = q; q = p;
if(key < p->key) p = p->llink; /* 进入*p的左子树 */
else p = p->rlink; /* 进入*p的右子树 */
if(q->bf != 0) { /* 寻找最小不平衡子树*node_a */
parent_a = r; node_a = q;
}
}
node = creatNode(key);
if (key < q->key) q->llink = node; /* 使新结点成为*p的左子女 */
else q->rlink = node; /* 使新结点成为*p的右子女 */
/* 已经将新结点结点插入到AVL树中,node_a指向最小不平衡子树。 */
if (key < node_a->key) { /* 新结点是插在*node_a的左子树中 */
node_b = p = node_a->llink; d = -1;
}
else { /* 新结点是插在*node_a的右子树中 */
node_b = p = node_a->rlink; d = 1;
}
/* 下面修改*node_b到新结点路径上的各结点的平衡因子,*node_b为*node_a的子女 */
while ( p != NULL && p != node ) {
if (key < p->key) { /* *p的左子树高度加1 */
p->bf = -1; p = p->llink;
}
else { /* *p的右子树高度加1 */
p->bf = 1; p = p->rlink;
}
}
if (node_a->bf == 0) {
/* *node_a原平衡因子为0,插入结点后只可能为1或-1,没有破坏平衡性 */
node_a->bf = d; return;
}
if (node_a->bf == -d) { /* 新结点插在原来高度较小的子树中 */
node_a->bf = 0; return;
}
/* 下面是新结点插在原来高度较大的子树中,破坏了平衡性,要对子树进行调整 */
if (d == -1) /* 新结点插在*node_a的左子树中*/
if(node_b->bf == -1)
node_b = lL(node_a, node_b); /* LL型调整*/
else node_b = lR(node_a, node_b); /* LR型调整*/
else /* 新结点插在*node_a的右子树中*/
if(node_b->bf == 1)
node_b = rR(node_a, node_b); /* RR型调整 */
else node_b = rL(node_a, node_b); /* RL 型调整 */
if(parent_a == NULL) /* node_a原来指向树的根结点 */
*ptree = node_b;
else {
if(parent_a->llink == node_a)
parent_a->llink = node_b;
else parent_a->rlink = node_b;
}
}
int searchNode(PAVLTree ptree, KeyType key, PAVLNode *position) {
PAVLNode p = *ptree, q = p;
while (p != NULL) {
q = p;
if (p->key == key) { /* 检索成功时,由参数position指向查找到的结点 */
*position = p; return TRUE;
}
else if (p->key > key) /* 进入左子树继续检索 */
p = p->llink;
else p = p->rlink; /* 进入右子树继续检索 */
}
*position = q;
return FALSE; /* 检索失败时,position指向该结点应插入的父结点 */
}
/* 下面是试验程序 */
#define MAXNUM 100
typedef struct {
KeyType key; /* 字典元素的关键码字段 */
/*DataType value; /* 字典元素的属性字段 */
} DicElement;
typedef struct {
int n; /* n<=MAXNUM,为字典中元素的个数 */
DicElement element[MAXNUM];
} SeqDictionary;
SeqDictionary dic = {11,
18, 10, 73, 5, 68, 99, 27, 25, 41, 32, 51
};
void creatTree(PAVLTree ptree, SeqDictionary dic);
int searchNode(PAVLTree ptree, KeyType key, PAVLNode *position);
/* 用一个线性字典创建平衡二叉树。假定 *ptree 原为空树 */
void creatTree(PAVLTree ptree, SeqDictionary dic) {
int i;
*ptree = NULL;
for(i = 0; i < dic.n; i++)
avlSearchInsert(ptree, dic.element[i].key); /* 将新结点插入树中 */
}
int main(){
AVLTree tree = NULL;
int i, key;
PAVLNode position;
creatTree(&tree, dic);
while(1){
printf("Input 1 to insert element\n"
"2 to search element\n"
"else to exit\nWhat do you want to do?");
scanf("%d", &i);
if(i==1){
printf("Input the key you want to insert:");
scanf("%d",&key);
avlSearchInsert(&tree,key);
}
else if (i == 2){
printf("Input the key you want to search:");
scanf("%d",&key);
if (searchNode(&tree, key, &position) == TRUE)
printf("It is in the dictionary!\n");
else printf("It is not in the dictionary!\n");
}
else break;
}
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -