北航数据结构期中测试编程题解析

编程题1

【问题描述】

有一种基于环的选择排序方法,其(从小至大排序)主要原理如下:

1.首先将待排序的数据构成一个数据环;

2.从环当前位置(初始时为待排序的第一个数据所在位置)开始按顺时针遍历环,从中找到当前环中最小元素;

3.将当前位置移至最小元素的下一元素位置,并将最小元素从环中取出(得到一个排好序的元素);

4.重复步骤2和3,直到环中没有元素。

编写程序,从标准输入中读取n个无序且不同的整数,利用环选择排序方法对其进行从小至大排序。要求每得到一个当前最小元素就输出从当前元素开始,到最小元素所经过的环中数据。

假如读入下面10个整数:

12 0 -200 36 187 -5 21 7600 11 -6

可将这10个整数按照读入顺序顺时针连接起来形成如下图的环:

【输入形式】

先从控制台读入一个整数n(n大于等于1,小于等于100),然后在下一行输入n个无序且不同的整数,各整数间以一个空格分隔。

【输出形式】

在屏幕上分行输出排序过程中每得到一个环中最小数据时所经历的环中的数据(包括该最小数据),各整数间以一个空格分隔,每行末尾整数后也有一个空格。

【样例输入】

10

12 0 -200 36 187 -5 21 7600 11 -6

【样例输出】

12 0 -200

36 187 -5 21 7600 11 -6

12 0 36 187 -5

21 7600 11 12 0

36 187 21 7600 11

12

36 187 21

7600 36

187

7600

【样例说明】

输入了10个整数,组成了如上图的环。从读入的第一个整数12开始,找到环中最小的整数-200,输出所经过的环中数据12 0 -200,然后将-200从环中删除,继续从下一个数据36开始,在环中找到最小的整数-6,并输出经过的环中数据,依次类推,直至环中没有数据,这样输出的每行最后一个元素形成了数据从小到大排序。

【评分标准】

该程序要求编程实现数据的循环查找删除操作,提交程序文件名为sort.c。

解析

【代码思路】

本题主要考察循环链表的创建,在循环链表中查找元素及删除元素等知识。代码设计思路如下:

1.用尾插法构造循环链表;

2.找到循环链表中的最小值的位置和最小值的前驱;

3.打印从当前位置到最小值之间的结点;

4.删除最小值结点;

5.重复步骤2、3、4直到链表中只剩下一个结点(curre->next == curre)为止;

6.打印最后一个结点,并释放存储空间。

【源代码】

//sort.c
#include<stdio.h>
#include<stdlib.h>
typedef struct ListNode{
    int data;
    struct ListNode *next;
}ListNode;

ListNode* CreateList()
{
    int n;
    scanf("%d", &n);
    int data;
    scanf("%d", &data);

    ListNode*list, *p,*q;
    list = (ListNode*)malloc(sizeof(ListNode));
    list->next = NULL;
    list->data = data;

    q = list;
    for (int i = 1; i < n; ++i)
    {
        p = (ListNode*)malloc(sizeof(ListNode));
        scanf("%d", &data);
        p->data = data;
        p->next = NULL;
        q->next = p;
        q = p;
    }
    p->next = list;
    return list;
}

ListNode* FindMin(ListNode*list, ListNode**pre)
{//找到最小的结点, *pre指向最小结点的前一个结点
    ListNode*p = list;
    ListNode* q,*ppre;
    int min;
    min = p->data;
    ppre = NULL;
    do
    {
        if (p->data <= min)
        {
            min = p->data;
            q = p;
            *pre = ppre;
        }
        ppre = p;
        p = p->next;
    
    } while (p != list);
    if (*pre == NULL)
    {
        while (p->next != list) p = p->next;
        *pre = p;
    }
    return q;
}

void print(ListNode*curre, ListNode*minpos)
{//打印从curre到minpos之间的结点(包含端点)
    ListNode*p;
    p = curre;
    while (p != minpos)
    {
        printf("%d ", p->data);
        p = p->next;
    }
    printf("%d \n", p->data);
}

