数据结构上机题

习题1.8 二分查找

Position BinarySearch( List L, ElementType X )
{
    int l,r,mid;
    l=1;
    r=L->Last;//注意这里L不要写成l
    while(l<=r)
    {
        mid=(l+r)/2;
        if(L->Data[mid]<X) l=mid+1;//这里Data不要写成data
        else if(L->Data[mid]>X) r=mid-1;
        else  return mid;
    }
    return NotFound;
    
}

习题1.9 有序数组的插入


注释的几个需要注意的点要养成一下习惯

bool Insert(List L,ElementType X)
{    
    if(L->Last==MAXSIZE-1) return false;

    for(int i=0;i<=L->Last;i++)//这里是<=
    {
        if(L->Data[i]==X) return false;
        //从大到小遍历,遍历到第一个比它小的时候就往后挪
        else if(L->Data[i]<X)
        {
            for(int j=L->Last;j>=i;j--)
            {
                L->Data[j+1]=L->Data[j];//这里别写成i
            }
            L->Data[i]=X;
            L->Last++;//每一次插入成功后记得增加长度
            break;
        }else{
            //如果每一个都大于该值,插入末尾
            if(i==L->Last){ 
            L->Data[i+1]=X;
            L->Last++;//同理
                break;
            }
        }
    }
    return true;
}

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

List Insert(List L,ElementType X)
{
  //这种方法是直接找第一个比它的结点的前驱结点
    List s=(List)malloc(sizeof (List));
    s->Data=X;
    List p=L;//工作指针
    while( p->Next && X > p->Next->Data)//x比下一个结点的值大才更新指针
    //这样保证p指向的就是所需要的前驱结点
    {
        p=p->Next;
    }

    s->Next=p->Next;
    p->Next=s;

    return L; //别忘记返回L
}
List Insert(List L,ElementType X)
{
//这种方法是找第一个大于X的结点
    List s,p=L->Next,pre=L;//p为工作指针
    s=(List)malloc(sizeof(List));//临时结点放x
    s->Data=X;

    while(p!=NULL &&p->Data<X){
        pre=p;
        p=p->Next;
    }
    if(p!=NULL)
    {
        pre->Next=s;
        s->Next=p;
    }
    else {
        pre->Next=s;
        s->Next=NULL;
    }
    return L;
}

习题2.5 两个有序链表序列的合并

