今天介绍两个链表的简单应用。
1.约瑟夫问题
假设有N个人决定选出一个领导人,方法如下:所有人排成一个圆圈,按顺序数数,每次数到第M个人出局,此时,他两边的人靠拢重新形成圆圈。问题是找出哪一个人将会是最后剩下的那个人。下列程序依次读入N和M,并给出最终结果。
#include <stdlib.h>
#include <stdio.h>
typedef struct node* link;
struct node {
int item;
link next;
};
int main(int argc,char *argv[])
{
int i,N = atoi(argv[1]),M = atoi(argv[2]);
link t = malloc(sizeof *t),x = t;
t->item = 1;
t->next = t;
for (i = 2;i <= N;i++) {
x = (x->next = malloc(sizeof *x));
x->item = i;
x->next = t;
}
while (x != x->next) {
for (i = 1;i < M;i++)
x = x->next;
x->next = x->next->next;
N--;
}
printf("%d\n",x->item);
}
前面介绍过插入排序,是用数组的方法实现的,程序很简单,用链表反而显得比较复杂。但是主要是为了熟悉链表的使用。
#include <stdlib.h>
#include <stdio.h>
typedef struct node* link;
struct node {
int item;
link next;
};
int main(int argc,char *argv[])
{
int i,N = atoi(argv[1]);
struct node heada,headb;
link t,x,a,b,u;
t = &heada;
a = t;
for (i = 0;i < N;i++) {
t->next = malloc(sizeof *t);
t->next->item = rand() % 100;
t = t->next;
t->next = NULL;
}
for (t = a;t->next != NULL;t = t->next)
printf("%d ",t->next->item);
printf("\n");
for (b = &headb,b->next = NULL,t = a->next;t != NULL;t = u) {
u = t->next;
for (x = b;x->next != NULL;x = x->next)
if(t->item < x->next->item)
break;
//x->next = t;
//x->next->next = NULL;
t->next = x->next;
x->next = t;
}
for (t = b;t->next != NULL;t = t->next)
printf("%d ",t->next->item);
printf("\n");
}
上面两个例子有个很明显的问题,只是动态申请了内存,但是没有释放,实际写程序的时候千万要注意释放,这里偷个懒就没加了。
对于第二个例子,在每次插入的时候都是从链表头到尾遍历,可以考虑利用双向链表或者循环双向链表实现从链表尾到头的遍历。