void solve(ListNode*list)
{
    ListNode* minpos, *curre,*minpre;
    curre = list;

    while (curre->next != curre)
    {
        minpos = FindMin(curre, &minpre);
        print(curre, minpos);

        //删除minpos指向的结点
        minpre->next = minpos->next; free(minpos);
        curre = minpre->next;
    }

    //打印最后一个结点
    printf("%d \n", curre->data); free(curre);
}

int main()
{
    freopen("1.txt", "r", stdin);
    ListNode *list,*p;
    list = CreateList();
    solve(list);
}//运行成功 2019年4月23日11:37:35

 

编程题2:格式控制输出模拟

【问题描述】

在C语言中,标准库函数printf可进行格式输出。编写程序,实现一种类似printf中的字符串格式输出,其从控制台读入一个格式控制字符和一行待输出的字符串,然后按照该格式控制串中的格式要求将该字符串输出到控制台。格式控制串的格式要求如下:

%[-]m:nS

格式控制串除了末尾有换行符外没有其他空白符;第一个字符是“%”;中括号表示其内字符可省略,字符“-”若省略,表示输出字符串靠左对齐,否则表示靠右对齐;m和n是大于0小于100的整数,两整数之间以字符“:”分隔;m表示只输出字符串中的前m个字符,若m大于字符串的长度,则表示字符串全部输出;n表示输出字符串至少占n个字符宽度,若n大于待输出的字符串长度,则多余的位置以字符‘#’填充,若n小于等于待输出的字符串长度,则按照实际字符串输出,无需填充。

【输入形式】

从控制台读入格式控制串和待输出的字符串,第一行为格式控制串,第二行为待输出的字符串(字符串长度不超过100),第二行末尾的换行符不属于待输出的字符串。

【输出形式】

按照上述格式控制要求,将输入的第二行字符串输出到控制台。

【样例1输入】

%-20:30S

Hello,word!

【样例1输出】

##################Hello,word!

【样例1说明】

根据第一行的格式控制要求,要将第二行的前20个字符按照右对齐输出,最少占30个字符的宽度,因为待输出的字符串只有12个字符(注意:字符w前有个空格),所以要全部输出,并且在左边填充18个‘#’字符。

【样例2输入】

%8:30S

Hello,word!

【样例2输出】

Hello,w######################

【样例2说明】

根据第一行的格式控制要求,要将第二行的前8个字符按照左对齐输出,最少占30个字符的宽度。待输出的字符串有12个字符,只输出前8个字符,并且在右边填充22个“#”字符。

【评分标准】

该程序要求编程实现字符串格式控制输出,提交程序文件名为outputf.c。

解析

【代码思路】

本题主要考察字符串解析及C语言基本库函数的熟练程度,思维比第一题简单,代码思路如下:

1.对格式串进行解析,得到对齐方式、m和n的数值等信息。

2.用待输出字符串的长度与m、n进行数值比较,判断是否要填充,是否要对字符串进行截断,最后再根据对齐方式等规则按要求打印出待输出字符串即可。

【源代码】

#include<stdio.h>
#include<string.h>
char buff[1000];
char commadline[100];
void print(int m, int len)
{
    if (m > len)
        printf("%s", buff);
    else
    {
        //输出前m个字符
        int i;
        for ( i = 0; i < m; ++i)
            putchar(buff[i]);
    }
}

void tianchong(int n)
{
    int i;
    for ( i = 0; i < n; ++i)
        putchar('#');
}

int main()
{
    freopen("2.txt", "r", stdin);
    gets(commadline);
    gets(buff);

    bool right = false;
    if (commadline[1] == '-') right = true;
    char newcomm[100];
    if (right)
        strcpy(newcomm, commadline+2);
    else
        strcpy(newcomm, commadline + 1);
    int m, n;
    sscanf(newcomm, "%d:%d", &m, &n);
    
    int len = strlen(buff);
    
    int lenc;//填充的字符个数
    if (m > len)
        lenc = n - len;
    else
        lenc = n - m;

    if (n > len)
    {
        //n大于字符长度,要填充
        if (!right)
        {//先输出再填充
            print(m, len);
            tianchong(lenc);
        }
        else
        {
            tianchong(lenc);
            print(m, len);
        }
    }
    else
    {
        print(m, len);
    }
}

2018.04.22

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章