数据结构题目

178 整型关键字的平方探测法散列

将给定的无重复正整数序列插入一个散列表,输出每个输入的数字在表中的位置。所用的散列函数是 H(key)=key%TSize,其中 TSize 是散列表的表长。要求用平方探测法(只增不减,即H(Key)+i2)解决冲突。注意散列表的表长最好是个素数。如果输入给定的表长不是素数,你必须将表长重新定义为大于给定表长的最小素数。

输入格式:

首先第一行给出两个正整数 MSize(≤104)和 N(≤MSize),分别对应输入的表长和输入数字的个数。随后第二行给出 N 个不重复的正整数,数字间以空格分隔。

输出格式:

在一行中按照输入的顺序给出每个数字在散列表中的位置(下标从 0 开始)。如果某个数字无法插入,就在其位置上输出 -。输出间以 1 个空格分隔,行首尾不得有多余空格。

#include <stdio.h>
#include <stdlib.h>
 
#define bool char
#define true 1
#define false 0
 
 
//判断是否素数
bool SuShu(int n)
{
    if(n == 1)
        return false;
    else if(n == 2)
        return true;
 
    int mark = 1;
    for(int i = 2; i < n; i++)
    {
        if(n%i == 0)
        {
            mark = 0;
            break;
        }
    }
    if(mark == 1)
        return true;
    else
        return false;
}
 
//如果不是素数就加一
int Add(int num)
{
    while(!SuShu(num))
    {
        num++;
    }
    return num;
}
 
//哈希表结构
typedef struct HashTable
{
    int data;
 
} HashTable;
 
//存储方式
void Cunchu(HashTable* H, int num[], int m, int n)
{
 
    for(int i = 0; i < n; i++)
    {
 
        int key = num[i]%m;
        //被占用时
        int j;
        int pos = key;
        for(j = 1; H[key].data != -1; j++)
        {
            key = (pos+j*j)%m;
            if(j == m)
            {
                break;
            }
 
        }
        if(j == m)
        {
            if(i == 0)
                printf("-");
            else
                printf(" -");
        }
        else
        {
            if(i == 0)
                printf("%d",key);
            else
                printf(" %d",key);
 
            H[key].data = num[i];
        }
    }
}
 
int main()
{
    //m是表长,n是数字个数
    int m, n, i;
    scanf("%d %d",&m,&n);
    int num[n];
    for(i = 0; i < n; i++)
    {
        scanf("%d",&num[i]);
    }
 
    //对表长进行余数处理
    m = Add(m);
 
 
    HashTable H[m];
    //-1代表还没被占用
    for(i = 0; i < m; i++)
    {
        H[i].data = -1;
    }
    //开始存储
    Cunchu(H, num, m, n);
    return 0;
}

179 PAT排名汇总

每次考试会在若干个不同的考点同时举行,每个考点用局域网,产生本考点的成绩。考试结束后,各个考点的成绩将即刻汇总成一张总的排名表。现在就请你写一个程序自动归并各个考点的成绩并生成总排名表。

输入格式:

输入的第一行给出一个正整数N(≤100),代表考点总数。随后给出N个考点的成绩,格式为:首先一行给出正整数K(≤300),代表该考点的考生总数;随后K行,每行给出1个考生的信息,包括考号(由13位整数字组成)和得分(为[0,100]区间内的整数),中间用空格分隔。

输出格式:

首先在第一行里输出考生总数。随后输出汇总的排名表,每个考生的信息占一行,顺序为:考号、最终排名、考点编号、在该考点的排名。其中考点按输入给出的顺序从1到N编号。考生的输出须按最终排名的非递减顺序输出,获得相同分数的考生应有相同名次,并按考号的递增顺序输出。

#include <bits/stdc++.h>
using namespace std;
const int N=101;
struct stu{
    string id;
    int po;
    int num;//在考点排名 
    int score;//成绩 
}xx[30005];
int cmp(stu a,stu b){
    if(a.score!=b.score) return a.score>b.score;
    else return a.id<b.id;
}
int main()
{
    int n,k,s=0;
    cin>>n;
    for(int i=0;i<n;i++){
        cin>>k;
        for(int j=0;j<k;j++){
            cin>>xx[s+j].id>>xx[s+j].score;
            xx[s+j].po=i+1;
        }
        sort(xx+s,xx+k+s,cmp);
        int pre=-1;
        for(int j=0,num=0;j<k;j++){
            if(xx[s+j].score!=pre) num=j+1;
            xx[s+j].num=num;
            pre=xx[j+s].score;
        }
        s=s+k;
    }
    int pre=-1;
    sort(xx,xx+s,cmp);
    cout<<s<<endl;
    for(int i=0,num=0;i<s;i++){
        if(xx[i].score!=pre) num=i+1;
        cout<<xx[i].id<<" "<<num<<" "<<xx[i].po<<" "<<xx[i].num<<endl;
        pre=xx[i].score;
    }
    return 0;
}

180 插入排序还是归并排序

根据维基百科的定义:

插入排序是迭代算法,逐一获得输入数据,逐步产生有序的输出序列。每步迭代中,算法从输入序列中取出一元素,将之插入有序序列中正确的位置。如此迭代直到全部元素有序。

归并排序进行如下迭代操作:首先将原始序列看成 N 个只包含 1 个元素的有序子序列,然后每次迭代归并两个相邻的有序子序列,直到最后只剩下 1 个有序的序列。

