c語言數據結構之單向循環鏈表約瑟夫問題

問題描述:

約瑟夫問題的一種描述是:編號爲12,……,nn個人按順時針方向坐一圈,沒人持有一個密碼(正整數)。一開始任選一個作爲報數上限值m,從第一個開始順時針自1開始順序報數,報到m是停止報數。報m的人出列,將他的密碼作爲新的m值,從他在順時針方向的下一個人重新從1報數,如此下去,直到所有的人全部出列爲止。設計一個程序,求出出列順序


廢話不多說,上代碼:


/*==========Definition.h==============*/
/*標準庫函數*/
#include<string.h>
#include<ctype.h>
#include<malloc.h>
#include<limits.h>
#include<stdio.h>
#include<stdlib.h>
#include<io.h>
#include<math.h>
#include<process.h>

/*常量定義*/
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define LIST_INIT_SIZE 5 /*循環鏈表存儲空間的初始分配量*/

/*類型定義*/
/*Status是函數的類型,其值是函數結果狀態代碼,如OK等*/
typedef int Status;
/*Boolean是布爾類型,其值是TRUE或FALSE*/
typedef int Boolean;
/*演示程序設定元素類型爲int,如有必要可以修改成其他類型*/
typedef int ElemType;
/*線性表的鏈式存儲結構*/
struct Node
{
   ElemType data; /*數據域*/
   struct Node * next; /*後繼指針域*/
   ElemType bianhao;
};
typedef struct Node LinkNode;
typedef struct Node * LinkList;





/*=======循環鏈表功能模塊========*/


/*正序構造一個循環鏈表,並使用參數L返回*/
Status Initialize(LinkList&L,int n)
{
	/*產生頭結點,並使L指向此頭結點。此語句等價於:L=(LinkList)malloc(sizeof(struct Node)); */
	L=(LinkList)malloc(sizeof(LinkNode));
	if(!L) /*存儲分配失敗*/
		exit(OVERFLOW);
	/*指針域暫時置爲空*/
	L->next=NULL;
	LinkList p,q;
	q=L;
	for(int i=0;i<n;i++)
	{
		/*生成新的有效數據結點*/
		p=(LinkList)malloc(sizeof(LinkNode));
		scanf("%d",&p->data);
		p->bianhao=i+1;
		/*該語句不能省,否則會造成程序異常*/
		p->next=NULL;
		q->next=p;
        q=p;
	}
	q->next=L;
	scanf("&d",L->data);
	L->bianhao=n;
	return OK;
}


/*=======在帶頭節點的循環鏈表L中,刪除第i個元素,並由e返回其值========*/


Status LinkDelet(LinkList&L, int i, ElemType  &e,ElemType &n)
{
    LinkList p=L;
	int j = 0;
	while (p->next&&j < i - 1)       //查找到第i-1個節點
	{
		p = p->next;
		++j;
	}
	LinkList q;                   //刪除第i個結點
    q = p->next;
    p->next = q ->next;
	e = q->data;
    n=q->bianhao;
	free(q);
	L=p;
	return OK;
}  




/*==================解決約瑟夫問題================*/
int main()
{
    int mima,m,n,bianhao,num;
    LinkList L;
    printf("=====下面爲約瑟夫排序問題的計算過程及結果=====\n");
    printf("請輸入環中元素的個數(正整數):");
    scanf("%d",&n);  
    printf("請輸入%d個數據元素(每次輸入一個元素後空格,全部輸完以後回車):",n);
    Initialize(L,n);
	printf("請輸入上限值m:");
    scanf(" %d",&m);
	printf("出列順序爲:");
    for(int i=0;i<n;i++)
    {
        LinkDelet(L,m,mima,bianhao);
		m=mima;
        printf(" %d",bianhao);
    }
	printf("\n");
	return 0;
}



一開始,創建循環鏈表是把我難住了,雖然書上說的很簡單,但是一開始我的鏈表是帶頭結點的,而且並不打算在頭結點存值,所以把尾結點指向頭結點的下一個結點,循環起來難免出錯。於是最後只得妥協,先將尾結點的下一個結點指向頭結點,同時給頭結點賦值,這樣才輸出正確的結果。



運行結果



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