北航數據結構期中測試編程題解析

編程題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

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