浙大版《数据结构(第2版)》题目集函数题题解

先放个地址题目链接:https://pintia.cn/problem-sets/434/problems/type/6感谢免费开放题集

函数题

编程题题解链接:https://blog.csdn.net/Alpaca00/article/details/104418351

习题1.8 二分查找

就是一个二分查找的裸题应该没什么好说的,主要是要注意他的L是一个指针然后注意判断条件不要写反了,还有就是他的返回值不能自己随便写,要用他设置好的宏定义或者枚举。

Position BinarySearch( List L, ElementType X ){
    Position left=1,right=L->Last;
    Position mid;
    while(left<=right){
        mid=(left+right)/2;
        if(L->Data[mid]==X) return mid;
        if(L->Data[mid]>X){			//注意这里的判断是根据元素是升序或降序来写的
            right=mid-1; 
        }else{
            left=mid+1;
        }
    }
    return NotFound;
}

习题1.9 有序数组的插入

这个因为是在有序数组插入,所以定位插入位置可以用二分查找。其他就没啥了

bool Insert( List L, ElementType X )
{
    if(L->Last==MAXSIZE-1) return false;
    Position left=0,right=L->Last;
    Position mid,ans;
    int flag;
    while(left<=right){
        mid=(left+right)/2;
        if(L->Data[mid]==X) return false;
        if(L->Data[mid]>X){
            flag=1;
            left=mid+1;
        }else{
            flag=0;
            right=mid-1;
        }
    }
    if(flag) mid+=1;
    right=L->Last+=1;
    while(right>mid){
        L->Data[right]=L->Data[right-1];
        right--;
    }
    L->Data[right]=X;
    return true;
}

习题2.4 递增的整数序列链表的插入

因为是链表所以只能一个个比较找到插入位置,然后定义一前一后两个指针方便插入。

List Insert( List L, ElementType X )
{
    PtrToNode p1=L->Next,p2=L;
    while(p1!=NULL&&X>p1->Data){
        p2=p1;
        p1=p1->Next;
    }
    p2->Next=malloc(sizeof(struct Node));
    p2->Next->Data=X;
    p2->Next->Next=p1;
    return L;
}

习题2.5 两个有序链表序列的合并 (15分)

因为必须要使用原来的元素所以就只能这么写了大概,其实也和普通归并算法无差异
普通二路归并可参考:二路归并算法和归并排序
从这开始后面图方便就写了好多宏定义做小写,后面的代码就不贴了,所以如果大小写参杂请原谅orz

#define last Last
#define data Data
#define ptr PtrToNode
#define next Next
#define node Node
#define list List
#define len sizeof(struct node)
List Merge( List L1, List L2 )
{
    list head=malloc(len),p=head;
    head->next=NULL;
    list p1=L1->next,p2=L2->next;
    L1->next=NULL,L2->next=NULL;
    while(p1!=NULL&&p2!=NULL){
        if(p1->data<p2->data){
            p->next=p1;
            p=p->next;
            p1=p1->next;
        }else{
            p->next=p2;
            p=p->next;
            p2=p2->next;
        }
    }
    if(p1!=NULL) p->next=p1;
    if(p2!=NULL) p->next=p2;
    return head;
}

习题2.6 递归求简单交错幂级数的部分和 (15分)

因为要用递归,所以这题的式子可以拆一下发现可以拆成
x ∗ ( 1 − x ∗ ( 1 − x ∗ ( 1 − x ∗ ( . . . ) ) ) ) x*(1-x*(1-x*(1-x*(...)))) x(1x(1x(1x(...))))于是就变成了模板的递归调用了

double fn( double x, int n )
{
    if(n==1){
        return x;
    }
    return x*(1-fn(x,n-1));
}

习题2.7 弹球距离 (15分)

模拟题没啥好说的,只是要注意可能刚开始的h就比tol小,但是因为h是下落距离所以也要算进去

double dist( double h, double p )
{
    double sum=h;
    h*=p;
    while(h>=TOL){
        sum+=2*h;
        h*=p;  
    }
    return sum;
}

习题3.3 线性表元素的区间删除 (20分)

定义一个活动下标now表示当前值,然后判断是否被放入数组就行了

List Delete( List L, ElementType minD, ElementType maxD )
{
    int start=0,now=0;
    while(now<=L->last){
        if(!(L->data[now]>minD&&L->data[now]<maxD)){
            L->data[start++]=L->data[now];
        }
        now++;
    }
    L->last=start-1;
    return L;
}

