이중 연결 목록은 Joseph 문제를 구현합니다.


제목: 이중 연결 목록은 Joseph 문제 구현
날짜: 2023-05-16 11:42:26
태그:


  • **질문:**알려진 n명이 원탁에 둘러앉아 있습니다. k의 사람이 세기 시작하고 m까지 센 사람이 나가고, 그 다음 사람이 1부터 세기 시작하고 m까지 센 사람이 다시 나간다; 이 규칙을 테이블 주위의 원이 될 때까지 반복하십시오. .

  • Git 주소: https://github.com/944613709/HIT-Data-Structures-and-Algorithms

    알고리즘 사고:

    \1. n 노드의 이중 연결 목록을 구성하고 연결 목록의 각 노드의 데이터 값을 초기화하고 순서대로 i에 할당합니다(연결 목록의 i번째를 나타냄).

    \2. 검색 기능을 실행하고 Head에서 Pth 노드 검색을 시작하며 head = head->next를 반복하면서 Pth 노드에 도달할 때까지

    \3. 일반적으로 현재 헤드의 첫 번째 m-1 노드에서 번호를 보고한 다음 m번째 노드를 반환하는 점프 기능을 실행합니다.

    \4. Jump 함수에 의해 반환된 m번째 노드에서 Delete 문을 새로운 헤드로 실행하고, 현재 노드를 삭제하고, 다음 카운트를 위해 다음 노드로 돌아갑니다.

    \5. Delete 함수에 의해 반환된 노드를 새 헤드로 사용하고 작업 3과 4를 반복합니다.

    \6. 총 n-1 dequeue에 대해 위의 반복 작업을 수행한 후 마지막 사람이 남습니다.

    알고리즘 단계:

    \1. n 노드의 이중 연결 목록 생성

    (1) 헤드 노드 데이터 할당 값을 1로 Node *head를 정의한 후 Node *tail을 정의하여 테일 노드를 기록

    (2) For순환 n-1차, for(int i=2;i<=len;i++)

    ① Node *node를 정의하고 현재 i에 데이터 값을 할당

    ② 꼬리 삽입 방법, 링크드 리스트에 노드 삽입

    \2. 검색 기능 실행

    (1) k번째 노드까지 while 루프를 실행합니다. while (head->data != k)

    ① 머리 = 머리->다음;

    (2) k번째 노드 반환 헤드 반환

    \3. while 루프를 사용하여 점프 및 삭제 작업을 반복하고 카운트를 사용하여 대기열에서 빼는 횟수를 기록합니다.

    3.1 점프 기능 실행

    (1) int count=0; count를 사용하여 숫자를 기록하고 보고합니다.

    (2) count=m-1이 될 때까지 While 루프

    ① Count++는 개수 더하기 1을 나타냅니다.

    ② Printf는 보고서를 실행합니다.

    ③ Head Point를 다음 노드로 설정

    \1) 이때 head가 이미 끝 노드를 가리키고 있으면 head=head->pre가 다시 연결 목록의 첫 번째 노드를 가리킬 때까지 while 루프가 계속됩니다.

    \2) head가 끝 노드를 가리키지 않으면 head=head->next;

    (3) 리턴 노드 리턴 헤드

    3.2 삭제 문 실행

    (4) 노드 *temp=헤드;

    (5) printf를 실행하여 이 노드를 삭제할 것임을 선언하고 세 가지 경우에 대해 논의

    ① 헤드 노드 삭제(temp->pre == NULL)는 head=head->next, temp->next=NULL, head->pre=NULL, free(temp), return head;

    ② tail 노드 if(temp->next == NULL)을 삭제하려면 while 루프 head=head->pre;를 사용하여 head가 연결 목록의 첫 번째 노드로 점프한 후 원래 tail 노드 temp를 삭제합니다. ->사전->다음 =NULL;임시->사전=NULL;자유(임시);

    ③ 중간 노드 삭제를 위해 head=head->next; temp->pre->next=temp->next; temp->next->pre=temp->pre; free(temp);

    테스트 샘플:

    이미지

    특정 코드

    #include<stdio.h>

  **#include<stdlib.h>**

  **#include<math.h>**

  **int delTime=0;**

  **typedef struct Node**

  **{**

  ​     **int data;**

  ​     **struct Node \*pre;**

  ​     **struct Node \*next;**

  **}Node;**

  **Node\* CreatNode(int data)//****新建结点并赋值** 

  **{**

  ​     **Node \*node=(Node\*)malloc(sizeof(Node));**

  ​     **node->data=data;**

  ​     **node->pre=NULL;**

  ​     **node->next=NULL;**

  ​     **return node;**

  **}**

  **Node\* CreatList(int len)**

  **{**

  ​     **int num=1;**

  ​     **Node \*head= CreatNode(1);**

  ​     **Node \*tail=head;**

  ​     **for(int i=2;i<=len;i++)**

  ​     **{**

  ​          **Node \*node=CreatNode(i);**

  ​          **tail->next=node;**

  ​          **node->pre=tail;**

  ​          **tail=tail->next;**

  ​     **}**

  ​     **tail->next=NULL;**

  ​     **return head;**

  **}**

  **Node\* Delete(Node \*head)//****删除当前的,并且返回下一个节点,进行下一轮报数** 

  **{**

  ​     **Node \*temp=head;**

  ​     **delTime++;//****用以判断是否到删除的数** 

  ​     **printf("****本轮报数正好出列,第%d****次执行删除编号为%d\n",delTime,temp->data);**

  ​     **if(temp->pre == NULL)//****对于删除头节点** 

  ​      **{**

  ​      **head=head->next;**

  ​      **temp->next=NULL;**

  ​      **head->pre=NULL;**

  ​      **free(temp);**

  ​      **return head;**

  ​      **}**

   

  ​      **/\*****判断是否是尾节点\*/**

  ​      **else if(temp->next == NULL)//****对于删除尾结点** 

  ​      **{**

  ​           **while(head->pre!=NULL)**

  ​                 **head=head->pre;//****删除后head****跳到当前链表第一个** 

  ​        **temp->pre->next=NULL;**

  ​        **temp->pre=NULL;**

  ​        **free(temp);**

  ​        **return head;**

  ​      **}**

  ​      **else//****删除中间结点** 

  ​      **{**

  ​           **head=head->next;**

  ​        **temp->pre->next=temp->next;**

  ​        **temp->next->pre=temp->pre;**

  ​        **free(temp);**  

  ​        **return head;**  

  ​      **}**

  ​       

  **}** 

  **Node \*Search(Node \*head, int k) {  //****从Head****开始寻找第P****个节点**

  ​     **while (head->data != k) {**

  ​          **head = head->next;**

  ​     **}**

  ​     **return head;**

  **}**

  **Node \*Jump(Node \*head, int m)//****将head****前m-1****次正常报数,然后返回第m****次** 

  **{**

  ​     **int count=0;**

  ​     **while(count!=m-1)//****前m-1****个人都能正常报数**

  ​     **{**

  ​          **count++;**

  ​          **printf("****报数为->%d,****编号data****为->%d\n",count,head->data);//****报数** 

  ​          **if(head->next==NULL)**

  ​          **{**

  ​              **while(head->pre!=NULL)**

  ​                   **head=head->pre;**

  ​          **}//****换行** 

  ​          **else**

  ​              **head=head->next;**

  ​     **}**

  ​     **return head;** 

  **}**

  **int main()//****已知n****个人围坐在一张圆桌周围。从编号为k****的人开始报数,数到m****的那个人出列;他的下一个人又从1****开始报数,数到m****的那个人又出列;依此规律重复下去,直到圆桌周围的人全部出列。(****摘自百度百科)**

  **{**

  ​     **int n,k,m;**

  ​     **int count=0;**

  ​     **printf("****按照n,k,m\n");**

  ​     **while(scanf("%d,%d,%d",&n,&k,&m)!=3)**

  ​     **{**

  ​     **}**

  ​     **Node \*head=CreatList(n);**

  ​     **head=Search(head,k);**

  ​     **while(count!=n-1)//****执行n-1****次出列,来完成剩下最后一个人**

  ​     **{**

  ​          **count++;**

  ​          **head=Jump(head,m);//****将head****前m-1****次正常报数,然后返回第m****次** 

  ​          **head=Delete(head);//****删除当前的,并且返回下一个节点,进行下一轮报数** 

  ​     **}**

  ​     **printf("****最后剩下的是编号为%d\n",head->data);**

  **}**

추천

출처blog.csdn.net/qq_35798433/article/details/130700764