现给定原始序列和由某排序算法产生的中间序列,请你判断该算法究竟是哪种排序算法?

输入格式:

输入在第一行给出正整数 N (≤100);随后一行给出原始序列的 N 个整数;最后一行给出由某排序算法产生的中间序列。这里假设排序的目标序列是升序。数字间以空格分隔。

输出格式:

首先在第 1 行中输出Insertion Sort表示插入排序、或Merge Sort表示归并排序;然后在第 2 行中输出用该排序算法再迭代一轮的结果序列。题目保证每组测试的结果是唯一的。数字间以空格分隔,且行首尾不得有多余空格。

#include<bits/stdc++.h>
#include<algorithm>
using namespace std;
int a[200],b[200]; //a是原数组,b是中间序列数组;
int main()
{
    int N,j,i;
    cin>>N;
    for( i=0;i<N;i++)
        scanf("%d",&a[i]);
    for(i=0;i<N;i++)
        scanf("%d",&b[i]);
    int flag=-1,tag=1,count=0,dex;
    for( i=1;i<N;i++){//判断是归并还是插入
        if(count<1){
            if(b[i]<b[i-1])
            {
                tag=0;
                dex=i;//记录不符合非递减规则的第一个出现元素的下标
                count++;
            }    
        }
        if(tag==0)
        {
            if(a[i]==b[i])
               flag=1;
            else{
                flag=0;
                break;
            }
        }
    }
    if(flag){//插入
         cout<<"Insertion Sort"<<endl;
        sort(b,b+dex+1);
         for(j=0;j<N-1;j++)
            cout<<b[j]<<" ";
        cout<<b[j]<<endl;
    } 
    else {//归并
        cout<<"Merge Sort"<<endl;
        int cnt1=1,cnt2=1,cnt,m=0,z=0;
        for(i=1;i<N;i++)//判断头两个相邻非递减序列的长度,cnt1和cnt2;
        {
            if(m<1){
                if(b[i]>=b[i-1])
                       cnt1++;
                else
                    m++;
            }
            else{
                if(b[i]>=b[i-1])
                       cnt2++;
                else
                    break;
            }    
        }
        cnt=cnt1<cnt2?cnt1:cnt2;//取cnt1和cnt2的较小值
        int x=N/(2*cnt)*(2*cnt);
        while(z+2*cnt<=N){
            sort(b+z,b+z+2*cnt);
            z+=2*cnt;    
        }
        if(N%(2*cnt)!=0){//末尾元素得处理
            sort(b+x,b+N);
        }
        for( j=0;j<N-1;j++)
            cout<<b[j]<<" ";
        cout<<b[j]<<endl;
    } 
    return 0;
 } 
 

181 两个有序链表序列的合并

已知两个非降序链表序列S1与S2,设计函数构造出S1与S2合并后的新的非降序链表S3。

输入格式:

输入分两行,分别在每行给出由若干个正整数构成的非降序序列,用−1表示序列的结尾(−1不属于这个序列)。数字用空格间隔。

输出格式:

在一行中输出合并后新的非降序链表,数字间用空格分开,结尾不能有多余空格;若新链表为空,输出NULL

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<algorithm>
using namespace std;
typedef int ElemType;
typedef struct Node
{
    ElemType date;
    struct Node* next;
} Node,*LinkList; /*指向结构体结点的指针*/
void InitList(LinkList &L)/*&这里的作用是引用,&引用名=目标变量名*/
{
    L=(LinkList)malloc(sizeof(Node));/*初始头结点*/
    L->next=NULL;
}
void GreatFromTail(LinkList &L)/*尾插法建表*/
{
    Node *r,*s;
    int flag=1;
    r=L;/*动态指向链表的尾部*/
    while(flag)
    {
        ElemType q;
        scanf("%d",&q);
        if(q!=-1)
        {
            s=(Node*)malloc(sizeof(Node));
            s->date=q;
            r->next=s;
            r=s;
        }
        else
        {
            flag=0;
            r->next=NULL;
        }
    }
}
void MergeLinkList(LinkList &LA,LinkList &LB)
{
    Node *pa,*pb,*r;
    LinkList LC;
    pa=LA->next;/*pa,pb分别指向第一个结点*/
    pb=LB->next;
    LC=LA;
    LC->next=NULL;/*LC初始为空表*/
    r=LC;/*r指向LC的尾部*/
    while(pa!=NULL&&pb!=NULL)
    {
        if(pa->date<=pb->date)
        {
            r->next=pa;
            r=pa;
            pa=pa->next;
        }
        else
        {
            r->next=pb;
            r=pb;
            pb=pb->next;
        }
    }
    if(pa)
        r->next=pa;/*不管后面剩几个元素,把开头连上了,后面就都连上了*/
    else
        r->next=pb;
    if(LC->next==NULL)
        printf("NULL");
    else
    {
        LC=LC->next;
        printf("%d",LC->date);
        LC=LC->next;
        while(LC!=NULL)
        {
            printf(" %d",LC->date);
            LC=LC->next;
        }
        printf("\n");
    }
}
int main()
{
    LinkList LA,LB;
    InitList(LA);
    InitList(LB);
    GreatFromTail(LA);
    GreatFromTail(LB);
    MergeLinkList(LA,LB);
    return 0;
}
 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值