二叉树之AVL树
#include <iostream.h>
#include <math.h>;
#include <stdlib.h>; //建立一个整数类型 #define MAXSIZE 512
typedef struct obj_n_t { int obj_key; } obj_node_t; //建立树结点的基本机构
typedef struct tree_n_t { int key; struct tree_n_t *left,*right; int height;
} tree_node_t; //建立堆栈
tree_node_t *stack[MAXSIZE]; //warning!the tree can contain 256 leaves at most!
int i=0; //堆栈计数器 //堆栈清空
void stack_clear()
{
while(i!=0)
{
stack[i-1]=NULL;
i--;
}
}
//堆栈为空
int stack_empty()
{
return(i==0);
}
//入栈函数
int push(tree_node_t *node)
{
if(i<MAXSIZE)
{
stack[i++]=node;
return(0);
}
else
return(-1);
}
//出栈函数
tree_node_t *pop()
{
if(i>0)
return(stack[--i]);
else
return(0);
}
//建立get_node函数,用于动态分配内存空间
tree_node_t *get_node()
{
tree_node_t *tmp;
tmp=(tree_node_t *)malloc(sizeof(tree_node_t));
return(tmp);
}
//建立return_node函数,用于释放内存
void return_node(tree_node_t *free_node)
{
free(free_node);
}
//建立左旋转函数
void left_rotation(tree_node_t *node)
{
tree_node_t *tmp;
int tmp_key;
tmp=node->left;
tmp_key=node->key;
node->left=node->right;
node->key=node->right->key;
node->right=node->left->right;
node->left->right=node->left->left;
node->left->left=tmp;
node->left->key=tmp_key;
}
//建立右旋转函数
void right_rotation(tree_node_t *node)
{
tree_node_t *tmp;
int tmp_key;
tmp=node->right;
tmp_key=node->key;
node->right=node->left;
node->key=node->left->key;
node->left=node->right->left;
node->right->left=node->right->right;
node->right->right=tmp;
node->right->key=tmp_key;
}
int rebalance(tree_node_t *node)
{
int finished=0;
while(!stack_empty()&&!finished)
{
int tmp_height,old_height;
node=pop(); //back to the root along the search path
old_height=node->height;
if(node->left->height-node->right->height==2)
{
if(node->left->left->height-node->right->height==1)
{
right_rotation(node);
node->right->height=node->right->left->height+1;
node->height=node->right->height+1;
}
else
{
left_rotation(node->left);
right_rotation(node);
tmp_height=node->left->left->height;
node->left->height=tmp_height+1;
node->right->height=tmp_height+1;
node->height=tmp_height+2;
}
}
else if(node->left->height-node->right->height==-2)
{
if(node->right->right->height-node->left->height==1)
{
left_rotation(node);
node->left->height=node->left->right->height+1;
node->height=node->left->height+1;
}
else
{
right_rotation(node->right);
left_rotation(node);
tmp_height=node->right->right->height;
node->left->height=tmp_height+1;
node->right->height=tmp_height+1;
node->height=tmp_height+2;
}
}
else
{
if(node->left->height>node->right->height)
node->height=node->left->height+1;
else
node->height=node->right->height+1;
}
if(node->height==old_height)
finished=1;
}
stack_clear();
return(0);
}
//建立creat_tree函数,用于建立一颗空树
tree_node_t *creat_tree()
{
tree_node_t *root;
root=get_node();
root->left=root->right=NULL;
root->height=0;
return(root); //build up an empty tree.the first insert bases on the empty tree.
}
//建立find函数,用于查找一个对象
obj_node_t *find(tree_node_t *tree,int query_key)
{
tree_node_t *tmp;
if(tree->left==NULL)
return(NULL);
else
{
tmp=tree;
while(tmp->right!=NULL)
{
if(query_key<tmp->key)
tmp=tmp->left;
else
tmp=tmp->right;
}
if(tmp->key==query_key)
return((obj_node_t*)tmp->left);
else
return(NULL);
}
}
//建立插入函数
int insert(tree_node_t *tree,obj_node_t *new_obj)
{
tree_node_t *tmp;
int query_key,new_key;
query_key=new_key=new_obj->obj_key;
if(tree->left==NULL)
{
tree->left=(tree_node_t *)new_obj;
tree->key=new_key;
tree->height=0;
tree->right=NULL;
}
else
{
stack_clear();
tmp=tree;
while(tmp->right!=NULL)
{
//use stack to remember the path from root to the position at which the new object should be inserted.
//then after inserting,we can rebalance from the parrent node of the leaf which pointing to new object to the root node.
push(tmp);
if(query_key<tmp->key)
tmp=tmp->left;
else
tmp=tmp->right;
}
if(tmp->key==query_key)
return(-1);
else
{
tree_node_t *old_leaf,*new_leaf;
//It must allocate 2 node space in memory.
//One for the new one,another for the old one.
//the previous node becomes the parrent of the new node.
//when we delete a leaf,it will free two node memory spaces as well.
old_leaf=get_node();
old_leaf->left=tmp->left;
old_leaf->key=tmp->key;
old_leaf->right=NULL;
old_leaf->height=0;
new_leaf=get_node();
new_leaf->left=(tree_node_t *)new_obj;
new_leaf->key=new_key;
new_leaf->right=NULL;
new_leaf->height=0;
if(tmp->key<new_key)
{
tmp->left=old_leaf;
tmp->right=new_leaf;
tmp->key=new_key;
}
else
{
tmp->left=new_leaf;
tmp->right=old_leaf;
}
tmp->height=1;
}
}
rebalance(tmp);
return(0);
}
//建立删除函数
int del(tree_node_t *tree,int key)
{
tree_node_t *tmp,*upper,*other;
if(tree->left==NULL)
return(-1);
else if(tree->right==NULL)
{
if(tree->key==key)
{
tree->left=NULL;
return(0);
}
else
return(-1);
}
else
{
tmp=tree;
stack_clear();
while(tmp->right!=NULL)
{
upper=tmp;
push(upper);
if(key<tmp->key)
{
tmp=upper->left;
other=upper->right;
}
else
{
tmp=upper->right;
other=upper->left;
}
}
if(tmp->key!=key)
return(-1);
else
{
upper->key=other->key;
upper->left=other->left;
upper->right=other->right;
upper->height=upper->height-1;
return_node(tmp);
return_node(other);
rebalance(pop());
//here must pop,then rebalance can run from the parrent of upper,because upper has become a leaf.
return(0);
}
}
}
//建立测试遍历函数
int travel(tree_node_t *tree)
{
stack_clear();
if(tree->left==NULL)
push(tree);
else if(tree->left!=NULL)
{
int m=0;
push(tree);
while(i!=m)
{
if(stack[m]->left!=NULL && stack[m]->right!=NULL)
{
push(stack[m]->left);
push(stack[m]->right);
}
m++;
}
}
return(0);
}
//建立测试函数
int test_structure(tree_node_t *tree)
{
travel(tree);
int state=-1;
while(!stack_empty())
{
--i;
if(stack->right==NULL && stack->height==0) //this statement is leaf,but also contains an empty tree
state=0;
else if(stack->left!=NULL && stack->right!=NULL)
{
if(abs(stack->height-stack->height)<=1)
state=0;
else
{
state=-1;
stack_clear();
}
}
}
stack_clear();
return(state);
}
//建立remove_tree函数
int remove_tree(tree_node_t *tree)
{
travel(tree);
if(stack_empty())
return(-1);
else
{
while(!stack_empty())
{
return_node(pop());
}
return(0);
}
}
void main()
{
tree_node_t *atree=NULL;
obj_node_t obj[256],*f; //MAXSIZE=n(number of leaf)+(n-1) number of node
int n,j=0;
cout<<"Now Let's start this program! There is no tree in memory.\n";
int item;
while(item!=0)
{
cout<<"\nRoot address = "<<atree<<"\n";
cout<<"\n1.Create a tree\n";
cout<<"\n2.Insert a int type object\n";
cout<<"\n3.Test the structure of the tree\n";
cout<<"\n4.Find a object\n";
cout<<"\n6.Delete a object\n";
cout<<"\n7.Remove the Tree\n";
cout<<"\n0.Exit\n";
cout<<"\nPlease select:";
cin>>item;
cout<<"\n\n\n";
switch(item)
{
case 1:
{
atree=creat_tree();
cout<<"\nA new empty tree has been built up!\n";
break;
}
case 2:
{
if(atree!=NULL)
{
while(n!=3458)
{
cout<<"Please insert a new object.\nOnly one object every time(3458 is an end code) : ";
cin>>n;
if(n!=3458)
{
obj[j].obj_key=n;
if(insert(atree,&obj[j])==0)
{
j++;
cout<<"Integer "<<n<<" has been input!\n\n";
}
else
cout<<"\n\nInsert failed!\n\n";
}
}
}
else
cout<<"\n\nNo tree in memory,insert Fail!\n\n";
break;
}
case 3:
{
if(atree!=NULL)
{
n=test_structure(atree);
if(n==-1)
cout<<"\n\nIt's not a correct AVL tree.\n\n";
if(n==0)
cout<<"\n\nIt's a AVL tree\n\n";
}
else
cout<<"\n\nNo tree in memory,Test Fail!\n\n";
break;
}
case 4:
{
if(atree!=NULL)
{
cout<<"\n\nWhat do you want to find? : ";
cin>>n;
f=find(atree,n);
if(f==NULL)
{
cout<<"\n\nSorry,"<<n<<" can't be found!\n\n";
}
else
{
cout<<"\n\nObject "<<f->obj_key<<" has been found!\n\n";
}
}
else
cout<<"\n\nNo tree in memory,Find Fail!\n\n";
break;
}
case 5:
{
if(atree!=NULL)
{
travel(atree);
for(int count=0;count<i;count++)
{
cout<<" "<<stack[count]->key<<",";
}
}
else
cout<<"\n\nNo tree in memory,Travel Fail!\n\n";
break;
}
case 6:
{
if(atree!=NULL)
{
cout<<"\n\nWhich object do you want to delete?\n\n";
cin>>n;
if(del(atree,n)==0)
{
cout<<"\n\n"<<n<<" has been deleted!\n\n";
}
else
cout<<"\n\nNo this object\n\n";
}
else
cout<<"\n\nNo tree in memory,Delete Fail!\n\n";
break;
}
case 7:
{
if(atree!=NULL)
{
remove_tree(atree);
cout<<"\n\nThe Tree has been removed!\n\n";
atree=NULL;
}
else
cout<<"\n\nNo tree in memory,Removing Fail!\n\n";
break;
}
default:
cout<<"\n\nNo this operation!\n\n";
}
n=0;
}
}
二叉树之AVL树的更多相关文章
- 二叉树与AVL树
二叉树 什么是二叉树? 父节点至多只有两个子树的树形结构成为二叉树.如下图所示,图1不是二叉树,图2是一棵二叉树. 图1 普通的树 ...
- 二叉树,AVL树和红黑树
为了接下来能更好的学习TreeMap和TreeSet,讲解一下二叉树,AVL树和红黑树. 1. 二叉查找树 2. AVL树 2.1. 树旋转 2.1.1. 左旋和右旋 2.1.2. 左左,右右,左右, ...
- 二叉树-二叉查找树-AVL树-遍历
一.二叉树 定义:每个节点都不能有多于两个的儿子的树. 二叉树节点声明: struct treeNode { elementType element; treeNode * left; treeNod ...
- python常用算法(5)——树,二叉树与AVL树
1,树 树是一种非常重要的非线性数据结构,直观的看,它是数据元素(在树中称为节点)按分支关系组织起来的结构,很像自然界中树那样.树结构在客观世界中广泛存在,如人类社会的族谱和各种社会组织机构都可用树形 ...
- 5分钟了解二叉树之AVL树
转载请注明出处:https://www.cnblogs.com/morningli/p/16033733.html AVL树是带有平衡条件的二叉查找树,其每个节点的左子树和右子树的高度最多相差1.为了 ...
- 二叉树之AVL树的平衡实现(递归与非递归)
这篇文章用来复习AVL的平衡操作,分别会介绍其旋转操作的递归与非递归实现,但是最终带有插入示例的版本会以递归呈现. 下面这张图绘制了需要旋转操作的8种情况.(我要给做这张图的兄弟一个赞)后面会给出这八 ...
- 04-树4. Root of AVL Tree-平衡查找树AVL树的实现
对于一棵普通的二叉查找树而言,在进行多次的插入或删除后,容易让树失去平衡,导致树的深度不是O(logN),而接近O(N),这样将大大减少对树的查找效率.一种解决办法就是要有一个称为平衡的附加的结构条件 ...
- AVL树和伸展树 -数据结构(C语言实现)
读数据结构与算法分析 AVL树 带有平衡条件的二叉树,通常要求每颗树的左右子树深度差<=1 可以将破坏平衡的插入操作分为四种,最后通过旋转恢复平衡 破坏平衡的插入方式 描述 恢复平衡旋转方式 L ...
- 【数据结构】什么是AVL树
目录 什么是AVL树 1. 什么是AVL树 2. 节点的实现 3. AVL树的调整 3.1 LL旋转 3.2 RR旋转 3.3 RL旋转 3.4 LR旋转 什么是AVL树 二叉查找树的一个局限性就是有 ...
随机推荐
- Python爬虫与一汽项目【综述】
项目来源 这个爬虫项目是 去年实验室去一汽后的第一个项目(基本交工,现在处于更新维护阶段).内容大概是,获取到全国31个省份政府的关于汽车的招标公告,再用图形界面的方式展示爬虫内容.在完成政府招标采购 ...
- 当namenode启动不了时
重新格式即可,注意格式化前要将临时目录下的文件全部删除
- better-scroll 中的img标签无法触发长按保存菜单
better-scroll 默认禁用的多数标签的默认行为,启用默认行为需加如下属性 preventDefaultException: { tagName: /^(IMG|INPUT|TEXTAREA| ...
- Linux服务器 XAMPP后添加PHP和MYSQL环境变量
编辑/etc/profile文件 在文件末尾添加两行代码 vi /etc/profile CentOS: PATH=$PATH:/opt/lampp/bin export PATH Ubuntu: e ...
- Android系统应用Mms之Sms短信发送流程(Mms应用部分)二
1. 新建一条短信, 在发送短信之前, 首先创建的是一个会话Conversation, 以后所有与该接收人(一个或多个接收人)的消息交互, 都在该会话Conversation中. ComposeMes ...
- Mac OS 挂载 EFI 引导分区
正如Windows下的EFI分区一样在资源管理器中默认不显示EFI引导分区(即ESP分区),Mac OS也是如此,为了安全嘛,不让用户随意操作. 那么怎么挂载显示出来呢? 命令转自 https://b ...
- 9_grep及正则表达式
文本查找的需要grep,egrep,fgrep grep:Global Research.根据模式,去搜索文本,并将符合模式的文本行显示出来Pattern:文本字符和正则表达式的元字符组合而成匹配条件 ...
- react native 项目使用 expo 二维码扫描失败
今天学习react native,需使用expo在移动端进行调试. npm start 运行项目后,使用expo扫描二维码,始终没有反应.于是决定采用这个方法: 连上手机打开usb调试后,按下‘a’, ...
- Maven安装环境变量配置教程(带图)
Maven安装配置环境变量教程 什么是maven:Maven是一个软件项目管理和综合工具.基于项目对象模型(POM)的概念,Maven可以从一个中心资料片管理项目构建,报告和文件. (简单来说就是,安 ...
- vue--简化项目逻辑属性
computed属性对数据变化是实时响应的 因此当项目中某个数值发生变化,并且要在别的地方引用这个数值时,computed即可派上用场 来看一个例子: html部分: <div id=" ...