五、算法设计题
- 设计一个算法:递归折半查找给定关键字
代码:int HalfSearch(SSTable T,ElemType k){ int high=T.length; int low=1; int mid=(high+low)/2;//找到中间位置 if(T.r[mid].key==k) return mid;//如果是查找值与中间位置相同则返回mid else if(T.r[mid].key>k){ SSTable S; S.length=mid-1; for(int i=0;i<S.length;i++) S.r[i]=T.r[i]; return HalfSearch(S,k); }//如果k小于中间值,则将左半部分赋值给S,并递归在S中查找 else{ S.length=T.length-mid+1; for(int i=0;i<S.length;i++) S.r[i]=T.r[mid+i]; return HalfSearch(S,k); }//如果k大于中间值,则将右半部分赋值给S,并递归在S中查找 return 0;//查找失败 }
- 设计一个算法:求给定结点在二叉排序树中所在的层数。
代码:int FindLevels(BSTree T,RedType k){ if(T==NULL) return 0;//树空则返回0 if(k==T->data) return 1;//如果根结点的值与k相等返回层数为1 else if(k<T->data){//如果k小于根结点的值,则递归计算左子树 int leftlev=FindLevels(T->lchild,k); if(leftlev!=0) return leftlev+1;//如果在左子树中找到k的层数则返回左子树中的层数值+1 }else{//如果k大于根结点的值,则递归计算右子树 int rightlev=FindLevels(T->rchild,k); if(rightlev!=0) return rightlev+1;//如果在右子树中找到k的层数则返回右子树中的层数值+1 } return 0;//树中没有值为k的结点,返回0 }
- 设计一个算法:判别给定二叉树是否为二叉排序树。设此二叉树以二叉链表为存储结构,且树中记录结点的关键字均不同。
代码:bool isBST(BSTree T){ if(T==NULL) return TRUE;//如果T为空树,则返回TRUE if(T->lchild!=NULL&&T->lchild->data>T->data) return FALSE;//如果T有左孩子且左孩子的值大于T则返回FALSE if(T->rchild!=NULL&&T->rchild->data<T->data) return FALSE;//如果T有右孩子且右孩子的值小于T则返回FALSE return isBST(T->lchild)&&isBST(T->rchild);//递归检查T的左右孩子 }
- 设计一个算法:在二叉排序树上找出任意两个不同结点的最近公共祖先。
代码:BSTNode *Ancestor(BSTree T,RedType k1,RedType k2){ BSTNode *p,*pre; p=pre=T;//将p和pre都指向根结点 while(p!=NULL){ if((k1<p->data)&&(k2<p->data)){ pre=p; p=p->lchild; }//如果k1,k2都小于p的值,则pre指向p,p指向p的左孩子 else if((k1>p->data)&&(k2>p->data)){ pre=p; p=p->rchild; }//如果k1,k2都大于p的值,则pre指向p,p指向p的右孩子 else if(((k1<p->data)&&(k2>p->data))||((k1>p->data)&&(k2<p->data))) return p;//如果k1,k2一个比p大一个比p小,那么p就是他们的第一个公共祖先 else if((k1==p->data)||(k2==p->data)) return pre;//如果p与k1或k2任何一个值相同,那么pre就是他们的公共祖先 } }
- 假设哈希表上删除操作已将记录关键字标记为DELETED(例如设DELETED为-2)。试设计一个查找及插入算法,使之能够正确的查找插入。
代码:int HashSearch_Close(HashTable T,RedType red){ int m=HashTable_Size; int DELETED=-2; int k=-1 int j=Hash(red.key,m);//哈希函数,求red对应的哈希地址 if(T.r[j].key==red.key) return j;//未发生冲突,一次查找成功,返回地址j int i=(j+1)%m;//开放定址法,线性探测再散列 while((T.r[i].key!=NULL)&&(i!=j)){//当i处哈希表值不为空,且i与j不等时 if(T.r[i].key==red.key) return i;//如果给定值与i处关键字相等,查找成功返回i if(T.r[i].key==DELETED) k=i;//如果线性探测过程中发现有删除点,做记录 i=(i+1)%m;//没满足上述条件继续使用开放定址法,线性探测再散列 } if(i==j){ if(k>=0){ T.r[k]=red; return -1; } else{ cout<<"Overflow!"<<endl; exit(1); } } /*如果最后循环到i=j都没找到,但是探测过程中有删除点, 则插入到所记录的删除点,否则报错溢出*/ else{//如果找到个位置i为空的单元 T.r[i]=red;//将red插入i处 T.length++;//哈希表记录个数加一 return -1;//返回-1 } } int Hash(ElemType k,int m){//除留余数法求k的哈希地址 return k%m; }