AVL树(附加序列化和反序列化功能)

/*************************************************************************
    > File Name: AVLTree.c
    > Author: guoximing
    > Mail: wuxinliulei@gmail.com 
    > Created Time: 2014年03月24日 星期一 23时31分49秒
 ************************************************************************/

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct node{
	int data;
	int bf;		//balance flag 平衡因子的缩写
	struct node *lchild , *rchild;
}BitNode,*BiTree;

int array[100][2];
//之所以要用** 是因为参数传递情况下 要更改指针指向内容的需要 地址传递
//右调整:对以p为根的二叉树右旋   该树 左子树深度大于右子树
//调整后: 根节点为p节点的左孩子,同时将p节点左孩子的右孩子接在p节点的左孩子
//然后将p节点作为新根的右孩子
void rightRotate(BiTree *p){
	BiTree L = (*p)->lchild;
	(*p)->lchild = L->rchild;
	L->rchild = (*p);
	*p = L;
}

//左调整:同理,只是将以p为根的二叉树左旋,该树的右子树深度大于左子树
//调整好:根节点为p的右孩子,同时将p节点的右孩子的左孩子加在p节点的右孩子
//然后将p节点作为新的根节点的左孩子

void leftRotate(BiTree *p){
	BiTree R = (*p)->rchild;
	(*p)->rchild = R->lchild;
	R->lchild = (*p);
	*p = R;
}

//处理LL 和LR 两种类型的旋状  LL型旋转只需要右旋一次 LR型又分三种情况
//但是LR型的处理方法都是先根据根节点的左孩子左旋转一次变为LL型然后再又旋转
void LL_LRBalance(BiTree *p){
    BiTree L = (*p)->lchild;
	BiTree R;
	switch(L->bf){
		case 1://若为1,则表示新节点插在左孩子的左子树上,为LL型
			(*p)->bf = L->bf = 0;
			rightRotate(p);
			break;
		case -1://若为-1,则表示插入到左孩子的右子树上,为LR型
			R = L->rchild;
			switch(R->bf){
				case 0:
					(*p)->bf = L->bf = 0; break;
				case 1:
					(*p)->bf = -1; R->bf = L->bf = 0; break;
				case -1:
					(*p)->bf = R->bf = 0; L->bf = 1; break;

			}
			leftRotate(&((*p)->lchild));
			rightRotate(p);
			break;
	}
}


void RR_RLBalance(BiTree *p){
	BiTree R = (*p)->rchild;
	BiTree L;
	switch(R->bf){
		case -1:
			(*p)->bf = R->bf = 0;
			leftRotate(p);
			break;
		case 1:
		    L = R->lchild;
			switch(L->bf){
				case 0: (*p)->bf = R->bf = 0; break;
				case 1: (*p)->bf = L->bf =0; R->bf = -1; break;
				case -1: (*p)->bf = 1; L->bf = R->bf = 0; break;
			}
			rightRotate(&(*p)->rchild);
			leftRotate(p);
			break;
	}
}

