小學期C語言實訓:約瑟夫環(C工程文件和鏈表練習)

題目:

在這裏插入圖片描述

代碼:

Josephus.h

typedef int Status; // 一個新類型Status 表明操作成功與否的狀態,如果函數成功返回整形值1,否則返回整型值0
struct Lnode { // 單鏈表結點類型
    int data; // 信息存儲
    Lnode *next; // 下一結點地址
};
typedef Lnode Linklist ;

///函數聲明
Status CreatJosephus_L ( Linklist &L , int n ) ; // 依次輸入整數1-n的n個元素的值到鏈表的結點的數據單元,建立約瑟夫環用指針L指向第一個結點
Status OutputJosephus_L ( Linklist &L , int n ) ; // 從結點 L 開始,輸出n個元素
void MenuSelect ( Linklist &L ) ; // 處理鏈表L
using namespace std ;

Josephus_app

#include<stdio.h>
#include<iostream>
#include"Josephus.h"
using namespace std ;
Status CreatJosephus_L ( Linklist &head , int n ) {
    Lnode *L = &head ; // 記錄頭結點地址
    if ( n<=0 ) { // 序列長度 n 不合法
        return 0 ;
    }
    int temp;
    scanf( "%d", &temp ) ;
    L->data = temp ; // 爲第一個節點賦值
    n = n - 1 ;
    while( n-- ) { // 循環 n 次,依次添加每一個節點
        L->next = new(Lnode) ; // 新建下一個節點
        L = L->next ; // L 指向下一個節點
        scanf( "%d", &temp ) ;
        L->data = temp ;
    }
    L->next = &head ; // 尾結點連回頭結點,形成循環鏈表
    return 1;
}
Status CreatJosephus_L2 ( Linklist &head , int n ) { // 自動生成序列
    Lnode *L = &head ; // 記錄頭結點地址
    if ( n<=0 ) { // 序列長度 n 不合法
        return 0 ;
    }
    int temp = 1;
    L->data = temp ; // 爲第一個節點賦值
    n = n - 1 ;
    while( n-- ) { // 循環 n 次,依次添加每一個節點
        L->next = new(Lnode) ; // 新建下一個節點
        L = L->next ; // L 指向下一個節點
        temp++;
        L->data = temp ;
    }
    L->next = &head ; // 尾結點連回頭結點,形成循環鏈表
    return 1;
}
Status OutputJosephus_L ( Linklist &h , int n ) { // 從k開始報數,報數到m此人出列,輸出所有人出列序列
    int m, k;
    /// 輸入參數
    printf( "please input k and m :" ) ;
    scanf( "%d%d", &k, &m ) ; // 輸入 k 和 m
    printf( "the seq with parameter( k=%d,m=%d ) is :\n", k, m ) ;

    /// 按參數模擬報數
    Lnode *p = &h ; // 取得頭結點地址
    k-- ;
    if ( k<0 || m<0 ) { // 參數 k或m 不合法
        return 0 ;
    }
    while( k-- ) { // 首先從頭結點開始向後報數k-1個(找到編號爲k的人)
        p = p->next ;
    }
    while( n>0 ) { // 之後以 m 爲週期一次輸出每個出列的人的信息
        /// 此時 p 指向的人的報數爲 1
        for( int i=2; i<m; i++ ) { // 從當前 p 向後找到報數爲 m-1 的人,用 p 指向他
            p = p->next ;
        }
        printf( "%d ", p->next->data ) ; // 輸出報數爲m的人的信息
        p->next = p->next->next ; // 報數爲 m-1 的人的下一人 指向 報數爲 m 的人的下一人(刪除報數爲m的結點)
        p = p->next ; // p指向新的報數爲 1 的人
        n--; // 循環鏈表人數-1
    }
    printf( "\n" ) ;
    return 1;
}

void MenuSelect ( Linklist &L ) {
    int op = -1 , st1 , st2 ;
    int n ; // 鏈表長度
    while( op != 0 ) {
        printf( "please select op: " ) ;
        scanf( "%d", &op ) ;
        switch ( op ) { // 功能選擇
            case 0 : // 功能0:退出程序
                printf( "over !\n" ) ;
                break;
            case 1 : // 功能1:輸入鏈表
                printf( "please input n:" ) ;
                scanf( "%d", &n ) ; // 輸入鏈表長度
                printf( "please input seq :") ;
                st1 = CreatJosephus_L ( L , n ) ; // 輸入n個數字建立循環鏈表,若成功則st=1
                if ( st1 == 0 ) { // 建立失敗
                    printf( "error!\n" ) ;
                }
                break;
            case 2 : // 功能2:輸入參數並模擬輸出出隊序列
                st2 = OutputJosephus_L( L , n ) ;
                if ( st2 == 0 ) { // 輸出失敗
                    printf( "error\n" ) ;
                }
                else { // 輸出成功
                    printf( "successful\n" ) ;
                }
                break;
            default :
                printf( "error!\n" ) ;
        }
    }
}

Josephus_Main

#include<stdio.h>
#include<iostream>
#include"Josephus.h"
using namespace std ;

int main() {
    Linklist head ; // 建立鏈表
    MenuSelect( head ) ;
    return 0;
}
/*
input:
5
1 2 3 4  5
1 3

樣例解釋:
序列長度 n = 5
參數:k=1,m=3

第一次
出隊元素:3
剩餘序列:4 5 1 2

第二次
出隊元素:1
剩餘序列:2 4 5

第三次
出隊元素:5
剩餘序列:2 4

第四次
出隊元素:2
剩餘序列:4

第五次
出隊元素:4
剩餘序列:

*/

運行截圖:

在這裏插入圖片描述

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