1. 程式人生 > >約瑟夫環問題(動態連結串列操作)n個學生圍成一圈,每m個出隊,輸出所有出隊的序列

約瑟夫環問題(動態連結串列操作)n個學生圍成一圈,每m個出隊,輸出所有出隊的序列

 需求:掌握連結串列的簡單操作(增刪查改)詳解在備註中指出

#include <iostream>
#include <stdlib.h>
#include <stdio.h>
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
   struct node{
		int data;//資料 
		node* next;//指標 
	};
	node* creat(int array[],int n)// 建立一個長度為n的迴圈列表 
	{
		node *p,*head,*pre;// 建立現在指標,頭指標,前指標 
		head =new node;// 新建立一個空的頭地址 
		
		head->next=NULL;// 先進行置空 
		pre=head;//  將前指標置為頭結點 
		for(int i=0;i<n;i++)// 建立n個長度的連結串列 
		{
			p=new node;	// 建立新節點 
			p->next=NULL;// 先進行置空 
			pre->next=p;// 和新建的連線
			p->data=array[i];// 將新建節點賦值 
			pre=p;// 推進 
		}
		p->next=head;// 因為是迴圈列表將尾指標指向頭指標 
	
		return head;// 返回頭指標(頭指標data沒賦值) 
	} 
	void delet(node* head,int length,int m)// 將指定head頭的連結串列的第m個刪除並輸出(迴圈 )
	{
		node *pre,*p;
		int count=1,sum=0;//建立計數器(p的位置)和sum 
		pre=head;//頭結點指定head
		p=head->next;//p(現在節點)指向第1個元素 
	
		while(length!=0)//當連結串列中沒元素時退出 
		{
			if(p==head)//當迴圈到頭結點時因為不應該進行計數所以推進 
			{
				pre=pre->next;//將兩個節點推進 
				p=p->next;
			}
			
			if(count==m)//如果當p(現在節點)的計數等於m ,刪除該p節點 
			{
				printf("第%d個出隊:%d號學生\n",++sum,p->data);//輸出 該刪除的節點 
				pre->next=p->next;//直接將p前一節點的指標域賦為p的下一個節點的地址(跳過p節點) 
				delete(p);//釋放空間 此時p的地址為空 
				p=pre->next;// 將p的地址賦為pre的下一個地址(始終保持p在pre前) 
				length--;//長度減一 
				count=0;//重置計數器 
			}
			else//如果沒有刪除節點那麼p節點就沒有變化,此時我們推進 
			{
				pre=pre->next;
				p=p->next;
			}
			
			count++;//推進一次計數器加一,當刪除一個元素後,p直接為下一個地址,等於說p推進了一次,那麼計數器也應該加一 
			
		}
		
	}
	int main() {
		int n,m;
		int arr[1000];
		for(int i=0;i<n;i++)//將學生編號 
		{
			arr[i]=i+1;//學生編號為1,2,3,4.... 
		}
		printf("請輸入學生數目n 迴圈次數m\n1代表1號學生\n");
		scanf("%d%d",&n,&m);//錄入n,m 
		
		node* l=creat(arr,n);//呼叫兩個方法 
		delet(l,n,m);   	 
		   	
	 
	return 0;
}