第9章 内部排序.docx

上传人:b****6 文档编号:8911393 上传时间:2023-02-02 格式:DOCX 页数:15 大小:54.20KB
下载 相关 举报
第9章 内部排序.docx_第1页
第1页 / 共15页
第9章 内部排序.docx_第2页
第2页 / 共15页
第9章 内部排序.docx_第3页
第3页 / 共15页
第9章 内部排序.docx_第4页
第4页 / 共15页
第9章 内部排序.docx_第5页
第5页 / 共15页
点击查看更多>>
下载资源
资源描述

第9章 内部排序.docx

《第9章 内部排序.docx》由会员分享,可在线阅读,更多相关《第9章 内部排序.docx(15页珍藏版)》请在冰豆网上搜索。

第9章 内部排序.docx

第9章内部排序

第9章内部排序

9.1

(1)无序表:

顺序查找不成功时,查找长度为n+1;成功时,平均查找长度为1/(n+1)*(1+2+…+(n+1))=(n+2)/2;两者不相同。

(2)表中只有一个关键字等于给定值k的记录,无序表、有序表:

顺序查找成功时,平均查找长度均为1/(n)*(1+2+…+n)=(n+1)/2;两者相同。

(3)表中只有m个关键字等于给定值k的记录,无序表:

ASL=n+1;有序表:

ASL=(n+1)/2+m;两者不相同。

 

9.3

ASL=1/10(1+2*2+4*3+3*4)=2.9

 

9.11

 

 

9.14

 

删除50后

 

 

删除68后

 

9.19

22

67

41

30

 

53

46

 

13

 

01

0

1

2

3

4

5

6

7

8

9

10

 

ASL=(4*1+2*2+3+6)/8=17/8

 

9.25

intSearch-Seq(SSTableST,KeyTypekey){

//在顺序表ST中顺序查找其关键字等于key的数据元素,ST按关键字自大至小有序,

//若找到,则函数值为该元素在表中的位置,否则为0

ST.elem[ST.length+1].key=key;

for(i=1;ST.elem[i].key>key;++i);

if(ST.elem[i].key==key)&&(i<=ST.length)returni

elsereturn0;

}//Search-Seq

 

9.31

TelemTypeMaxv(BitreeT){

//返回二叉排序树T中所有结点的最大值

for(p=T;p->rchild;p=p->rchild);

returnp->data;

}//Maxv

 

TelemTypeMinv(BitreeT){

//返回二叉排序树T中所有结点的最小值

for(p=T;p->lchild;p=p->lchild);

returnp->data;

}//Minv

 

