平衡二叉树代码 栈实现

平衡二叉树

定义:

平衡二叉搜索树(Self-balancing binary search tree)又被称为AVL树(有别于AVL算法),且具有以下性质:它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。平衡二叉树的常用实现方法有红黑树、AVL、替罪羊树、Treap、伸展树等。 最小二叉平衡树的节点总数的公式如下 F(n)=F(n-1)+F(n-2)+1 这个类似于一个递归的数列,可以参考Fibonacci(斐波那契)数列,1是根节点,F(n-1)是左子树的节点数量,F(n-2)是右子树的节点数量。

其中最艰难的是插入和删除,这里提供两种方法。

测试函数:

#include <stdio.h>
#include <stdlib.h>
#include "avltree.h"

void show_menu(void){
	printf("*******平衡二叉排序(AVL树功能测试**********\n");
	printf("**1. 插入元素 \n");
	printf("**2. 删除元素 \n");
//	printf("**3. 查找某元素是否在树中 \n");
	printf("**4. 树是否为空 \n");
	printf("**5. 树中元素个数 \n");
	printf("**6. 树的高度 \n");
	printf("**7. 树的先序遍历 \n");
	printf("**8. 树的中序遍历 \n");
	printf("**9. 树的后序遍历 \n");
//	printf("**10.树的层序遍历 \n");
	printf("**11. 清空树 \n");
	printf("**0. 退出 \n");
	printf(">>>>");
}

void travel(int n){
	printf("%d ",n);
}

void test_bin_tree(void){
	AVLTree tree = NULL;
	avl_tree_init(&tree);
	while(true){
		show_menu();
		int opt = 0;
		int elem = 0;
		int ret = 0;
		bool f = true;
		scanf("%d",&opt);
		switch(opt){
			case 1:
				printf("请输入要插入二叉排序树中的元素:");
				scanf("%d",&elem);
				ret = avl_tree_insert(&tree,elem);
				if(ret == 0){
					printf("插入成功!\n");
				}else{
					if(ret == -1){
						printf("树中已有该元素,插入失败!\n");
					}else{
						printf("插入失败!内存问题!\n");
					}
				}
				break;
			case 2:
				printf("请输入要删除的元素:");
				scanf("%d",&elem);
				ret = avl_tree_delete(&tree,elem);
				if(ret == 0){
					printf("删除成功!\n");
				}else{
					printf("删除失败!树中没有该元素!\n");
				}
				break;
			case 3:
//				printf("请输入要查找树中是否存在的元素:");
//				scanf("%d",&elem);
//				if(val_tree_contains(tree,elem)){
//					printf("树中存在该元素!\n");
//				}else{
//					printf("树中没有该元素!\n");
//				}
				break;
			case 4:
				avl_tree_empty(tree)?puts("空空如也!\n"):puts("树中有元素!\n");
			case 5:
				printf("树中元素个数:%u\n",avl_tree_size(tree));
			case 6:
				printf("树的高度为:%u\n",avl_tree_hight(tree));
				break;
			case 7:
				avl_tree_front_travel(tree,travel);
				printf("\n");
			case 8:
				avl_tree_mid_travel(tree,travel);
				printf("\n");
			case 9:
				avl_tree_back_travel(tree,travel);
				printf("\n");
			case 10:
				//avl_tree_layer_travel(tree,travel);
				printf("\n");
				break;
			case 11:
				avl_tree_clear(&tree);
				break;
			case 0:
				avl_tree_destroy(&tree);
				return; 
		}
	}
}

int main(int argc, char *argv[]) {
	test_bin_tree();
	return 0;
}

方法一:非栈的形式

#include "avltree.h"
/*
typedef int ETYPE;
typedef struct AVLNode{
	ETYPE elem;
	struct AVLNode *lchild,*rchild;
	size_t hight;   //结点所在高度 
	//int balance;  //平衡因子 
}AVLNode,*AVLTree;
*/

#define HIGHT(node) (node==NULL?0:node->hight)
#define REHIGHT(node) (HIGHT(node->lchild)>HIGHT(node->rchild)?HIGHT(node->lchild)+1:HIGHT(node->rchild)+1)

