6-10 二分查找
题目要求:
本题要求实现二分查找算法。L是用户传入的一个线性表,其中ElementType元素可以通过>、==、<进行比较,并且题目保证传入的数据是递增有序的。函数BinarySearch要查找X在Data中的位置,即数组下标(注意:元素从下标1开始存储)。找到则返回下标,否则返回一个特殊的失败标记NotFound。
代码如下:
Position BinarySearch( List L, ElementType X ){
int head,last,mid;
head=1;
last=L->Last;
while(head<=last){
mid=(head+last)/2;
if(L->Data[mid]==X){
return mid;
}
if(L->Data[mid]>X){
last=mid-1;
}
if(L->Data[mid]<X){
head=mid+1;
}
}
return NotFound;
}
本题思路:
1、二分法查找有三个指针分别指向头、尾和中间。循环比较欲找X与中间值的大小关系,直到头尾指针重合或者中间指针指到了X上,判断X是否在数组中存在。
2、while的判断语句中while(head<=last)
必须有等于号。原因是如果X在头尾指针相遇的位置,假设判断语句只有<号,此时head和last相等会跳出循环,从而没法返回这一项。
6-11 先序输出叶结点
题目要求:
本题要求按照先序遍历的顺序输出给定二叉树的叶结点。接口定义:void PreorderPrintLeaves( BinTree BT )
函数PreorderPrintLeaves应按照先序遍历的顺序输出给定二叉树BT的叶结点,格式为一个空格跟着一个字符。
代码如下:
void PreorderPrintLeaves( BinTree BT ){
if(BT!=NULL){
if(BT->Left==NULL && BT->Right==NULL){
printf(" %c",BT->Data);
}
PreorderPrintLeaves(BT->Left);
PreorderPrintLeaves(BT->Right);
}
}
本题思路:
1、之前做过一道用单链表穿起叶子结点的题,比较类似,思想都差不多,这道题做了一定简化,使用递归的思想,遇到结点先判断是否为叶子结点,如果是则输出数据,之后处理非叶结点的左右子树。递归的思路是从下到上的,从最迫切需求到一般需求,需要好好体会。
6-12 二叉搜索树的操作集
题目要求:
本题要求实现给定二叉搜索树的5种常用操作。
BinTree Insert( BinTree BST, ElementType X );
BinTree Delete( BinTree BST, ElementType X );
Position Find( BinTree BST, ElementType X );
Position FindMin( BinTree BST );
Position FindMax( BinTree BST );
函数Insert将X插入二叉搜索树BST并返回结果树的根结点指针;
函数Delete将X从二叉搜索树BST中删除,并返回结果树的根结点指针;如果X不在树中,则打印一行Not Found并返回原树的根结点指针;
函数Find在二叉搜索树BST中找到X,返回该结点的指针;如果找不到则返回空指针;
函数FindMin返回二叉搜索树BST中最小元结点的指针;
函数FindMax返回二叉搜索树BST中最大元结点的指针。
代码如下:
BinTree Insert( BinTree BST, ElementType X ){
if(BST==NULL){ //遇到空节点。
BST=(BinTree)malloc(sizeof(struct TNode));
BST->Data=X;
BST->Left=NULL;
BST->Right=NULL;
}
else{
if(BST->Data>X){
BST->Left=Insert(BST->Left,X);//若果不加BST->left=,会出问题。
}
else if(BST->Data<X){
BST->Right=Insert(BST->Right,X);
}
}
return BST;
}
BinTree Delete( BinTree BST, ElementType X ){
BinTree temp;
if(BST==NULL){
printf("Not Found\n");
}
else{
if(BST->Data>X){
BST->Left=Delete(BST->Left,X);
}
else if(BST->Data<X){
BST->Right=Delete(BST->Right,X);
}
else{ //找到需要删除的结点
if(BST->Left && BST->Right){ //左右子树都存在
temp=FindMin(BST->Right);
BST->Data=temp->Data;
BST->Right=Delete(BST->Right,temp->Data);
}
else{ //只存在单子树。
temp=BST;
if(!BST->Left){
BST=BST->Right;
}
else if(!BST->Right){
BST=BST->Left;
}
free(temp);
}
}
}
return BST;
}
Position Find( BinTree BST, ElementType X ){
while(BST!=NULL){
if(BST->Data==X){
return BST;
}
else if(BST->Data>X){
BST=BST->Left;
}
else if(BST->Data<X){
BST=BST->Right;
}
}
return NULL;
}
Position FindMin( BinTree BST ){
if(BST==NULL){
return NULL;
}
while(BST->Left!=NULL){
BST=BST->Left;
}
return BST;
}
Position FindMax( BinTree BST ){
if(BST==NULL){
return NULL;
}
while(BST->Right!=NULL){
BST=BST->Right;
}
return BST;
}
本题思路:
1、插入操作中:运用递归的思想,首先判断是否到达插入结点位置,到达则插入,注意要分配储存空间。之后判断遇到普通结点应该怎么做。注意因为后续会对相关联普通结点的左或右子树进行插入,如果在递归时BST->Left=Insert(BST->Left,X);
没有写BST->Left=
会出现新插入的结点没有父结点。
2、查找操作比较简单,比现结点大就找右子树,小就找左子树。
3、找最小操作就是找整个树上最左结点,找最大操作就是找最右结点。注意如果没有遇到相应结点或者为空树则返回NULL。
4、删除操作:采用递归的思想,如果找不到就返回没找到,之后对普通结点进行判别,依旧需要注意的是删除操作也是会对左或右子树进行更改,所以需要加BST->Left=
。之后有需要判断预删除节点是左右子树都存在还是单子树。
删除需要借助一个temp变量来定位现指针,如果是左右子树都存在的情况,则需要找到右子树的最小值,与现指针指向的值进行替换,之后删除被替换的结点。
如果删除的是单子树,就子承父业。这里记得要将存储在temp里的他爹删除掉。