方法:
1、首先启动excel 2010,运行该程序,执行文件-打开命令,打开事先准备的好一份表格数据。
2、接着选择单元b2,执行数据菜单命令,从中选择数据有效性选项,d出数据有效性对话框。
3、切换到设置选项卡,允许设置为序列,点击来源右下角d出对话框,切换到sheet2,选择姓名列,然后点击确定按钮。
4、选择单元格b3,输入公式=VLOOKUP(B2,Sheet2!$A:$G,MATCH(Sheet1!A3,Sheet2!$1:$1,0),0)后,点击确定按钮,这个时候就会看到相应的信息了。
5、接着选择单元格,b2,按一下f4,变成绝对引用,在接着把鼠标放在b2右下角出现黑色十字后双击进行填充即可。
6、选择vl公式复制粘贴到单元格d2中,然后修改公式中相应的参数,接着进行填充其他选项即可完成。
7、随便找一个单元格输入=INDEX(Sheet2!$H:$H,MATCH(Sheet1!$B$2,Sheet2!$A:$A,0)),执行菜单公式命令,从中找到定义名称按钮,在d出的对话框中输入名称为照片,点击确定按钮。
8、执行公式-名称管理器命令,在d出的名称管理器的对话框中就会看到刚才定义的函数公式了。
9、接着选择单元格e2,输入公式为=照片,然后按回车键,这时候你会看到照片就引用过来了。
10、执行学生信息查询表就制作完成了,只要切换学生姓名,其他相应信息就会自动变化了。执行文件-保存命令,将文件保存即可。
int main(int argc, char const *argv[]){
for (int i = 0i <10++i)
{
TestAALock()
gCount = 0
gCountArray.clear()
}
return 0
}
以前做的。一、 需求分析
1. 本程序是是利用平衡二叉树实现一个动态查找表,实现动态查找表的三种基本功能:查找、插入和删除。
2. 初始,平衡二叉树为空树,可以按先序输入平衡二叉树,以输入0结束,中间以回车隔开,创建好二叉树后,可以对其查找,再对其插入,输入0结束插入,再可以对其删除,输入0结束,每次插入或删除一个结点后,更新平衡二叉树的显示。
3. 本程序以用户和计算机的对话方式执行,根据计算机终端显示:“提示信息”下,用户可由键盘输入要执行的 *** 作。
4. 测试数据(附后)
二、 概要设计
1. 抽象数据类型动态查找表的定义如下:
ADT DynamicSearchTable{
数据结构D:D是具有相同特性的数据元素的集合。各个数据元素含有类型相同,可惟一标识数据元素的关键字。
数据关系R:数据元素同属一个集合。
基本 *** 作P:
InitDSTable(&DT)
*** 作结果:构造一个空的动态查找表DT。
DestroyDSTable(&DT)
初试条件:动态查找表DT存在。
*** 作结果: 销毁动态查找表DT。
SearchDSTable(DT,key)
初试条件:动态查找表DT存在,key为和关键字类型相同的给定值。
*** 作结果: 若DT中存在其关键字等于key的数据元素,则函数值为该元素的值或表中的位置,否则为“空”。
InsertDSTable(&DT,e)
初试条件:动态查找表DT存在,e为待插入的数据元素。
*** 作结果: 若DT中不存在其关键字等于e. key的数据元素,则插入e到DT。
DeleteDSTable(&DT,key)
初试条件:动态查找表DT存在,key为和关键字类型相同的给定值。
*** 作结果: 若DT中存在其关键字等于key的数据元素,则删除之。
TraverseDSTable(DT,Visit())
初试条件:动态查找表DT存在,Visit()是结点 *** 作的应用函数。
*** 作结果: 按某种次序对DT的每个结点调用函数Visit()一次且至多
一次。一但Visit()失败,则 *** 作失败。
}ADT DynamicSearchTable
2. 本程序包含两个模块:
Void main(){
Do{
接受命令(根据提示输入终点城市和起点城市的序号);
处理命令;
}while(“命令”=“退出”);
}
3.本程序只有两个模块,调用关系简单
主程序模块
平衡二叉树的模块
三、 详细设计
1. 根据题目要求和查找的基本特点,其结点类型
typedef struct BSTnode{
int data
int bf
struct BSTnode *lchild,*rchild
}BSTnode,*bstree
#define LH +1
#define EH 0
#define RH -1
/-----------------------------************对平衡二叉树的 *** 作
bstree InsertAVL(bstree &T, int e);
////////在平衡二叉树中插入结点。
int FindAVL(bstree p,int e);
////////查找平衡二叉树中是否有结点e。
bstree DeleteAVL(bstree &T,int e)
////////删除平衡平衡二叉树的结点e,并保持平衡二叉树的性质。
int Preordertraverse(bstree T)
////////按先序遍历平衡二叉树。
/------------------------************平衡二叉树的 *** 作的详细算法
bstree InsertAVL(bstree &T, int e)
{
bstree p
//插入新结点,树长高置taller为TRUE
if(!T) {
T=(bstree)malloc(sizeof(BSTnode))
T->data=e
T->lchild=T->rchild=NULL
T->bf=EH
taller=TRUE
}
else {
//树中存在和e有相同关键字的结点则不再插入
if(e==T->data){
taller=FALSE
return NULL
}
//值小于则继续在树的左子树中搜索
if(e <T->data){
//插入到左子树且左子树长高
p=InsertAVL(T->lchild,e)
if(p){
T->lchild=p
if(taller) {
switch(T->bf){ //检查*T的平衡度
case LH: //原本左子树比右子树高,需要做左平衡处理
T=LeftBalance(T)
taller=FALSE
break
case EH: //原本左子树和右子树同高,现因左子树争高而使树增高
T->bf=LH
taller=TRUE
break
case RH: //原本右子树比左子树高,现在左右子树等高
T->bf=EH
taller=FALSE
break
}///////switch(T->bf)
}///////if(taller)
}/////if(p)
}///////if(e <T->data)
//继续在*T的右子树中搜索
else{
//插入到右子树且使右子树长高
p=InsertAVL(T->rchild,e)
if (p){
T->rchild=p
if(taller) {
switch(T->bf){ //检查*T的平衡度
case LH: //原本左子树比右子树高,现在左右子树等高
T->bf=EH
taller=FALSE
break
case EH: //原本左子树和右子树同高,现因右子树增高而使树增高
T->bf=RH
taller=TRUE
break
case RH: //原本右子树比左子树高,需要做右平衡处理
T=RightBalance(T)
taller=FALSE
break
}//////switch(T->bf)
}/////if(taller)
}/////if (p)
}//////if(e >T->data)
}///////else
return T
}
int Preordertraverse(bstree T){
if(T){
printf(" %d %d\n",T->data,T->bf)
Preordertraverse(T->lchild)
Preordertraverse(T->rchild)
}
return 1
}
int FindAVL(bstree p,int e){
if(p==NULL)return NULL
else if(e==p->data) return true
else if(e<p->data){
p=p->lchild
return FindAVL(p, e)
}////左子树上查找
else {
p=p->rchild
return FindAVL( p, e)
}////右子树上查找
}
bstree DeleteAVL(bstree &T,int e){
//删除后要保证该二叉树还是平衡的
int n,m=0/////标记
bstree q
if(!T)return NULL
else {
if(e==T->data) {////直接删除
n=Delete(T,e)
m=n
if(m!=0) {
q=T
DeleteAVL(T,m)
q->data=m}
}
else {
if(e<T->data){////在左子树上寻找
DeleteAVL(T->lchild,e)
if(shorter){
switch(T->bf){
case LH:T->bf=EHshorter=truebreak
case EH:T->bf=RHshorter=falsebreak
case RH:Delete_Rightbalance(T)shorter=truebreak
}////switch(T->bf)
}/////if(shorter)
}/////if(e<T->data)
else{ /////////在右子树上寻找
DeleteAVL(T->rchild,e)
if(shorter)
switch(T->bf){
case LH:Delete_Leftbalance(T)shorter=truebreak
case EH:T->bf=LHshorter=falsebreak
case RH:T->bf=EHshorter=truebreak
}////////switch(T->bf)
}////////在右子数上寻找完
}////////在左右子上完
}///////////删除完
return T
}
2. 主程序和其他伪码算法
void main(){
while(e!=0){
if(e!=0) InsertAVL(T,e)
}
while(d!=0){
if(d!=0) InsertAVL(T,d)
Preordertraverse(T)
}
c=FindAVL(T,t)
if(c==1)printf("有要查找的节点\n")
else printf("无要查找的节点\n")
do{
DeleteAVL(T,b)
Preordertraverse(T)
}while(b==1)
}
///右旋
bstree R_Rotate(bstree &p){
bstree lc
lc=p->lchild
p->lchild=lc->rchild
lc->rchild=p
p=lc
return p
}
////左旋
bstree L_Rotate(bstree &p){
bstree rc
rc=p->rchild
p->rchild=rc->lchild
rc->lchild=p
p=rc
return p
}
/////左平衡处理
bstree LeftBalance(bstree &T){
bstree lc,rd
lc=T->lchild//lc指向*T的左子树根结点
switch(lc->bf) { //检查*T的左子树平衡度,并做相应的平衡处理
case LH: //新结点插入在*T的左孩子的左子树上,要做单右旋处理
T->bf=lc->bf=EH
T=R_Rotate(T)
break
case RH: //新结点插入在*T的左孩子的右子树上,要做双旋处理
rd=lc->rchild//rd指向*T的左孩子的右子树根
switch(rd->bf){ //修改*T及其左孩子的平衡因子
case LH:
T->bf=RH
lc->bf=EH
break
case EH:
T->bf=lc->bf=EH
break
case RH:
T->bf=EH
lc->bf=LH
break
}//////////switch(rd->bf)
rd->bf=EH
T->lchild=L_Rotate(T->lchild)//对*T的左孩子做左旋平衡处理
T=R_Rotate(T)//对*T做右旋处理
}////////switch(lc->bf)
return T
}
////右平衡处理
bstree RightBalance(bstree &T)
{
bstree rc,ld
rc=T->rchild//rc指向*T的右子树根结点
switch(rc->bf) { //检查*T的右子树平衡度,并做相应的平衡处理
case RH: //新结点插入在*T的右孩子的右子树上,要做单右旋处理
T->bf=rc->bf=EH
T=L_Rotate(T)
break
case LH: //新结点插入在*T的右孩子的左子树上,要做双旋处理
ld=rc->lchild//ld指向*T的右孩子的左子树根
switch(ld->bf){ //修改*T及其右孩子的平衡因子
case LH:
T->bf=EH
rc->bf=RH
break
case EH:
T->bf=rc->bf=EH
break
case RH:
T->bf=LH
rc->bf=EH
break
}///switch(ld->bf)
ld->bf=EH
T->rchild=R_Rotate(T->rchild)//对*T的右孩子做右旋平衡处理
T=L_Rotate(T)//对*T做左旋处理
}/////switch(rc->bf)
return T
}
int Delete(bstree &T,int e){
//删除结点
bstree p,q
e=0
p=T
if(!T->rchild) {//右子数为空需要重接它的左子数
T=T->lchild
free(p)
shorter=true
}
else if(!T->lchild) {//重接它的右子数
T=T->rchild
free(p)
shorter=true
}
else{ //左右子数均不空
q=T->lchild
while(q->rchild!=NULL){//转左,然后向右到尽头
q=q->rchild
}
e=q->data
}
return e
}
void Delete_Rightbalance(bstree &T){
///////////删除在左子树上的,相当于插入在右子树
bstree rc=T->rchild,ld
switch(rc->bf){
case LH://///////双旋 ,先右旋后左旋
ld=rc->lchild
rc->lchild=ld->rchild
ld->rchild=rc
T->rchild=rc->lchild
rc->lchild=T
switch(ld->bf) {
case LH:T->bf=EH
rc->bf=RH
break
case EH:T->bf=rc->bf=EH
break
case RH:T->bf=LH
rc->bf=EH
break
}
ld->bf=EH
T=rc
shorter=truebreak
case EH:///////删除在左子树,相当于插入在右子树,左单旋
T->rchild=rc->lchild
rc->lchild=T
rc->bf=LH
T->bf=RH
T=rc
shorter=EHbreak
case RH:///////删除在左子树,相当于插入在右子树,左单旋
T->rchild=rc->lchild
rc->lchild=T
rc->bf=T->bf=EH
T=rc
shorter=truebreak
}
}
void Delete_Leftbalance(bstree &T)/////删除右子树上的,相当于插入在左子树上
{
bstree p1,p2
p1=T->lchild
switch(p1->bf) {
case LH:T->lchild=p1->rchild//////右旋
p1->rchild=T
p1->bf=T->bf=EH
T=p1
shorter=true
break
case EH:T->lchild=p1->rchild///////右旋
p1->rchild=T
p1->bf=RH
T->bf=LH
T=p1
shorter=false
break
case RH:p2=p1->rchild//////////右双旋
p1->rchild=p2->lchild
p2->lchild=p1
T->lchild=p2->rchild
p2->rchild=T
switch(p2->bf){
case LH:T->bf=RHp1->bf=EHbreak
case EH:T->bf=EHp1->bf=EHbreak
case RH:T->bf=EHp1->bf=LHbreak
}
p2->bf=EH
T=p2
shorter=truebreak
}
}
3. 函数的调用关系图
Main
InsertAVL Preordertraverse FindAVL DeleteAVL
四、 调试分析
1. 在开始对平衡二叉树的插入后,再做平衡处理时,特别是在做双向旋转平衡处理后的更新时,费了一些时间;
2. 在做平衡二叉树的删除时,当删除结点左右孩子均在时,开始直接用左子树的最大数代替,然后直接删除结点,结果导致删除了将要删除的结点及其孩子均删除了,后来将要删除的结点用左子树的最大树代替后,对左子树的最大结点做好标记,然后再做对其做删除处理。
3. 本程序算法基本简单,没有多大困难,就是在分析做双旋平衡处理的更新时,开始思路有些混乱,后来就好了;
五、 用户手册
1. 本程序的运行环境为DOS *** 作系统,执行文件为Balanced Tree.exe。
2. 进入演示程序后,按广度遍历输入平衡二叉树,中间以回车键隔开,输入0为结束;再输入要插入的结点,输入0结束,再输入要查找的结点,最后可以输入要删除的结点,输入0结束
六、 测试结果
先按广度遍历创建平衡二叉树(亦可一个一个的插入二叉树的结点)(50 20 60 10 30 55 70 5 15 25 58 90) ,输入0结束,然后可插入结点(39),其会显示插入后的二叉树,输入0,不再插入;输入要查找结点(6),输入要删除的结点(20),其显示如下:
七、 附录
Balance Tree.cpp
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)