StatusIsBST(BitreeT){

//判别T是否为二叉排序树

if(!

T)returnOK;

elseif((!

T->lchild)||((T->lchild)&&(IsBST(T->lchild)&&(Maxv(T->lchild)data)))

&&((!

T->rchild)||((T->rchild)&&(IsBST(T->rchild)&&(Minv(T->rchild)>T->data)))

returnOK

elsereturnERROR;

}//IsBST

 

9.33

StatusOutputGEx(BitreeT,TelemTypex){

//从大到小输出给定二叉排序树T中所有值不小于x的数据元素

if(T){

if(OutputGEx(T->rchild,x))

if(T->data>=x){

print(T->data);

if(OutputGEx(T->lchild,x))returnOK;

}

elsereturnOK;

}

elsereturnOK;

}//OutputGEx

 

第九章查找

9.25

intSearch_Sq(SSTableST,intkey)//在有序表上顺序查找的算法,监视哨设在高下标端

{

  ST.elem[ST.length+1].key=key;

  for(i=1;ST.elem[i].key>key;i++);

  if(i>ST.length||ST.elem[i].key

  returni;

}//Search_Sq

分析:

本算法查找成功情况下的平均查找长度为ST.length/2,不成功情况下为ST.length.

9.26

intSearch_Bin_Digui(SSTableST,intkey,intlow,inthigh)//折半查找的递归算法

{

  if(low>high)return0;//查找不到时返回0

  mid=(low+high)/2;

  if(ST.elem[mid].key==key)returnmid;

  elseif(ST.elem[mid].key>key)

    returnSearch_Bin_Digui(ST,key,low,mid-1);

  elsereturnSearch_Bin_Digui(ST,key,mid+1,high);

  }

}//Search_Bin_Digui

9.27

intLocate_Bin(SSTableST,intkey)//折半查找,返回小于或等于待查元素的最后一个结点号

{

  int*r;

  r=ST.elem;

  if(key

  elseif(key>=r[ST.length].key)returnST.length;

  low=1;high=ST.length;

  while(low<=high)

  {

    mid=(low+high)/2;

    if(key>=r[mid].key&&key

      returnmid;

    elseif(key

    elselow=mid;

  }//本算法不存在查找失败的情况,不需要return0;

}//Locate_Bin

9.28

typedefstruct{

                intmaxkey;

                intfirstloc;

              }Index;

typedefstruct{

                int*elem;

                intlength;

                Indexidx[MAXBLOCK];//每块起始位置和最大元素,其中idx[0]不利用,其内容初始化为{0,0}以利于折半查找

                intblknum;//块的数目

              }IdxSqList;//索引顺序表类型

intSearch_IdxSeq(IdxSqListL,intkey)//分块查找,用折半查找法确定记录所在块,块内采用顺序查找法

{

  if(key>L.idx[L.blknum].maxkey)returnERROR;//超过最大元素

  low=1;high=L.blknum;

  found=0;

  while(low<=high&&!

found)//折半查找记录所在块号mid

  {

    mid=(low+high)/2;

    if(key<=L.idx[mid].maxkey&&key>L.idx[mid-1].maxkey)

      found=1;

    elseif(key>L.idx[mid].maxkey)

      low=mid+1;

    elsehigh=mid-1;

  }

  i=L.idx[mid].firstloc;//块的下界

  j=i+blksize-1;//块的上界

  temp=L.elem[i-1];//保存相邻元素

  L.elem[i-1]=key;//设置监视哨

  for(k=j;L.elem[k]!

=key;k--);//顺序查找

  L.elem[i-1]=temp;//恢复元素

  if(k

  returnk;

}//Search_IdxSeq

分析:

在块内进行顺序查找时,如果需要设置监视哨,则必须先保存相邻块的相邻元素,以免数据丢失.

9.29

typedefstruct{

                LNode*h;//h指向最小元素

                LNode*t;//t指向上次查找的结点

              }CSList;

LNode*Search_CSList(CSList&L,intkey)//在有序单循环链表存储结构上的查找算法,假定每次查找都成功

{

  if(L.t->data==key)returnL.t;

  elseif(L.t->data>key)

    for(p=L.h,i=1;p->data!

=key;p=p->next,i++);

  else

    for(p=L.t,i=L.tpos;p->data!

=key;p=p->next,i++);

  L.t=p;//更新t指针

  returnp;

}//Search_CSList

分析:

由于题目中假定每次查找都是成功的,所以本算法中没有关于查找失败的处理.由微积分可得,在等概率情况下,平均查找长度约为n/3.

9.30

typedefstruct{

                DLNode*pre;

                intdata;

                DLNode*next;

              }DLNode;

typedefstruct{

                DLNode*sp;

                intlength;

              }DSList;//供查找的双向循环链表类型

DLNode*Search_DSList(DSList&L,intkey)//在有序双向循环链表存储结构上的查找算法,假定每次查找都成功

{

  p=L.sp;

  if(p->data>key)

  {

    while(p->data>key)p=p->pre;

    L.sp=p;

  }

  elseif(p->data

  {

    while(p->datanext;

    L.sp=p;

  }

  returnp;

}//Search_DSList

分析:

本题的平均查找长度与上一题相同,也是n/3.

9.31

intlast=0,flag=1;

intIs_BSTree(BitreeT)//判断二叉树T是否二叉排序树,是则返回1,否则返回0

{

  if(T->lchild&&flag)Is_BSTree(T->lchild);

  if(T->data

  last=T->data;

  if(T->rchild&&flag)Is_BSTree(T->rchild);

  returnflag;

}//Is_BSTree

9.32

intlast=0;

voidMaxLT_MinGT(BiTreeT,intx)//找到二叉排序树T中小于x的最大元素和大于x的最小元素

{

  if(T->lchild)MaxLT_MinGT(T->lchild,x);//本算法仍是借助中序遍历来实现

  if(lastdata>=x)//找到了小于x的最大元素

    printf("a=%d\n",last);

  if(last<=x&&T->data>x)//找到了大于x的最小元素

    printf("b=%d\n",T->data);

  last=T->data;

  if(T->rchild)MaxLT_MinGT(T->rchild,x);

}//MaxLT_MinGT

9.33

voidPrint_NLT(BiTreeT,intx)//从大到小输出二叉排序树T中所有不小于x的元素

{

  if(T->rchild)Print_NLT(T->rchild,x);

  if(T->data

  printf("%d\n",T->data);

  if(T->lchild)Print_NLT(T->lchild,x);//先右后左的中序遍历

}//Print_NLT

9.34

voidDelete_NLT(BiTree&T,intx)//删除二叉排序树T中所有不小于x元素结点,并释放空间

{

  if(T->rchild)Delete_NLT(T->rchild,x);

  if(T->data

  q=T;

  T=T->lchild;

  free(q);//如果树根不小于x,则删除树根,并以左子树的根作为新的树根

  if(T)Delete_NLT(T,x);//继续在左子树中执行算法

}//Delete_NLT

9.35

voidPrint_Between(BiThrTreeT,inta,intb)//打印输出后继线索二叉排序树T中所有大于a且小于b的元素

{

  p=T;

  while(!

p->ltag)p=p->lchild;//找到最小元素

  while(p&&p->data

  {

    if(p->data>a)printf("%d\n",p->data);//输出符合条件的元素

    if(p->rtag)p=p->rtag;

    else

    {

      p=p->rchild;

      while(!

p->ltag)p=p->lchild;

    }//转到中序后继

  }//while

}//Print_Between

9.36

voidBSTree_Insert_Key(BiThrTree&T,intx)//在后继线索二叉排序树T中插入元素x

{

  if(T->data

  {

    if(T->rtag)//T没有右子树时,作为右孩子插入

    {

      p=T->rchild;

      q=(BiThrNode*)malloc(sizeof(BiThrNode));

      q->data=x;

      T->rchild=q;T->rtag=0;

      q->rtag=1;q->rchild=p;//修改原线索

    }

    elseBSTree_Insert_Key(T->rchild,x);//T有右子树时,插入右子树中

  }//if

  elseif(T->data>x)//插入到左子树中

  {

    if(!

T->lchild)//T没有左子树时,作为左孩子插入

    {

      q=(BiThrNode*)malloc(sizeof(BiThrNode));

      q->data=x;

      T->lchild=q;

      q->rtag=1;q->rchild=T;//修改自身的线索

    }

    elseBSTree_Insert_Key(T->lchild,x);//T有左子树时,插入左子树中

  }//if

}//BSTree_Insert_Key

9.37

StatusBSTree_Delete_key(BiThrTree&T,intx)//在后继线索二叉排序树T中删除元素x

{

  BTNode*pre,*ptr,*suc;//ptr为x所在结点,pre和suc分别指向ptr的前驱和后继

  p=T;last=NULL;//last始终指向当前结点p的前一个(前驱)

  while(!

p->ltag)p=p->lchild;//找到中序起始元素

  while(p)

  {

    if(p->data==x)//找到了元素x结点

    {

      pre=last;

      ptr=p;

    }

    elseif(last&&last->data==x)suc=p;//找到了x的后继

    if(p->rtag)p=p->rtag;

    else

    {

      p=p->rchild;

      while(!

p->ltag)p=p->lchild;

    }//转到中序后继

    last=p;

  }//while//借助中序遍历找到元素x及其前驱和后继结点

  if(!

ptr)returnERROR;//未找到待删结点

  Delete_BSTree(ptr);//删除x结点

  if(pre&&pre->rtag)

    pre->rchild=suc;//修改线索

  returnOK;

}//BSTree_Delete_key

voidDelete_BSTree(BiThrTree&T)//课本上给出的删除二叉排序树的子树T的算法,按照线索二叉树的结构作了一些改动

{

  q=T;

  if(!

T->ltag&&T->rtag)//结点无右子树,此时只需重接其左子树

    T=T->lchild;

  elseif(T->ltag&&!

T->rtag)//结点无左子树,此时只需重接其右子树

    T=T->rchild;

  elseif(!

T->ltag&&!

T->rtag)//结点既有左子树又有右子树

  {

    p=T;r=T->lchild;

    while(!

r->rtag)

    {

      s=r;

      r=r->rchild;//找到结点的前驱r和r的双亲s

    }

    T->data=r->data;//用r代替T结点

    if(s!

=T)

      s->rchild=r->lchild;

    elses->lchild=r->lchild;//重接r的左子树到其双亲结点上

    q=r;

  }//else

  free(q);//删除结点

}//Delete_BSTree

分析:

本算法采用了先求出x结点的前驱和后继,再删除x结点的办法,这样修改线索时会比较简单,直接让前驱的线索指向后继就行了.如果试图在删除x结点的同时修改线索,则问题反而复杂化了.

9.38

voidBSTree_Merge(BiTree&T,BiTree&S)//把二叉排序树S合并到T中

{

  if(S->lchild)BSTree_Merge(T,S->lchild);

  if(S->rchild)BSTree_Merge(T,S->rchild);//合并子树

  Insert_Key(T,S);//插入元素

}//BSTree_Merge

voidInsert_Key(Bitree&T,BTNode*S)//把树结点S插入到T的合适位置上

{

  if(S->data>T->data)

  {

    if(!

T->rchild)T->rchild=S;

    elseInsert_Key(T->rchild,S);

  }

  elseif(S->datadata)

  {

    if(!

T->lchild)T->lchild=S;

    elseInsert_Key(T->lchild,S);

  }

  S->lchild=NULL;//插入的新结点必须和原来的左右子树断绝关系

  S->rchild=NULL;//否则会导致树结构的混乱

}//Insert_Key

分析:

这是一个与课本上不同的插入算法.在合并过程中,并不释放或新建任何结点,而是采取修改指针的方式来完成合并.这样,就必须按照后序序列把一棵树中的元素逐个连接到另一棵树上,否则将会导致树的结构的混乱.

9.39

voidBSTree_Split(BiTree&T,BiTree&A,BiTree&B,intx)//把二叉排序树T分裂为两棵二叉排序树A和B,其中A的元素全部小于等于x,B的元素全部大于x

{

  if(T->lchild)BSTree_Split(T->lchild,A,B,x);

  if(T->rchild)BSTree_Split(T->rchild,A,B,x);//分裂左右子树

  if(T->data<=x)Insert_Key(A,T);

  elseInsert_Key(B,T);//将元素结点插入合适的树中

}//BSTree_Split

voidInsert_Key(Bitree&T,BTNode*S)//把树结点S插入到T的合适位置上

{

  if(!

T)T=S;//考虑到刚开始分裂时树A和树B为空的情况

  elseif(S->data>T->data)//其余部分与上一题同

  {

    if(!

T->rchild)T->rchild=S;

    elseInsert_Key(T->rchild,S);

  }

  elseif(S->datadata)

  {

    if(!

T->lchild)T->lchild=S;

    elseInsert_Key(T->lchild,S);

  }

  S->lchild=NULL;

  S->rchild=NULL;  

}//Insert_Key

9.40

typedefstruct{

                intdata;

                intbf;

                intlsize;//lsize域表示该结点的左子树的结点总数加1

                BlcNode*lchild,*rchild;

              }BlcNode,*BlcTree;//含lsize域的平衡二叉排序树类型

BTNode*Locate_BlcTree(BlcTreeT,intk)//在含lsize域的平衡二叉排序树T中确定第k小的结点指针

{

  if(!

T)returnNULL;//k小于1或大于树结点总数

  if(T->lsize==k)returnT;//就是这个结点

  elseif(T->lsize>k)

    returnLocate_BlcTree(T->lchild,k);//在左子树中寻找

  elsereturnLocate_BlcTre

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 外语学习 > 法语学习

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1