데이터 구조 - 조셉 링 문제(C 언어 버전)

목차

먼저 조셉링이 뭔가요?

조셉 링 구현

1. 구조 변수 생성

2. 연결리스트 초기화

3. 순환 연결 리스트 구성

4. 연결리스트 삭제

 5. 전체 코드 및 주석 설명

먼저 조셉링이 뭔가요?

조셉의 반지는 순환 연결 목록의 고전적인 문제 입니다 ; 제목 설명: n명이 원을 형성하고, 첫 번째 사람부터 세기 시작하고, m까지 센 사람들이 대기열에서 나가고, 다음 사람이 다시 1부터 세기 시작합니다 .

10명이 1부터 10까지 번호가 매겨진 원을 이룬다고 가정하고 숫자가 오름차순으로 보고되면 3인이 아웃됩니다. 프로세스 다이어그램은 다음과 같습니다.

조셉 링 구현

나는 개인적으로 순환 연결 목록을 선호합니다.

1. 구조 변수 생성

typedef struct Node{
    int data;  //数据域
    struct Node* next;  //指针域
}Node;

2. 연결리스트 초기화

Node* Create(){
	 Node* head;
     head = (Node*)malloc(sizeof(Node));
     if (head == NULL) {
         exit(1);
     }
     head->next = NULL;
     return head;
}

3. 순환 연결 리스트 구성

 임시 노드 tail을 생성하고 , 헤드 노드 head를 tail 에 할당하고 , 새 노드 p를 삽입하고 , tail다음 노드가 p 를 가리키 도록 하고 , p 의 다음 노드가 head 의 다음 노드인 노드 p 를 가리키도록 합니다 . 시간이 지나면 tail을 p 위치로 이동 시켜 다음 노드 삽입을 준비하게 함으로써 원형 연결 리스트가 처음으로 완성됩니다.

코드 블록

Node* Push(Node* head,Node* tail,int 1){
    p->data=i;
    tail->next =p;
    p->next = head->next;
    tail = p;
    return head;
}

 

 가장 중요한 것은 새로운 노드를 삽입할 때마다 꼬리를 새로운 노드 위치로 이동시키는 것입니다!

4. 연결리스트 삭제

 

void Print(Node* head){
    Node* q=head;
    q->next = p->next;
    printf("%d ", p->data);
    free(p);
    p = q->next;
}

 5. 전체 코드 및 주석 설명

#include<stdio.h>
#include<stdlib.h>
typedef struct Node{
    int data;
    struct Node* next;
}Node;
//创建结构体变量
Node* Create(){
	 Node* head;
     head = (Node*)malloc(sizeof(Node));
     if (head == NULL) {
         exit(1);
     }
     head->next = NULL;
     return head;
}
int main()
{
     int n, m,i;
     Node * tail, * p, * q;
     Node* head=Create();
     scanf("%d %d", &n, &m);  //输入n个人围一圈及报数m的人出局
//判断如果插入的数据为0或者以报数0为出局,则结束操作
     if (n == 0 || m == 0) {
         return 0;
     }
     else {
         tail = head;  //开始没有数据,故尾结点tail与头结点重合
         for ( i = 0; i < n; i++) {
             p = (Node*)malloc(sizeof(Node));  //插入新结点需,先申请动态内存
             if (p == NULL) {        //判断动态内存是否申请成功
                 printf("申请失败!");
                 exit(1);
             }
             p->data = i+1; //以下4步为插入新结点及数据的操作,具体分析请看上面构建循环链表
             tail->next =p;
             p->next = head->next;
             tail = p;
         }
     }
     p =head->next;  //插入完数据后,将最后一个结点的临时结点移到第一个数据处
     q =tail;   //然后临时结点到尾结点处
     i = 1;
     while (p != q) {      //首尾结点是否重合,重合则表示只剩一个数据,结束循环
         if (i == m) {     //对报数m的人进行出局操作
             q->next = p->next;  //以下四步为删除操作
             printf("%d ", p->data);
             free(p);     //一定记得将删除链表处的内存释放,以免内存内存泄漏
             p = q->next;
             i = 1;     //删除后,重新从1开始报数
         }
         else {   //没有报数到m,则p,q结点都往后移一位
             q = p;  //先q移到p的位置
             p = q->next;  //然后p移到q的下一个位置
             i++;
         }
     }
     printf("%d", p->data);  //打印最后一位出局的人的号数
     return 0;
}

부족한 점이 있다면 댓글란을 통해 지적해주시면 감사하겠습니다!

추천

출처blog.csdn.net/m0_73463638/article/details/129222800