数据结构复习题——编程题

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)变换为(aman−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行中给出NK(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");
        }
    }
}
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值