习题3.5 求链表的倒数第m个元素 (20分)

这个找倒数第m个,最简单的想法可能是一个一个输入到数组里面然后找到倒数第m个或者别的怎么样

但是这题其实可以定义两个指针一前以后相隔m个元素,后面的指针到尾部时,前面的指针就是倒数第m个元素了。
这题我觉得算这里面比较好的了

ElementType Find( List l, int m )
{
    list p1,p2;
    p2=l->next;
    while(m--){
        if(p2==NULL) return ERROR;
        p2=p2->next;
    }
    p1=l->next;
    while(p2!=NULL){
        p2=p2->next;
        p1=p1->next;
    }
    return p1->data;
}

习题3.12 另类循环队列 (20分)

就是用普通的循环队列,只是判断是否满载不能用首尾比较而是看有多少个元素就行了。

bool AddQ( Queue Q, ElementType X )
{
    if(Q->count==Q->size){
        printf("Queue Full\n");
        return false;
    }
    Q->data[(Q->front+Q->count)%Q->size]=X;
    Q->count++;
    return true;
}
ElementType DeleteQ( Queue Q )
{
    if(Q->count==0){
        printf("Queue Empty\n");
        return ERROR;
    }
    type x=Q->data[Q->front];
    if(Q->front+1==Q->size) Q->front=0;
    else Q->front++;
    Q->count--;
    return x;
}

习题3.13 双端队列 (25分)

这题待补充
orz
orz

习题3.14 另类堆栈 (15分)

这几个另类说是另类其实都是正常栈操作嘛
就是裸的栈
用top表示栈尾(最后一个元素的后面)

bool Push( Stack S, ElementType X )
{
    if(S->Top==S->MaxSize){
        printf("Stack Full\n");
        return false;
    }
    S->Data[(S->Top)++]=X;
    return true;
}
ElementType Pop( Stack S )
{
    if(S->Top==0){
        printf("Stack Empty\n");
        return ERROR;
    }
    return S->Data[--(S->Top)];
}

习题4.3 是否二叉搜索树 (25分)

这个是否二叉搜索树可以考虑用中序遍历,因为中序遍历二叉搜索树就一定有序
借助一个全局变量t1代表上一个元素,然后每次拿当前的和上一次的判断一下是不是有序的就行了

int flag=1;
int t1=-0x3f3f3f3f;
bool IsBST ( BinTree T )
{
    if(flag==0) return false;
    if(T!=NULL){
        IsBST(T->Left);
        if(T->Data<t1){
            flag=0;
            return false;
        }
        t1=T->Data;
        IsBST(T->Right);
    }
    return flag;
}

习题5.10 线性探测法的查找函数 (20分)

也是裸题,只是可能不知道线性探测是啥,就是如果这个哈希表冲突,那就一直往后找是否有空余的位置能插。
在普通的哈希表上加个count来循环往后找
只是他这题元素还有三种类型,所以要看好他的源代码来判断他这三个类型到底是个啥逻辑关系

Position Find( HashTable H, ElementType Key )
{
    Position ind;
    int count=0;
    while(count!=H->TableSize){
        ind=Hash(Key+count,H->TableSize);
        if((H->Cells[ind]).Info!=Empty){
            if((H->Cells[ind]).Data==Key){
                return ind;
            }
        }else return ind;
        count++;
    }
    return ERROR;
}

习题5.11 分离链接法的删除操作函数 (20分)

这个就是哈希挂链换了个名字,不知道哈希挂链是啥的可以参考:哈希挂链方法
这题还要注意不能犯 p 2 = h − > h e a d s [ i n d ] p2=h->heads[ind] p2=h>heads[ind] 的错误

bool Delete( HashTable H, ElementType Key )
{
    Index ind=Hash( Key, H->TableSize );
    List p1,p2;
    p2=(H->Heads)+ind;		//不是p2=h->heads[ind];
    p1=p2->Next;
    while(p1!=NULL){
        if(strcmp(p1->Data,Key)==0){
            printf("%s is deleted from list Heads[%d]\n",Key,ind);
            p2->Next=p1->Next;
            return true;
        }
        p2=p1;
        p1=p1->Next;
    }
    return false;
}

练习6.1 邻接矩阵存储图的深度优先遍历 (20分)

待补充

练习6.2 邻接表存储图的广度优先遍历 (20分)

待补充

  • 4
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值