void avl_tree_init(AVLTree *proot){
	*proot = NULL; 
}
bool avl_tree_empty(AVLTree root){
	return root == NULL;
}
size_t avl_tree_size(AVLTree root){
	if(root==NULL)
		return 0;
	return 1+avl_tree_size(root->lchild)+avl_tree_size(root->rchild);
}
size_t avl_tree_hight(AVLTree root){
	return root==NULL?0:root->hight;
}

static struct AVLNode *avl_tree_create_node(ETYPE elem){
	struct AVLNode *node = malloc(sizeof(struct AVLNode));
	if(node!=NULL){
		node->elem = elem;
		node->lchild = NULL;
		node->rchild = NULL;
		node->hight = 1;
	}
	return node;
}
/*
          |                                  |
		node                               left 
	    /  \                              /   \
    left    right  -->node进行右旋      ll     node
    / \                                        /  \
   ll  lr                                     lr   right
*/


static struct AVLNode *LL_rotation(struct AVLNode *node){
	struct AVLNode *left = node->lchild;
	node->lchild = left->rchild;
	left->rchild = node;
	node->hight = REHIGHT(node);
	left->hight = REHIGHT(left);
	return left;
}

/*
        |                                 |
       node                             right
      /    \                            /   \
    left   right          左旋        node   rr
           / \                        /  \
          rl  rr                    left  rl
*/



static struct AVLNode *RR_rotation(struct AVLNode *node){
	struct AVLNode *right = node->rchild;
	node->rchild = right->lchild; 
	right->lchild = node;
	node->hight = REHIGHT(node);
	right->hight = REHIGHT(right);
	return right;
}
/*
          |
         node
        /   \
      left   right
      / \
    ll  lr
*/

static struct AVLNode *LR_rotation(struct AVLNode *node){
	node->lchild = RR_rotation(node->lchild);
	return LL_rotation(node); 
}


/*
          |
         node
        /   \
      left   right
             / \
            rl  rr
*/
static struct AVLNode *RL_rotation(struct AVLNode *node){
	node->rchild = LL_rotation(node->rchild);
	return RR_rotation(node);
}

static void avl_tree_inset_repair(AVLTree *proot){
	struct AVLNode *node = *proot;
	int bn = HIGHT(node->lchild) - HIGHT(node->rchild);
	if(bn==2){//左高 
		int lbn = HIGHT(node->lchild->lchild) - HIGHT(node->lchild->rchild);
		if(lbn==1){
			*proot = LL_rotation(node);//对node结点进行右旋   LL 
		}else{//lbn==-1
			*proot = LR_rotation(node);//LR
		}
	}else if(bn==-2){//右高 
		int rbn = HIGHT(node->rchild->lchild) - HIGHT(node->rchild->rchild);
		if(rbn==-1){
			*proot = RR_rotation(node);//RR
		}else{
			*proot = RL_rotation(node);//RL
		}
	}
}
int avl_tree_insert(AVLTree *proot,ETYPE elem){
	//先把结点插入进去   如果失去平衡进行调整(旋转)   递归形式 
	if(*proot == NULL){
		*proot = avl_tree_create_node(elem);
		if(*proot == NULL){
			return -2;
		}
		return 0;
	}
	int ret = 0;
	if(elem < (*proot)->elem){
		ret = avl_tree_insert(&(*proot)->lchild,elem);
	}else if(elem > (*proot)->elem){
		ret = avl_tree_insert(&(*proot)->rchild,elem);
	}else{
		return -1;
	}
	if(ret == 0){//插入成功  可能失衡  需要调整 
		avl_tree_inset_repair(proot); 
		(*proot)->hight = REHIGHT((*proot));
	}
	return ret;
}


int avl_tree_delete(AVLTree *proot,ETYPE elem){
	if(*proot == NULL)
	{
		return -1;
	} 
	int ret = 0;
	if(elem = (*proot)->elem)
	{
	 	struct AVLNode *node = *proot;
	 	if(node->lchild != NULL && node->rchild != NULL)
	 	{
	 		for(node = node->lchild;node->rchild!=NULL;node = node->rchild);
	 		(*proot)->elem = node->elem;
	 		//去删除右子树中的最大值 
	 		ret = avl_tree_delete(&(*proot)->lchild,node->elem);//必须用递归调用删除 
		}
		else
		{
			*proot = node->lchild!=NULL?node->lchild:node->rchild;
			free(node);
			return 0; 
		}
	}
	if(elem < (*proot)->elem)
	{
	 	ret = avl_tree_delete(&(*proot)->lchild,elem);
	}
	else
	{
	 	ret = avl_tree_delete(&(*proot)->rchild,elem);
	}
	if(ret == 0)
	{
	 	avl_tree_inset_repair(proot); 
		(*proot)->hight = REHIGHT((*proot));
	}
}

