循环链表

  单链表的局限性:如果不从头结点出发,就无法访问的全部节点。

  循环链表定义:将单链表终端结点的指针由空指针改为指向头结点;使单链表形成一个环,称单循环链表,简称循环链表

  注:循环链表不一定有头结点。

约瑟夫环问题

  问题描述:N个人围成一圈,从第一个人开始报数,报到m的人出圈,剩下的人继续从1开始报数,报到m的人出圈;如此往复,直到所有人出圈。(模拟此过程,输出出圈的人的序号)

 1 #include <stdio.h>
 2 #include <malloc.h>
 3 
 4 typedef struct Node{
 5     int data;//数据
 6     struct Node *next;//游标(cursor)
 7 }node;
 8 
 9 node * create(int,node **);
10 void fun(node **,node **,int);
11 
12 void fun(node **head,node **rear,int m){
13     node *p=*head;
14     node *q;
15     int n=m;
16     if(*head == *rear){
17         printf("最后一个出圈人的序号是%d;\n",(*rear)->data);
18         free(*rear);
19     }else{
20         while(n>2){
21             p=p->next;
22             n--;
23         }
24         q=p->next;
25         printf("%d => ",q->data);
26         *head=q->next;
27         *rear=p;
28         p->next=p->next->next;
29         free(q);
30         fun(head,rear,m);
31     }
32 }
33 
34 node *create(int n,node **rear){
35     node *p,*head,*a;
36     int i=1;
37     head=(node *)malloc(sizeof(node));
38     p=head;
39     if(i != n){
40         while(i<=n){
41             a=(node *)malloc(sizeof(node));
42             a->data=i++;
43             p->next=a;
44             p=a;
45         }
46         p->next=head->next;
47         *rear=p;
48     }
49     free(head);
50     return p->next;
51 }
52 
53 void main(){
54     int n,m;
55     node *head,*rear;
56     printf("请输入约瑟夫人数:");
57     scanf("%d",&n);
58     head=create(n,&rear);
59     printf("请输入m:");
60     scanf("%d",&m);
61     fun(&head,&rear,m);
62 }

发牌问题

  问题描述:将13张牌按一定顺序排放;从1开始数,依次数到1-13;每次数的时候;若不是结束位置,就将该牌放置末尾;若是结束为止,将结束位置翻出并取出,为本次数到的数。

  方法:将头指针指向的结点元素设置为1,并将结点指向的结点赋值给指针

    将头指针指向向后移动 i 次,每次都判断结点的值是否为0,若不为0.则i自减1;

 1 #include <stdio.h>
 2 #include <malloc.h>
 3 #define NUM 13
 4 
 5 typedef struct node{
 6     int data;//数据
 7     struct node *next;//指针域
 8 }Node,* PNode;
 9 
10 PNode creat();
11 void printList(PNode);
12 void fun(PNode *,int);
13 
14 void fun(PNode *head,int k){
15     int i=1;
16     PNode p=*head;
17     while(i<k){
18         p=p->next;
19         if(p->data!=0)
20             i--;
21         i++;
22     }
23     p->data=k;
24     *head=p->next;
25     if(k!=NUM){
26         fun(head,k+1);
27     }
28 }
29 
30 void printList(PNode head){
31     PNode p=head->next;
32     printf("%d   ",head->data);
33     while(p!=head){
34         printf("%d   ",p->data);
35         p=p->next;
36     }
37     printf("\n");
38 }
39 
40 PNode creat(){
41     PNode head,p,q;
42     int i=0;
43     head=(PNode)malloc(sizeof(Node));
44     p=head;
45     while(i<NUM){
46         q=(PNode)malloc(sizeof(Node));
47         q->data=0;
48         p->next=q;
49         p=q;
50         i++;
51     }
52     q->next=head->next;
53     p=head->next;
54     free(head);
55     return p;
56 }
57 
58 void main(){
59     PNode head,p;
60     int i=1;
61     head=creat();
62     p=head;
63     fun(&p,i);
64     printList(head);
65 }
 1 //发牌问题用迭代实现
 2 void fun(int a[],int n){
 3     int i,j=0,k=0,p;
 4     for(i=0;i<n;i++){
 5         j=0;
 6         while(j<i){
 7             if(a[k]!=0)
 8                 j--;
 9             j=(j+1)%n;
10             k=(k+1)%n;
11         }
12         p=k;
13         while(a[k]!=0){
14             k=(k+1)%n;
15             if(k==p)
16                 break;
17         }
18         a[k]=i+1;
19     }
20 }

 双向链表

  • 双向链表的指针域有两个指针,分别指向他的前驱和后继;
  • 双向链表最后一个结点的后继指向头结点;头结点的前驱指向最后一个结点;

 

1 #include <stdio.h>
2 typedef int ElemType;
3 
4 typedef struct DualNode{
5     ElemType data;//数据
6     struct DualNode *prior;//前驱结点
7     struct DualNode *next;//后继结点
8 }DualNode,* DuLinkList;