List Merge(List L1,List L2)
{
    List p1=L1->Next;
    List p2=L2->Next;

    //创建一个新的头结点
    List L=(List)malloc(sizeof(List));
    List p=L;//工作指针p,用来添加L的后续结点

    
    while(p1&&p2)
    {    
        if(p1->Data <p2->Data)
        {
            //p要移动 p1也要移动
            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;

    //记得把这两个头结点取下来
    L1->Next=NULL;
    L2->Next=NULL;
    return L;
    
}

实例1.1 最大子列和问题

因为我们只需要得到最大的子列和,那么当sum>0时,不断的去取一个最大值,当sum<0时重新更新sum=0即可,这个最大值便是最大的子列和

#include <bits/stdc++.h>
using namespace std;
int main()
{
    int n; 
    cin>>n;
    int maxx=-1,sum=0;
    for(int i=0;i<n;i++)
    {
        int x;
        cin>>x;
        if(sum+x<0) sum=0;
        else{
            sum+=x;
            maxx=max(sum,maxx);
        }
    }
    cout<<maxx;
    
}

习题2.1 简单计算器

简单是简单,但是注意输入的顺序,不然容易卡半天

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int sum=0;
    char op;
    cin>>sum>>op;
    while(op!='=')
    {
        int x; 
        cin>>x;//输入操作数
        if(op=='+') sum+=x;
        else if(op=='-') sum-=x;
        else if(op=='*') sum*=x;
        else if(op=='/')
        {
            if(x==0){
                cout<<"ERROR";
                return 0;
            }
            else sum/=x;
        }else {
            cout<<"ERROR";
            return 0;
        }
        
        cin>>op;//输入符号
    }
    cout<<sum;
    
}

习题2.2 数组循环左移
这题其实有三个方法
方法1:直接观察结果输出即可

#include <bits/stdc++.h>
using namespace std;
int main()
{    
    int n,m;
    cin>>n>>m;
    m%=n;
    vector<int>ve(n+1);
    for(int i=1;i<=n;i++) cin>>ve[i];
    cout<<ve[m+1];
    for(int i=m+2;i<=n;i++) cout<<" "<<ve[i];
    for(int i=1;i<=m;i++) cout<<" "<<ve[i];
    
}

方法2:通过每次将N个元素循环位移一次,进行m次这样的循环位移

#include <bits/stdc++.h>
using namespace std;
int a[105];

void move(int n)
{
    int temp=a[0];
    for(int i=0;i<n-1;i++) a[i]=a[i+1];
    a[n-1]=temp;
}


int main()
{    
    int n,m;
    cin>>n>>m;
    m%=n;
    for(int i=0;i<n;i++) cin>>a[i];
    for(int i=0;i<m;i++) move(n);
    cout<<a[0];
    for(int i=1;i<n;i++) cout<<" "<<a[i];
}

方法3:就是通过元素翻转位置比如将1 2 3 4 5 6 7 8翻转为3 2 1 4 5 6 7 8然后按照特定顺序输出即可,这里不给出代码。

习题2.3 数列求和-加强版

常规方法是直接进行加减,但是这样当位数太大的时候是会溢出的,所以采取最优的方法就是在每一位上进行计算,然后把对应的每一位存在数组里,最后再输出每一位。原理其实就是加法的进位

#include <bits/stdc++.h>
using namespace std;
#define int long long

signed main()
{
   int A,N;
    cin>>A>>N;
    if(!N){
        cout<<0;
        return 0;
    }
    int S[100005];
    memset(S,0,sizeof S);
    int c=0;//每一位上的进位
    for(int i=0;i<N;i++)
    {
        //加法的进位
        c+=A*(N-i);
        S[i]=c%10;
        c/=10;
    }
    //最高位如果不是0
    if(c) cout<<c;
    //倒序输出
    for(int i=N-1;i>=0;i--) cout<<S[i];
}

习题3.4 最长连续递增子序列

处理两个子问题1.序列最大长度 2.最终的序列区间的左右端点下标
1.只要当\(a[i]<=a[i-1]\)时,我们就去更新当前的最大序列长度,和最终答案的下标即可,开temp,l,r分别来记录当前序列长度、序列当前左端点、序列当前右端点即可,否则temp++,r++
2.注意特别处理一下如果序列直接到达了末尾这种情况

#include <bits/stdc++.h>
using namespace std;
int a[100005];
int main()
{
    int n;
    cin>>n;
    for(int i=1;i<=n;i++) cin>>a[i];
    int ansl=0,ansr=0,maxx=-1,l=1,r=0;//l记得从1开始
    int temp=1;//当前序列长度
    for(int i=1;i<=n;i++)
    {
        if(a[i]>a[i-1])
        {
            temp++;
            r++;
        }else{
            if(temp>maxx)//如果当前序列长度大于最大的长度
            {
                maxx=temp;
                ansl=l;//更新答案区间下标
                ansr=r;
            }
            temp=1;
            l=r=i;
        }
    }
    //如果这个序列到达了末尾还需要处理一下
    if(temp>maxx){
        maxx=temp;
        ansl=l;
        ansr=r;
    }
    cout<<a[ansl];
    for(int i=ansl+1;i<=ansr;i++) cout<<" "<<a[i];
}

基础实验3-2.2 单链表分段逆转
每K段要进行翻转,也就是相当于进行K次头插法,把每一次头插法的第一个结点,当作下一次头插法的头结点。具体可以看图理解手动模拟。

void K_Reverse(List L,int K)
{
   List t=L->Next;
    int cnt=0;
    while(t){
        cnt++;
        t=t->Next;
    }

    List head=L,new,old,tmp,s;
    //head为每一次头插法的头结点
    //s为每一次头插法的第一个结点,也是下一次头插法的头结点
    //new 和old用来翻转指针将后一个指向前一个
    //tmp 用来往后移动old
        
    for(int i=0;i<cnt/K;i++)
    {
        new=head->Next;
        old=new->Next;
        s=new;
        int j=K-1;
        while(j--)
        {
            tmp=old->Next;
            old->Next=new;
            new=old,old=tmp;
        }
        head->Next=new;
        s->Next=old;
        head=s;
    }
    
    
}

posted on 2024-09-02 12:22  swj2529411658  阅读(7)  评论(0编辑  收藏  举报

导航