void avl_tree_front_travel(AVLTree root,void (*travel)(ETYPE)){
	if(root!=NULL){
		travel(root->elem);
		avl_tree_front_travel(root->lchild,travel);
		avl_tree_front_travel(root->rchild,travel);
	}
}
void avl_tree_mid_travel(AVLTree root,void (*travel)(ETYPE)){
	if(root!=NULL){
		avl_tree_mid_travel(root->lchild,travel);
		travel(root->elem);
		avl_tree_mid_travel(root->rchild,travel);
	}
}
void avl_tree_back_travel(AVLTree root,void (*travel)(ETYPE)){
	if(root!=NULL){
		avl_tree_back_travel(root->lchild,travel);
		avl_tree_back_travel(root->rchild,travel);
		travel(root->elem);
	}	
}
void avl_tree_clear(AVLTree *proot){
	if(*proot!=NULL){
		avl_tree_clear(&(*proot)->lchild);
		avl_tree_clear(&(*proot)->rchild);
		free(*proot);
		*proot = NULL;
	}
}
void avl_tree_destroy(AVLTree *proot){
	avl_tree_clear(proot);
}

方法二:栈实现

首先给出定义一个栈

#include "stack.h"

/*
typedef struct AVLNode ** ET;

typedef struct Stack{
	ET *data;
	size_t cap;
	size_t size; 
}Stack;
*/ 
int stack_init(Stack *ps,size_t cap){
	ps->data = malloc(sizeof(ET)*cap);
	if(ps->data == NULL){
		return -1;
	}
	ps->cap = cap;
	ps->size = 0;
}

bool stack_empty(Stack *ps){
	return ps->size == 0;
}
bool stack_full(Stack *ps){
	return ps->size == ps->cap;
}
int stack_push(Stack *ps,ET data){
	if(stack_full(ps))
		return -1;
	ps->data[ps->size++] = data;
	return 0;
}
ET stack_pop(Stack *ps){//给自己用,栈空时自己不用调用
	return ps->data[--ps->size];
}
void stack_destroy(Stack *ps){
	free(ps->data);
}

栈实现代码

#include "avltree.h"
#include "stack.h"

/*
typedef int ETYPE;
typedef struct AVLNode{
	ETYPE elem;
	int hight;
	struct AVLNode *lchild;
	struct AVLNode *rchild;
}AVLNode,*AVLTree;
*/ 


//插入的结点作为叶子结点 
static struct AVLNode *avl_tree_create_node(ETYPE elem){
	struct AVLNode *node = (struct AVLNode *)malloc(sizeof(struct AVLNode));
	if(node!=NULL){
		node->elem = elem;
		node->hight = 1;
		node->lchild = NULL;
		node->rchild = NULL;
	}
	return node;
}


#define HIGHT(node) (node==NULL?0:node->hight)
#define REHIGHT(node) (HIGHT(node->lchild)>HIGHT(node->rchild)?HIGHT(node->lchild)+1:HIGHT(node->rchild)+1)
enum BALANCE{LL=2,RR=-2}; 
/*
	     |                                           |
	   node                                        left 
	   /  \            node结点进行右旋           /    \
	left  right                                  ll    node
	/ \                                                /  \
   ll  lr                                             lr   right
*/
static struct AVLNode *LL_rotate(AVLNode *node){
	struct AVLNode *left = node->lchild;
	node->lchild = left->rchild;
	left->rchild = node;
	node->hight = REHIGHT(node);
	left->hight = REHIGHT(left);
	return left;
}
/*
         |                                                |
       node                                             right 
       /  \                   node结点进行左旋          /   \
     left  right                                      node   rr
            / \                                       /  \
           rl  rr                                   left  rl
*/
static struct AVLNode *RR_rotate(AVLNode *node){
	struct AVLNode *right = node->rchild;
	node->rchild = right->lchild;
	right->lchild = node;
	node->hight = REHIGHT(node);
	right->hight = REHIGHT(right);
	return right;
}
/* 
         |                              |                                   |
       node                            node                                lr  
       /  \                            /   \                              /   \
	left   right    --left左旋        lr   right       node进行右旋      left  node
	/  \                             /                                   /       \
   ll   lr                          left                               ll        right
                                    /
                                  ll
*/
static struct AVLNode *LR_rotate(AVLNode *node){
	node->lchild = RR_rotate(node->lchild);
	return LL_rotate(node);
}
/* 
         |                              |                                   |
       node                            node                                 rl  
       /  \                            /   \                              /   \
	left  right    --right右旋       left   rl       node进行左旋       node   right
           /  \                              \                           /       \
          rl  rr                             right                     left       rr
                                                \
                                                rr   
*/
static struct AVLNode *RL_rotate(AVLNode *node){
	node->rchild = LL_rotate(node->rchild);
	return RR_rotate(node);
}



