高度为 h 的 AVL 树,节点数 N 最多2^h − 1; 最少N(h)=N(h− 1) +N(h− 2) + 1。
最少节点数n 如以斐波那契数列可以用数学归纳法证明:
即:
N(0) = 0 (表示 AVL Tree 高度为0的节点总数)
N(1) = 1 (表示 AVL Tree 高度为1的节点总数)
N(2) = 2 (表示 AVL Tree 高度为2的节点总数)
N(h)=N(h− 1) +N(h− 2) + 1 (表示 AVL Tree 高度为h的节点总数)
 
 

#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树的更多相关文章

  1. 二叉树与AVL树

    二叉树 什么是二叉树? 父节点至多只有两个子树的树形结构成为二叉树.如下图所示,图1不是二叉树,图2是一棵二叉树. 图1 普通的树                                    ...

  2. 二叉树,AVL树和红黑树

    为了接下来能更好的学习TreeMap和TreeSet,讲解一下二叉树,AVL树和红黑树. 1. 二叉查找树 2. AVL树 2.1. 树旋转 2.1.1. 左旋和右旋 2.1.2. 左左,右右,左右, ...

  3. 二叉树-二叉查找树-AVL树-遍历

    一.二叉树 定义:每个节点都不能有多于两个的儿子的树. 二叉树节点声明: struct treeNode { elementType element; treeNode * left; treeNod ...

  4. python常用算法(5)——树,二叉树与AVL树

    1,树 树是一种非常重要的非线性数据结构,直观的看,它是数据元素(在树中称为节点)按分支关系组织起来的结构,很像自然界中树那样.树结构在客观世界中广泛存在,如人类社会的族谱和各种社会组织机构都可用树形 ...

  5. 5分钟了解二叉树之AVL树

    转载请注明出处:https://www.cnblogs.com/morningli/p/16033733.html AVL树是带有平衡条件的二叉查找树,其每个节点的左子树和右子树的高度最多相差1.为了 ...

  6. 二叉树之AVL树的平衡实现(递归与非递归)

    这篇文章用来复习AVL的平衡操作,分别会介绍其旋转操作的递归与非递归实现,但是最终带有插入示例的版本会以递归呈现. 下面这张图绘制了需要旋转操作的8种情况.(我要给做这张图的兄弟一个赞)后面会给出这八 ...

  7. 04-树4. Root of AVL Tree-平衡查找树AVL树的实现

    对于一棵普通的二叉查找树而言,在进行多次的插入或删除后,容易让树失去平衡,导致树的深度不是O(logN),而接近O(N),这样将大大减少对树的查找效率.一种解决办法就是要有一个称为平衡的附加的结构条件 ...

  8. AVL树和伸展树 -数据结构(C语言实现)

    读数据结构与算法分析 AVL树 带有平衡条件的二叉树,通常要求每颗树的左右子树深度差<=1 可以将破坏平衡的插入操作分为四种,最后通过旋转恢复平衡 破坏平衡的插入方式 描述 恢复平衡旋转方式 L ...

  9. 【数据结构】什么是AVL树

    目录 什么是AVL树 1. 什么是AVL树 2. 节点的实现 3. AVL树的调整 3.1 LL旋转 3.2 RR旋转 3.3 RL旋转 3.4 LR旋转 什么是AVL树 二叉查找树的一个局限性就是有 ...

随机推荐

  1. TeamCity 创建docker构建步骤

    1 dockerfile source 选择dockerfile文件的路径,一共有三种方式: 1.1.1 file content 这种方式是在线写dockerfile文件. 其在进行创建的时候会在 ...

  2. 代码修改WinForm datagridview 样式 及数据绑定

    #region 表格设置 /// <summary> /// 调整表格 /// </summary> /// <param name="dataGrid&quo ...

  3. 微信省市区 Mysql数据库

    $jsonStr = '[{"cities":["\u5b89\u5e86","\u868c\u57e0","\u4eb3\u5d ...

  4. MySQL高性能优化规范建议,速度收藏

    数据库命令规范 •所有数据库对象名称必须使用小写字母并用下划线分割•所有数据库对象名称禁止使用 MySQL 保留关键字(如果表名中包含关键字查询时,需要将其用单引号括起来)•数据库对象的命名要能做到见 ...

  5. [Python数据挖掘]第5章、挖掘建模(下)

    四.关联规则 Apriori算法代码(被调函数部分没怎么看懂) from __future__ import print_function import pandas as pd #自定义连接函数,用 ...

  6. CefSharp浏览器网页中文语言设置

    设置浏览器语言而非cef语言 ChromiumWebBrowser browser = new ChromiumWebBrowser(url); BrowserSettings browserSett ...

  7. 使用guava过期map

    最近需要将微信的accesstoken保存到缓存里面,防止重复请求微信接口获取token,造成token请求次数超标,其实随便一个缓存都可以轻松解决,但是现有的环境中没有redis,没有memcahe ...

  8. ORACLE中INSERT插入多条数据

    insert ALL into u_role_permission(rid,pid) values (4,12) into u_role_permission(rid,pid) values (3,4 ...

  9. testng.xml中groups标签使用

    XML配置如下: <?xml version="1.0" encoding="UTF-8"?> <suite name="suite ...

  10. [原][杂谈]如果人类的末日:"天网"出现

    本文由南水之源在2019年3月21日发布,转载需声明原作者 本文仅为一次基于科技发展与科幻小说的幻想,如果天网真的出现,请不要参考这篇逻辑破败的推论. 参考: 天网(Skynet),是电影<终结 ...