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;
}