static void avl_tree_repair(AVLTree *proot){
	int lh = HIGHT((*proot)->lchild);
	int rh = HIGHT((*proot)->rchild);
	if(lh-rh==LL){
		struct AVLNode *left = (*proot)->lchild;
		int llh = HIGHT(left->lchild);
		int lrh = HIGHT(left->rchild);
		if(llh>=lrh){//LL 
			*proot = LL_rotate(*proot);
		}else{//LR
			*proot = LR_rotate(*proot);
		}
	}else if(lh-rh==RR){
		struct AVLNode *right = (*proot)->rchild;
		int rlh = HIGHT(right->lchild);
		int rrh = HIGHT(right->rchild);
		if(rlh>rrh){//RL
			*proot = RL_rotate(*proot);
		}else{//RR
			*proot = RR_rotate(*proot);
		}
	}
}

int avl_tree_insert(AVLTree *proot,ETYPE elem){
	Stack s;
	stack_init(&s,avl_tree_size(*proot)+1);
	while(*proot != NULL){
		stack_push(&s,proot);
		if(elem < (*proot)->elem){
			proot = &(*proot)->lchild;
		}else if(elem > (*proot)->elem){
			proot = &(*proot)->rchild;
		}else{
			stack_destroy(&s);
			return -1;
		}
	}
	*proot = avl_tree_create_node(elem);
	if(*proot == NULL){
		stack_destroy(&s);
		return -2;
	}
	while(!stack_empty(&s)){
		proot = stack_pop(&s);
		avl_tree_repair(proot);
		(*proot)->hight = REHIGHT((*proot)); 
	}
	stack_destroy(&s); 
	return 0;
}
/*
int avl_tree_insert(AVLTree *proot,ETYPE elem){
	//用栈保存比较的每一个结点   插入成功之后  取出栈中所有结点 依次调整高度 如果失衡进行调整
	if(*proot == NULL){
		*proot = avl_tree_create_node(elem);
		if(*proot == NULL){
			return -2;//申请内存失败 
		} 
		return 0;//插入成功    return *proot == NULL ? -2 : 0; 
	} 
	int ret = 0;
	if(elem < (*proot)->elem){
		ret = avl_tree_insert(&(*proot)->lchild,elem);
	}else if(elem > (*proot)->elem){
		ret = avl_tree_insert(&(*proot)->rchild,elem);
	}else{
		return -1;//插入相同的元素  直接失败 
	}
	if(ret == 0){//插入成功  修复平衡  调整高度 
		avl_tree_repair(proot);
		(*proot)->hight = REHIGHT((*proot)); 
	}
	return ret;
}
*/
int avl_tree_delete(AVLTree *proot,ETYPE elem){
	Stack s;
	stack_init(&s,avl_tree_size(*proot)+1);
	while(*proot != NULL){	
		if(elem == (*proot)->elem){
			break; 
		}else if(elem < (*proot)->elem){
			proot = &(*proot)->lchild;
		}else{
			proot = &(*proot)->rchild;
		}
		stack_push(&s,proot);
	}
	if(*proot == NULL){
		stack_destroy(&s);
		return -1;
	}
	struct AVLNode *node = *proot;
	if(node->lchild!=NULL && node->rchild!=NULL){
		//struct AVLNode *left = node->lchild;
		for(proot = &(*proot)->lchild; (*proot)->rchild!=NULL;proot = &(*proot)->rchild){
			stack_push(&s,proot);
		}
		stack_pop(&s);//*proot == NULL
		node->elem = (*proot)->elem;
		node = *proot;
	}
	*proot = node->lchild!=NULL?node->lchild:node->rchild;
	free(node);
	
	while(!stack_empty(&s)){
		proot = stack_pop(&s);
		avl_tree_repair(proot);
		(*proot)->hight = REHIGHT((*proot));		
	}
	stack_destroy(&s);
	return 0;
}