//输入参数 p为根节点指针 key为被插入的关键字 chain表示插入节点后是否引起调整
//初使为0 
int insertAVL(BiTree *p,int key,int * chain){
	//表示未在树中找到key,直接生成新的节点,用于存储key
	if((*p) == NULL){
		(*p) = (BitNode *) malloc (sizeof(BitNode));
		(*p)->bf = 0;
		(*p)->lchild = (*p)->rchild = NULL;
		(*p)->data = key;
		*chain = 1;
	}
    else{
		//表示树中有相同的关键字,表示插入失败
		if(key == (*p)->data){
			*chain = 0; 
			return 0;
		}
		//表示插入值小于当前的结点key,则递归在当前结点的左子树插入
		if(key < (*p)->data){
			//如果插入不成功
			if(!insertAVL(&(*p)->lchild,key,chain)) return 0;

			if(*chain){
				//此处在递归调用退出时调用,表示新节点在p左子树插入
				switch((*p)->bf){
					
					//if p的平衡因子为0 那么在其左子树插入,他将变为1
					//树的高度增加,会产生平衡引子的变化  但不用调整
					case 0:(*p)->bf = 1; *chain = 1; break;
					
					//if p的平衡因子为1,那么在其左子树插入,平衡被破坏,
					//需要进行调整,调整之后,不会导致树的高度增加,则结束

					case 1: LL_LRBalance(p); *chain = 0; break;

					//if p的平衡因子为-1,那么在其左孩子插入节点,则bf变为0,
					//树的平衡没有破坏,反应结束
					case -1:(*p)->bf = 0; chain = 0; break;
				}
			}
		}
	  else
	  {
		if(!insertAVL(&(*p)->rchild,key,chain)) return 0;
		if(*chain){
			{
				switch((*p)->bf){
					case 0: (*p)->bf = -1; chain = 1; break;
				    case 1: (*p)->bf = 0; chain = 0; break;
					case -1:RR_RLBalance(p); chain = 0; break;
				}
			}
		}
	  }
	}
	return 1;
}

void InOrder(BiTree t){
    if(t != NULL){
		InOrder(t->lchild);
		printf("%d  ",t->data);
		InOrder(t->rchild);
	}
}

void serialize(BiTree t,int index){
	if(t == NULL)
	{
		return;
	}
	array[index][0] = t->data; 
    array[index][1] = t->bf;
	serialize(t->lchild,index*2);
	serialize(t->rchild,index*2+1);
}

void unSerialize(BiTree *p,int index){
    if(array[index][1] == 100){
		return ;
	}

    (*p) = (BitNode *)malloc(sizeof(BitNode));
    
	(*p)->data = array[index][0];
	(*p)->bf   = array[index][1];
	(*p)->lchild = NULL;
	(*p)->rchild = NULL;

	unSerialize(&(*p)->lchild,index*2);
	unSerialize(&(*p)->rchild,index*2+1);
}

void init(){
	int n;
    for(n=0;n<100;n++){
	    array[n][0] = 100;
		array[n][1] = 100;
	}
}

int main(){
	int i;
	int a[10] = {3,2,1,4,5,6,9,7,8,0};
	BiTree T = NULL;
	int chain;
	for(i=0;i<10;i++){
		insertAVL(&T,a[i],&chain);
	}
	printf("中序遍历的结果:");
	InOrder(T);
	printf("\n");

    //memset(array,100,sizeof(array));这是错误的
    init();

	serialize(T,1);
 
	T = NULL;
    
	FILE *f = fopen("./file","w+");
	if(f == NULL)
	{
		printf("打开文件失败!");
	}
    int n ;
	printf("存储到文件当中的数组内容如下:\n");
    for(n=1;n<100;n++)
	{
		        //fprintf(f,"%d%d",array[n][0],array[n][1]);
		fwrite(&array[n][0],sizeof(int),1,f);
		fwrite(&array[n][1],sizeof(int),1,f);
		printf("%d %d ",array[n][0],array[n][1]);
	}
    
	fclose(f);

    init();
    
	printf("\n重新读取文件中的数据初始化数组如下:\n");
	f = fopen("./file","rb");
    for(n=1;n<100;n++)
	{
				//fscanf(f,"%d%d",&array[n][0],&array[n][1]);
		fread(&array[n][0],sizeof(int),1,f);
		fread(&array[n][1],sizeof(int),1,f);
	}

	
    for(n=1;n<100;n++)
	{
		printf("%d %d ",array[n][0],array[n][1]);
	}

	unSerialize(&T,1);

    printf("\n反序列化之后的中序遍历:");
	InOrder(T);
    
	printf("\n");
	int test;
	printf("请输入你想插入的数据:");
    scanf("%d",&test);
	insertAVL(&T,test,&chain);	
	printf("中序遍历的结果:");
	InOrder(T);
	printf("\n");
}

    原文作者:AVL树
    原文地址: https://blog.csdn.net/wuxinliulei/article/details/22693825
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