關於狂人C第九章練習題二

題目出自:http://www.cnblogs.com/KBTiller/archive/2010/12/23/1914542.html

題目:

    (2)一個旅行社要從n個旅客中選出一名旅客,爲他提供免費的環球旅行服務。旅行社安排這些旅客圍成一個圓圈,從帽子中取出一張紙條,用上面寫的正整數m(<n)作爲報數值。遊戲進行時,從第一個人開始按順時針方向自1開始順序報數,報到m時停止報數,報m的人被淘汰出列,然後從他順時針方向上的下一個人開始重新報數,如此下去,直到圓圈中只剩下一個人,這個最後的倖存者就是遊戲的勝利者,將得到免費旅行的獎勵。

編程對某個給定的n = 8與m = 3,給出被淘汰出列的旅客編號,以及最終的倖存者。

代碼我是這麼寫的:

#include <stdio.h>
#include <stdlib.h>


typedef struct node {
    int number;
    struct node * nextPtr;
}Node;

Node * init(int n);
void delete(Node *sPtr, int n);

int main()
{
    int m, n, i;
    Node * head = NULL;
    Node * temp = NULL;
    

    scanf("%d%d", &m, &n);
    head = init(n);
    temp = head;

    while (temp->nextPtr != temp)
    {
        int deleteNumber;
        for (i=1; i<m; i++)
        {
            temp = temp->nextPtr;
        }
        deleteNumber = temp->number;
        
        temp = temp->nextPtr;
        delete(head, deleteNumber);
    }

    printf("Survivors is %d\n", temp->number);
    free(temp);
    
    return 0;
}

Node * init(int n)
{
    int i;
    Node * curNode = NULL;
    Node * head = NULL;
    curNode = (Node *)malloc(sizeof(Node *));
    curNode->number = 1;
    curNode->nextPtr = NULL;
    head = curNode;

    for (i=1; i<n; i++)
    {
        Node * newNode;
        newNode = malloc(sizeof(Node *));
        newNode->number = i + 1;
        newNode->nextPtr = NULL;
        curNode->nextPtr = newNode;
        curNode = newNode;
    }
    curNode->nextPtr = head;

    return head;
}

void delete(Node *sPtr, int n)
{
    Node * prePtr=NULL;
    Node * curPtr=NULL;

    curPtr = sPtr;
    while (curPtr->number != n) {
        prePtr = curPtr;
        curPtr = curPtr->nextPtr;
        printf("%d-->", prePtr->number);
    }
    prePtr->nextPtr = curPtr->nextPtr;
    printf("delete %d\n", curPtr->number);
    free(curPtr);
}



輸入m=3,n=8運行結果是:

##############################

./a.out 3 81-->2-->delete 31-->2-->4-->5-->delete 6段錯誤

##############################

最後面發現錯在head這個Node指針變量,本意是想用來保存單向循環鏈表的頭節點信息,然後通過每次從head開始遍歷鏈表來刪除節點,而

delete(head,deleteNumber);

這一句依賴head,在第三次循環刪除節點1之後,head就相當於指向一個被收回的地址,就產生段溢出錯誤了。

最後修改程序邏輯,使用temp來傳參給delete函數來開始遍歷鏈表就OK了,如下改動:

 //   Node * head = NULL;
 //   head = init(n);
//    temp = head;

上面三行替換成temp = init(n);
//delete(head, deleteNumber);

上面這行替換成delete(temp, deleteNumber);

運行結果:

./a.out
3 8
4-->5-->6-->7-->8-->1-->2-->delete 3
7-->8-->1-->2-->4-->5-->delete 6
2-->4-->5-->7-->8-->delete 1
7-->8-->2-->4-->delete 5
4-->7-->8-->delete 2
4-->7-->delete 8
7-->delete 4
Survivors is 7


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