/*
int avl_tree_delete(AVLTree *proot,ETYPE elem){
	if(*proot == NULL){
		return -1;
	}
	int ret = 0;
	if(elem == (*proot)->elem){
		struct AVLNode *node = *proot;
		if(node->lchild!=NULL && node->rchild!=NULL){
			for(node = node->lchild;node->rchild!=NULL;node=node->rchild);
			(*proot)->elem = node->elem;
			//去删除右子树中的最大值 
			ret = avl_tree_delete(&(*proot)->lchild,node->elem);//必须用递归调用去删除 
		}else{
			*proot = node->lchild!=NULL?node->lchild:node->rchild;
			free(node);
			return 0;
		}
	}
	if(elem < (*proot)->elem){
		ret = avl_tree_delete(&(*proot)->lchild,elem);
	}else{
		ret = avl_tree_delete(&(*proot)->rchild,elem);
	}
	if(ret == 0){
		avl_tree_repair(proot);
		(*proot)->hight = REHIGHT((*proot)); 
	}
	return ret;
}
*/

void avl_tree_init(AVLTree *proot){
	*proot = NULL; 
}
bool avl_tree_empty(AVLTree root){
	return root == NULL;
}
size_t avl_tree_size(AVLTree root){
	if(root==NULL)
		return 0;
	return 1+avl_tree_size(root->lchild)+avl_tree_size(root->rchild);
}
size_t avl_tree_hight(AVLTree root){
	return root==NULL?0:root->hight;
}


void avl_tree_front_travel(AVLTree root,void (*travel)(ETYPE)){
	if(root!=NULL){
		travel(root->elem);
		avl_tree_front_travel(root->lchild,travel);
		avl_tree_front_travel(root->rchild,travel);
	}
}
void avl_tree_mid_travel(AVLTree root,void (*travel)(ETYPE)){
	if(root!=NULL){
		avl_tree_mid_travel(root->lchild,travel);
		travel(root->elem);
		avl_tree_mid_travel(root->rchild,travel);
	}
}
void avl_tree_back_travel(AVLTree root,void (*travel)(ETYPE)){
	if(root!=NULL){
		avl_tree_back_travel(root->lchild,travel);
		avl_tree_back_travel(root->rchild,travel);
		travel(root->elem);
	}	
}
void avl_tree_clear(AVLTree *proot){
	if(*proot!=NULL){
		avl_tree_clear(&(*proot)->lchild);
		avl_tree_clear(&(*proot)->rchild);
		free(*proot);
		*proot = NULL;
	}
}
void avl_tree_destroy(AVLTree *proot){
	avl_tree_clear(proot);
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
根据引用\[1\]和引用\[3\]的内容,构建一个平衡二叉树的过程包括以下几个步骤:输入结点、寻找结点插入位置、插入结点、判断树是否平衡、调整树的平衡。 首先,通过输入结点的值,从根结点开始逐一比较,如果大于根结点的值,则继续在根结点的右子树中递归寻找插入位置;如果小于根结点的值,则在根结点的左子树中递归寻找插入位置。当找到插入位置时,创建一个新的结点并将其插入。 接下来,利用递归的特点,从距离新插入结点最近的结点开始,从下往上进行平衡的检测。如果发现树的某个结点不平衡,即左右子树的高度差超过1,就进行旋转操作来调整树的平衡。 根据引用\[2\]的内容,旋转操作时需要重新申请一个类型为AVLTree的结点B,并将旋转结果复制到B中。这是为了避免在原有平衡树上进行修改,从而导致错误和重复的部分。 因此,练习4.2中平衡二叉树的根可以通过插入函数Insert来实现,具体代码可以参考引用\[3\]中的实现思路。在插入过程中,每次新申请的结点都需要插入,否则将不会有任何改变。 #### 引用[.reference_title] - *1* *2* *3* [PTA练习4.2 平衡二叉树的根 (25 分)](https://blog.csdn.net/Mai___/article/details/119139360)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

HOVL_C++

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值