7-1 求素数个数
求素数的个数。本题要求编写一个程序,求1~n的素数个数。 要求至少给出两种解法,对于相同的n,给出这两种解法的结果,通过相关数据进行测试,目的是通过对比同一问题不同解法的绝对执行时间体会如何设计“好”的算法。
输入格式:
输入在一行中给出1个整数n(<= 10 000 000)。
输出格式:
对每一组输入,在一行中输出1~n的素数个数。
输入样例1:
5
输出样例1:
3
输入样例2:
14
输出样例2:
6
#include <iostream>
#include <algorithm>
#include <cstring>//memset函数头文件
using namespace std;
const int MAX_N=10000100;
bool p[MAX_N];
int pr[MAX_N];
void Euler() {//欧拉筛法
int cnt = 0;
memset(p, true, sizeof(p));//将p内的数都变成true
p[0] = p[1] = false;//让p[0].p[1]都等于false
for (int i = 2; i < MAX_N; ++i) {
if (p[i]==1)
pr[cnt++] = i;
for (int j = 0; j < cnt && pr[j] * i < MAX_N; ++j) {
p[pr[j] * i] = false;
if (i % pr[j] == 0)
break;
}
}
}
int main(){
Euler();
int n,count=0;
cin >> n;
for(int i = 0;i <= MAX_N;i++){
if(pr[i] <= n)//计算n以内的素数个数
count++;
else
break;
}
cout << count << endl;
return 0;
}
7-2 数组循环左移
本题要求实现一个对数组进行循环左移的简单函数:一个数组a中存有n(>0)个整数,在不允许使用另外数组的前提下,将每个整数循环向左移m(≥0)个位置,即将a中的数据由(a0a1⋯an−1)变换为(am⋯an−1a0a1⋯am−1)(最前面的m个数循环移至最后面的m个位置)。如果还需要考虑程序移动数据的次数尽量少,要如何设计移动的方法?
输入格式:
输入第1行给出正整数n(≤100)和整数m(≥0);第2行给出n个整数,其间以空格分隔。
输出格式:
在一行中输出循环左移m位以后的整数序列,之间用空格分隔,序列结尾不能有多余空格。
输入样例:
8 3
1 2 3 4 5 6 7 8
输出样例:
4 5 6 7 8 1 2 3
#include <stdio.h>
#include <stdlib.h>
int main()
{
int m,n,t;
scanf("%d%d",&n,&m);
int a[n],i,j;
if(m>=n)m=m%n;
for(i=n-1;i>=0;i--){//整体倒序
scanf("%d",&a[i]);
}
for(i=0,j=n-m-1;i<=j;i++,j--){
t=a[i];a[i]=a[j];a[j]=t;
}
for(i=n-m,j=n-1;i<=j;i++,j--){
t=a[i];a[i]=a[j];a[j]=t;
}
int f=1;
for(i=0;i<n;i++){
if(f==1)
{
printf("%d",a[i]);f++;
}
else
printf(" %d",a[i]);
}
}
7-28 两个有序链表序列的合并
已知两个非降序链表序列S1与S2,设计函数构造出S1与S2合并后的新的非降序链表S3。
输入格式:
输入分两行,分别在每行给出由若干个正整数构成的非降序序列,用−1表示序列的结尾(−1不属于这个序列)。数字用空格间隔。
输出格式:
在一行中输出合并后新的非降序链表,数字间用空格分开,结尾不能有多余空格;若新链表为空,输出NULL。
输入样例:
1 3 5 -1
2 4 6 8 10 -1
输出样例:
1 2 3 4 5 6 8 10
#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
typedef int ElemType;
typedef struct LNode
{
ElemType data;
struct LNode* next;
}LinkNode;
LinkNode* scan()
{
int a;
LinkNode*L, *r, *s;
L = (LinkNode*)malloc(sizeof(LinkNode));
r=L;
scanf("%d",&a);
while (a != -1)
{
s =(LinkNode*)malloc(sizeof(LinkNode));
s->data =a;
r->next = s;
r = s;
scanf("%d",&a);
}
r->next = NULL;
return L;
}
LinkNode* CombList(LinkNode*L1, LinkNode*L2)
{
LinkNode*a, *b, *c, *L;
L =(LinkNode*)malloc(sizeof(LinkNode));
a =L1->next;
b =L2->next;
c=L;
while (a != NULL && b != NULL)
{
if (a->data <= b->data) {
c->next = a;
c= a;
a = a->next;
}
else {
c->next = b;
c=b;
b =b->next;
}
}
if(a != NULL)
c->next =a;
else if(b!=NULL)
c->next = b;
L1->next =NULL;
L2->next =NULL;
return L;
}
void DispList(LinkNode*L)
{
LinkNode*p = L->next;
if(p == NULL)
{
printf("NULL");
return ;
}
while (p != NULL)
{ //p不为空,输出其值
printf("%d",p->data);
p=p->next;
if(p != NULL)
printf(" ");
}
}
int main()
{
LinkNode*s1, *s2, *s3;
s1 = scan();
s2 = scan();
s3 = CombList(s1, s2);
DispList(s3);
return 0;
}
7-176 目录树
在ZIP归档文件中,保留着所有压缩文件和目录的相对路径和名称。当使用WinZIP等GUI软件打开ZIP归档文件时,可以从这些信息中重建目录的树状结构。请编写程序实现目录的树状结构的重建工作。
输入格式:
输入首先给出正整数N(≤104),表示ZIP归档文件中的文件和目录的数量。随后N行,每行有如下格式的文件或目录的相对路径和名称(每行不超过260个字符):
路径和名称中的字符仅包括英文字母(区分大小写);
符号“\”仅作为路径分隔符出现;
目录以符号“\”结束;
不存在重复的输入项目;
整个输入大小不超过2MB。
输出格式:
假设所有的路径都相对于root目录。从root目录开始,在输出时每个目录首先输出自己的名字,然后以字典序输出所有子目录,然后以字典序输出所有文件。注意,在输出时,应根据目录的相对关系使用空格进行缩进,每级目录或文件比上一级多缩进2个空格。
输入样例:
7
b
c\
ab\cd
a\bc
ab\d
a\d\a
a\d\z\
输出样例:
root
a
d
z
a
bc
ab
cd
d
c
b
#include <iostream>
#include <string>
#include <cstring>
using namespace std;
typedef struct node//文件或目录的结点
{
char name[300];
struct node* ctl;//指向下一级的目录
struct node* file;//指向下一级的文件
struct node* next;//指向同级的文件或目录
};
struct node root;//定义根节点为全局变量
struct node* ptr = NULL;//定义一个全局的指向node的指针
//ptr的作用:每次插入结点后,(针对同一行的结点)ptr指向新插入的结点,使得下一次插入的时候能直接从ptr开始处理
//如果没有新插入结点(只有一种情况,即有同名目录的时候,ptr直接指向同名的那个结点,然后直接退出插入函数
//当处理完一行数据的时候,ptr指向root,因为每一行都是从root开始处理的
bool smaller(char s1[], char s2[])//按照字典序规则比较两个字符串,s1<s2返回true
{
for (int i = 0; i < 300; i++)
{
if (s1[i] == s2[i])
{
for (int j = i; j < 300; j++)
{
if (s1[j] == '\0' && s2[j] != '\0')
{
return true;
}
if (s1[j] != '\0' && s2[j] == '\0')
{
return false;
}
if (s1[j] < s2[j])
{
return true;
}
else if (s1[j] > s2[j])
{
return false;
}
}
}
else if (s1[i] < s2[i])return true;
else return false;
}
}
bool equal(char s1[], char s2[])//比较两个字符串,相等即返回true
{
for (int i = 0; i < 300; i++)
{
if (s1[i] != s2[i])
{
return false;
}
}
return true;
}
void ins_file(char name[])//插入一个文件结点
{
struct node* s = new struct node;
s->ctl = s->file = s->next = NULL;
strcpy(s->name, name);
if (!ptr->file)
{
ptr->file = s;
}
else
{//遍历文件结点,将s插入到第一个比它大的结点中(字典序排序规则)
struct node* p = ptr->file;//初始化为ptr的file指向的结点
struct node* p_pio = ptr;//前驱结点
int flag = 0;//标志,没有插入,置0;插入了s结点,置1
while (p)
{//重名的文件也要当成两个文件,但是重名目录不需要
if (smaller(s->name, p->name) || equal(s->name, p->name))//如果小于或等于,就可以头插入
{
flag = 1;
s->next = p;
if (p_pio->file == p)//如果上一个结点是上级结点
p_pio->file = s;//则令上一个结点的file指向s
else
p_pio->next = s;//如果是同级结点,则令它的next指向s
break;
}
p_pio = p;//
p = p->next;
}
if (flag == 0)//flag==0,说明上面过程没有插入,所以这里直接将s放最后面
{
p_pio->next = s;//如果没有比s小的,即s应该排在最后
}
}
ptr = s;//ptr需要指向新插入的结点
}
void ins_ctl(char name[])//插入一个目录结点
{
struct node* s = new struct node;
s->ctl = s->file = s->next = NULL;
strcpy(s->name, name);
if (!ptr->ctl)
{
ptr->ctl = s;
}
else
{
struct node* p = ptr->ctl;
struct node* p_pio = ptr;
int flag = 0;
while (p)
{
if (equal(s->name, p->name))
{//文件插入中这一步不需要,因为多同名的文件是要当成多个的,而同名目录可以共用
ptr = p;//s与p同名,所以不用插入s了,直接令ptr指向p,直接return,然后处理下个结点时就会从p开始
return;
}
else if (smaller(s->name, p->name))
{//以下方法与插入文件时相同
flag = 1;
s->next = p;
if (p_pio->ctl == p)
p_pio->ctl = s;
else
p_pio->next = s;
break;
}
p_pio = p;
p = p->next;
}
if (flag == 0)
{
p_pio->next = s;
}
}
ptr = s;
}
void print_sp(int n)//输出空格的函数
{
for (int i = 0; i < n; i++)
cout << ' ';
}
int d = 0;
int cnt = -2;
struct node* p = &root;
void Print(int cnt, struct node* p)//输出最终结果的函数
{
struct node* s = p;
if (!p)return;
print_sp(cnt);
cnt += 2;//输出空格后,cnt增加2
cout << p->name << endl;//输出名字
//用递归输出,先输出完目录,再输出文件的思想
while (s->ctl)
{
Print(cnt, s->ctl);
s->ctl = s->ctl->next;
}
while (p->file)
{
Print(cnt, p->file);
p->file = p->file->next;
}
}
int main()
{
root.ctl = root.file = root.next = NULL;
strcpy(root.name, "root");
int n; cin >> n;
for (int i = 0; i < n; i++)
{
char s[300];
char s1[300];
cin >> s;
ptr = &root;//ptr初始化为root,因为每行输入都是从root开始处理的
//全局指针ptr永远代表某一结点插入时开始处理的位置
for (int j = 0, k = 0; j < 300; k++, j++)
{
if (s[j] == '\\')
{
s1[j] = '\0';
ins_ctl(s1);
k = -1;
memset(s1, 0, sizeof(char) * 300);
continue;
}
else if (s[j] == '\0')
{
if (s[j - 1] == '\\')break;//这一句作用是处理如“a\b\”等最后的目录下没有文件的情况
s1[j] = '\0';
ins_file(s1);
k = -1;//设为-1是因为本次循环结束进入下一次循环k+1==0,刚好从0开始
memset(s1, 0, sizeof(char) * 300);
break;
}
else
{
s1[k] = s[j];//将输入一行中的某个结点的名字放到s1中
}
}
}
Print(0, &root);
return 0;
}
7-179 畅通工程之最低成本建设问题
某地区经过对城镇交通状况的调查,得到现有城镇间快速道路的统计数据,并提出“畅通工程”的目标:使整个地区任何两个城镇间都可以实现快速交通(但不一定有直接的快速道路相连,只要互相间接通过快速路可达即可)。现得到城镇道路统计表,表中列出了有可能建设成快速路的若干条道路的成本,求畅通工程需要的最低成本。
输入格式:
输入的第一行给出城镇数目N (1<N≤1000)和候选道路数目M≤3N;随后的M行,每行给出3个正整数,分别是该条道路直接连通的两个城镇的编号(从1编号到N)以及该道路改建的预算成本。
输出格式:
输出畅通工程需要的最低成本。如果输入数据不足以保证畅通,则输出“Impossible”。
输入样例1:
6 15
1 2 5
1 3 3
1 4 7
1 5 4
1 6 2
2 3 4
2 4 6
2 5 2
2 6 6
3 4 6
3 5 1
3 6 1
4 5 10
4 6 8
5 6 3
输出样例1:
12
输入样例2:
5 4
1 2 1
2 3 2
3 1 3
4 5 4
输出样例2:
Impossible
#include<stdio.h>
#include<algorithm>
using namespace std;
int G[1002][1002];
int d[1002]; //用来记录顶点与城镇间的最小花费
bool vis[1003]={false}; //用来做标记
int inf=0xfffffff;
int ans,n,q;
int a() //默认从第一个城镇开始,函数返回最小生成树边权之和
{
d[1]=0; //第一个城镇到自身的最小花费为0;
ans=0;
for(int i=1;i<=n;i++)
{
int u=-1,min=inf;
for(int j=1;j<=n;j++)
{
if(vis[j]==false&&d[j]<min)
{
u=j;
min=d[j];
} //用来判断未访问点中 d[]最小的;
}
if(u==-1)
return -1; //如果u值为-1,则表示两地点间不连通;
vis[u]=true;
ans+=d[u]; //进行最小边权值相加
for(int v=1;v<=n;v++)
{
if(vis[v]==false&&G[u][v]!=inf&&G[u][v]<d[v])
{
d[v]=G[u][v];
} //比较目前城市到目标城市的距离和起始点到目标城市的距离
}
}
return ans;
}
int main()
{
int u,v,w,x,m;
scanf("%d%d",&n,&m);
for(int i=0;i<1002;i++)
{
d[i]=inf;
vis[i]=false;
for(int j=0;j<1002;j++)
{
G[i][j]=inf;
}
} //以上为初始化
while(m--)
{
scanf("%d%d%d",&u,&v,&w);
G[u][v]=w;G[v][u]=w;//双向联通
}
int ans=a();
if(ans==-1)
printf("Impossible\n");
else
printf("%d\n",ans);
return 0;
}
7-207 寻找大富翁
胡润研究院的调查显示,截至2017年底,中国个人资产超过1亿元的高净值人群达15万人。假设给出N个人的个人资产值,请快速找出资产排前M位的大富翁。
输入格式:
输入首先给出两个正整数N(≤106)和M(≤10),其中N为总人数,M为需要找出的大富翁数;接下来一行给出N个人的个人资产值,以百万元为单位,为不超过长整型范围的整数。数字间以空格分隔。
输出格式:
在一行内按非递增顺序输出资产排前M位的大富翁的个人资产值。数字间以空格分隔,但结尾不得有多余空格。
输入样例:
8 3
8 12 7 3 20 9 5 18
输出样例:
20 18 12
#include<stdio.h>
void HeapAdjust(int a[],int i,int m)
{
int k,t;
t=a[i];
k=2*i+1;
while (k < m)
{
if((k<m-1) && (a[k] < a[k+1])) k ++;
if (t < a[k])
{
a[i] = a[k];
i = k;
k = 2 * i + 1;
}
else break;
}
a[i] = t;
}
void HeapSort(int a[],int n) //a 为排序数组,n为数组大小(编号0-n-1)
{
int i,k;
for (i = n/2-1; i>=0; i--) HeapAdjust(a,i,n);
for (i = n-1; i >= 1; i--)
{
k = a[0];
a[0] = a[i];
a[i] = k;
HeapAdjust(a,0,i);
}
}
int main()
{
long int n;
int m;
scanf("%ld %d",&n,&m);
int a[n];
int i;
for(i=0; i<n; i++)
{
scanf("%d",&a[i]);
}
HeapSort(a,n);
int t=n-1;
while(m>1&&t>0)
{
printf("%d ",a[t]);
t--;
m--;
}
printf("%d\n",a[t]);
return 0;
}
7-209 最长连续递增子序列
给定一个顺序存储的线性表,请设计一个算法查找该线性表中最长的连续递增子序列。例如,(1,9,2,5,7,3,4,6,8,0)中最长的递增子序列为(3,4,6,8)。
输入格式:
输入第1行给出正整数n(≤105);第2行给出n个整数,其间以空格分隔。
输出格式:
在一行中输出第一次出现的最长连续递增子序列,数字之间用空格分隔,序列结尾不能有多余空格。
输入样例:
15
1 9 2 5 7 3 4 6 8 0 11 15 17 17 10
输出样例:
3 4 6 8
#include <stdio.h>
#include <stdlib.h>
struct node
{
int data;
int count;
}s[100001];
int main()
{
int n,i,j;
scanf("%d",&n);
for(i=0;i<n;i++)
{
scanf("%d",&s[i].data);
s[i].count=1;
}
for(i=0;i<n;i++)
{
for(j=i+1;j<n+1;j++)
{
if(s[j].data>s[j-1].data)
s[i].count++;
else
break;
}
}
int sum=0,t,z;
for(i=0;i<n;i++)
{
if(sum<s[i].count)
{sum=s[i].count;
t=i;}
}
for(z=t;z<sum+t-1;z++)
{
printf("%d ",s[z].data);
}
printf("%d",s[z].data);
}
7-3 迷你搜索引擎
实现一种简单的搜索引擎功能,快速满足多达105条关键字查询请求。
输入格式:
输入首先给出正整数 N(≤ 100),为文件总数。随后按以下格式给出每个文件的内容:第一行给出文件的标题,随后给出不超过 100 行的文件正文,最后在一行中只给出一个字符 #,表示文件结束。每行不超过 50 个字符。在 N 个文件内容结束之后,给出查询总数 M(≤105),随后 M 行,每行给出不超过 10 个英文单词,其间以空格分隔,每个单词不超过 10 个英文字母,不区分大小写。
输出格式:
针对每一条查询,首先在一行中输出包含全部该查询单词的文件总数;如果总数为 0,则输出 Not Found。如果有找到符合条件的文件,则按输入的先后顺序输出这些文件,格式为:第1行输出文件标题;随后顺序输出包含查询单词的那些行内容。注意不能把相同的一行重复输出。
输入样例:
4
A00
Gold
silver truck
#
A01
Shipment of gold
damaged
in a fire
#
A02
Delivery
of silver
arrived in
a silver
truck
#
A03
Shipment of gold
arrived in
a truck
#
2
what ever
silver truck
输出样例:
0
Not Found
2
A00
silver truck
A02
of silver
a silver
truck
#include<string>
#include<cstdio>
#include<vector>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<set>
using namespace std;
string fileName[100];
string file[100][100];//第i个文件第j行
const int MAXTABLESIZE = 300009;
struct nodeB
{
int fileNum;
set<int> line;
};
struct nodeA
{
int lastFile;
int lastLine;
string word;
vector<nodeB> arrayB;
};
/*Hash*/
struct HashTbl
{
int TableSize;
nodeA* Cells;
};
typedef struct HashTbl* HashTable;
HashTable CreateTable()
{
int i;
HashTable H = new HashTbl;
H->TableSize = MAXTABLESIZE;
H->Cells = new nodeA[MAXTABLESIZE];
for(i=0; i<H->TableSize; i++)
{
H->Cells[i].lastFile = -1;
H->Cells[i].lastLine = -1;
}
return H;
}
int Hash(string Key, int P)
{
int i,len,N;
unsigned int h = 0;
for(i=0; i<N; i++)
{
h = (h<<5) + (Key[i] - 'a');
}
return (h&(32*32*32-1))%P;
}
int Find(HashTable H, string Key)//线形探测法解决冲突
{
int newPos, curPos,cnt = 0;//cnt表示冲突次数
newPos = curPos = Hash(Key, H->TableSize);
while((H->Cells[newPos].lastFile!=-1)&&(H->Cells[newPos].word!=Key))
{
cnt++;
newPos = curPos + cnt;
if(newPos>=H->TableSize)
newPos-=H->TableSize;
}
return newPos;
}
void Insert(HashTable H, string Key, int file, int line)
{
nodeB* tmp;
int pos = Find(H,Key);
if(H->Cells[pos].lastFile==-1)//表示这个位置为空,那么要先插入单词,再插入文件和行号
{
H->Cells[pos].lastFile = file;
H->Cells[pos].lastLine = line;
H->Cells[pos].word = Key;//printf("插入了%s\n",Key.c_str());
tmp = new nodeB;
tmp->fileNum = file; tmp->line.insert(line);
H->Cells[pos].arrayB.push_back(*tmp);
}
else if(H->Cells[pos].lastFile!=file)
{
H->Cells[pos].lastFile = file;
H->Cells[pos].lastLine = line;
tmp = new nodeB;
tmp->fileNum = file; tmp->line.insert(line);
H->Cells[pos].arrayB.push_back(*tmp);
}
else if(H->Cells[pos].lastLine!=line)
{
H->Cells[pos].arrayB[H->Cells[pos].arrayB.size()-1].line.insert(line);
}
}
/*Hash*/
void readFile(HashTable H)
{
int N,i,j,k;
string str,buff;
scanf("%d",&N);getchar();
char *cstr,*p;
for(i=0; i<N; i++)//i是文件的编号从0~N-1
{
getline(cin,fileName[i]);j = 0;//j代表行号
while(getline(cin,str), str != "#")
{
file[i][j] = str;
cstr = new char[str.size()+1];
strcpy(cstr,str.c_str());
p = strtok(cstr," ");
while(p!=NULL)
{
for(k=0; k<strlen(p); k++)
{
if((p[k]>='A')&&(p[k]<='Z'))
{
p[k] = p[k] + 32;
}
}
Insert(H,p,i,j);
p = strtok(NULL," ");
}
j++;
}
}
}
void Intersect(vector<nodeB> &v1, vector<nodeB> &v2, vector<nodeB> &v)
{
vector<nodeB>::iterator it1,it2;
set<int>::iterator it3,it4;
it1 = v1.begin(); it2 = v2.begin();
while(it1!=v1.end()&&it2!=v2.end())
{
if(it1->fileNum==it2->fileNum)
{
nodeB* tmp = new nodeB;
tmp->fileNum = it1->fileNum;
for(it3 = it1->line.begin();it3!=it1->line.end();it3++)
{
tmp->line.insert(*it3);
}
for(it4 = it2->line.begin();it4!=it2->line.end();it4++)
{
tmp->line.insert(*it4);
}
v.push_back(*tmp);
it1++;it2++;
}
else if(it1->fileNum<it2->fileNum)
{
it1++;
}
else
{
it2++;
}
}
}
void query(HashTable H)
{
int i,k; string str;
char* cstr,*p;
string buff[10];
getline(cin,str);
cstr = new char[str.size()+1];
strcpy(cstr,str.c_str());
p = strtok(cstr," ");//printf("%s\n", p);
int cnt = 0;
while(p!=NULL)
{
char* tmp;tmp = p;
while(*tmp!='\0')
{
if(*tmp>='A'&&*tmp<='Z')
{
*tmp = *tmp+32;
}
tmp++;
}
buff[cnt] = p;//cout<<buff[cnt]<<endl;
cnt++;
p = strtok(NULL," ");
}
vector<nodeB> vi;int pos;vector<nodeB> v;
for(i=0; i<cnt; i++)
{
pos = Find(H,buff[i]);//cout<<"单词是"<<H->Cells[pos].word<<endl;
if(i==0)
{
vi.insert(vi.begin(),H->Cells[pos].arrayB.begin(),H->Cells[pos].arrayB.end());
}
else
{
Intersect(vi,H->Cells[pos].arrayB,v);
vi.clear();
vi.insert(vi.begin(),v.begin(),v.end());
v.clear();
}
}
cout<<vi.size()<<endl;
if(vi.size()==0)
{
printf("Not Found\n");
return;
}
for(auto it = vi.begin(); it!=vi.end(); it++)
{
printf("%s\n",fileName[it->fileNum].c_str());
for(auto it5=it->line.begin(); it5!=it->line.end(); it5++)
{
printf("%s\n",file[it->fileNum][*it5].c_str());
}
}
}
int main()
{
HashTable H = CreateTable();
readFile(H);
int M;
scanf("%d",&M);getchar();
for(int i=0; i<M;i++)
{
query(H);
}
return 0;
}
7-233 排序
给定N个(长整型范围内的)整数,要求输出从小到大排序后的结果。
本题旨在测试各种不同的排序算法在各种数据情况下的表现。各组测试数据特点如下:
数据1:只有1个元素;
数据2:11个不相同的整数,测试基本正确性;
数据3:103个随机整数;
数据4:104个随机整数;
数据5:105个随机整数;
数据6:105个顺序整数;
数据7:105个逆序整数;
数据8:105个基本有序的整数;
数据9:105个随机正整数,每个数字不超过1000。
输入格式:
输入第一行给出正整数N(≤105),随后一行给出N个(长整型范围内的)整数,其间以空格分隔。
输出格式:
在一行中输出从小到大排序后的结果,数字间以1个空格分隔,行末不得有多余空格。
输入样例:
11
4 981 10 -17 0 -20 29 50 8 43 -5
输出样例:
-20 -17 -5 0 4 8 10 29 43 50 981
#include<stdio.h>
int fun(int a[],int n)
{
int i,j,t;
i=0; //记录第一个元素的下标
j=n-1; //记录最后一个元素的下标
if(n<=0)return 0;
t=a[0]; //拍照技术,被压了以后好复原,也是作为标准数
while(i<j)
{
while(i<j)
{
if(t>a[j]){a[i]=a[j];break;}
j--; //j不停的往前扫描
}
while(i<j)
{
if(t<a[i]){a[j]=a[i];break;}
i++; //i不停的往后扫描
}
a[i]=t;
}
fun(a,i); //对前半部分进行递归
fun(a+i+1,n-i-1); //对后半部分进行递归
}
int main()
{
int a[101100],n,i;
scanf("%d",&n);
for(i=0;i<n;i++)scanf("%d",&a[i]);
fun(a,n);
for(i=0;i<n;i++)
{
printf("%d",a[i]);
if(i+1!=n)printf(" ");
}
return 0;
}
7-237 选择法排序
本题要求将给定的n个整数从大到小排序后输出。
输入格式:
输入第一行给出一个不超过10的正整数n。第二行给出n个整数,其间以空格分隔。
输出格式:
在一行中输出从大到小有序的数列,相邻数字间有一个空格,行末不得有多余空格。
输入样例:
4
5 1 7 6
输出样例:
7 6 5 1
#include <stdio.h>
#define MAXS 10
int main(void)
{
int temp[MAXS], n;
scanf("%d",&n);
for(int i = 0; i< n; i++) //读取数据
scanf("%d", &temp[i]);
for (int i = 0; i < n - 1; i++) // 排序
{
for (int j = 0; j < n - i - 1; j++)
{
if (temp[j] < temp[j + 1])
{
int tempdigit = temp[j];
temp[j] = temp[j+1];
temp[j+1] = tempdigit;
}
}
}
for (int i = 0; i < n; i++) //输出
{
if (i != 0) printf(" %d", temp[i]);
else printf("%d", temp[i]);
}
printf("\n");
return 0;
}
7-241 冒泡法排序
将N个整数按从小到大排序的冒泡排序法是这样工作的:从头到尾比较相邻两个元素,如果前面的元素大于其紧随的后面元素,则交换它们。通过一遍扫描,则最后一个元素必定是最大的元素。然后用同样的方法对前N−1个元素进行第二遍扫描。依此类推,最后只需处理两个元素,就完成了对N个数的排序。
本题要求对任意给定的K(<N),输出扫描完第K遍后的中间结果数列。
输入格式:
输入在第1行中给出N和K(1≤K<N≤100),在第2行中给出N个待排序的整数,数字间以空格分隔。
输出格式:
在一行中输出冒泡排序法扫描完第K遍后的中间结果数列,数字间以空格分隔,但末尾不得有多余空格。
输入样例:
6 2
2 3 5 1 6 4
输出样例:
2 1 3 4 5 6
#include<stdio.h>
int main()
{
int n,k;
scanf("%d%d",&n,&k);
int data[n],i=0,j;
while(i<n)
scanf("%d",&data[i++]);
for(i=1;i<=k;i++)
{
for(j=0;j<n-i;j++)
{
if(data[j]>data[j+1])
{
int temp=data[j];
data[j]=data[j+1];
data[j+1]=temp;
}
}
}
i=0;
while(i<n-1)
printf("%d ",data[i++]);
printf("%d",data[i]);
}
7-266 堆栈操作合法性
假设以S和X分别表示入栈和出栈操作。如果根据一个仅由S和X构成的序列,对一个空堆栈进行操作,相应操作均可行(如没有出现删除时栈空)且最后状态也是栈空,则称该序列是合法的堆栈操作序列。请编写程序,输入S和X序列,判断该序列是否合法。
输入格式:
输入第一行给出两个正整数N和M,其中N是待测序列的个数,M(≤50)是堆栈的最大容量。随后N行,每行中给出一个仅由S和X构成的序列。序列保证不为空,且长度不超过100。
输出格式:
对每个序列,在一行中输出YES如果该序列是合法的堆栈操作序列,或NO如果不是。
输入样例:
4 10
SSSXXSXXSX
SSSXXSXXS
SSSSSSSSSSXSSXXXXXXXXXXX
SSSXXSXXX
输出样例:
YES
NO
NO
NO
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
//函数状态码定义
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
typedef int Position;
typedef char ElementType;
struct SNode {
ElementType *Data; //存储元素的数组
Position Top; //栈顶指针
int MaxSize; //堆栈最大容量
};
typedef struct SNode *Stack;
Stack CreateStack( int MaxSize )
{
Stack S = (Stack)malloc(sizeof(struct SNode));
S->Data = (ElementType *)malloc(MaxSize * sizeof(ElementType));
S->Top = -1;
S->MaxSize = MaxSize;
return S;
}
bool IsFull( Stack S )
{
return (S->Top == S->MaxSize-1);
}
bool Push( Stack S, ElementType X )
{
if ( IsFull(S) ) {
//printf("堆栈满");
return false;
}
else {
S->Data[++(S->Top)] = X;
return true;
}
}
bool IsEmpty( Stack S )
{
return (S->Top == -1);
}
ElementType Pop( Stack S )
{
if ( IsEmpty(S) ) {
//printf("堆栈空");
return ERROR;
}
else
return ( S->Data[(S->Top)--] );
}
int main() {
int N = 0, M = 0;
scanf("%d%d", &N, &M);
for(int i = 0; i < N; i++) {
bool Flag = true; //判断是否是正确地栈
Stack s1;
s1 = CreateStack(M);
char str[105];
scanf("%s", str);
int len = strlen(str);
for (int j = 0; j < len; j++) {
if (str[j] == 'S') {
if (IsFull(s1)) {
Flag = false;
printf("NO\n");
break;
}
Push(s1, 'S');
} else {
if (IsEmpty(s1)) {
Flag = false;
printf("NO\n");
break;
}
Pop(s1);
}
}
if (Flag && IsEmpty(s1)) {
printf("YES\n");
}
if(Flag && !IsEmpty(s1)){
printf("NO\n");
}
}
}