(1)将带头节点的单链表的所有节点逆置。
(2)利用顺序表求解约瑟夫问题。
(3)计算一个循环链表中节点的个数。
(1)将带头节点的单链表的所有节点逆置。
上机实现算法:将一个节点数据域依次是a1,a2,……,an(n≥3)的带头节点的单链表的所有节点逆置,即第一个节点的数据域变为an,最后一个节点的数据域为a1。
采用头插法建立一个新表,算法如下:
void reverse(SNode *h)
{
SNode *p,*q;
p=h->next;
h->next=NULL; /*建立一个带头节点的空表*/
while (p!=NULL)
{
q=p->next;
p->next=h->next; /*将*p节点插入到头节点之后*/
h->next=p;
p=q;
}
}
(2)利用顺序表求解约瑟夫问题。
求解约瑟夫问题:n只猴子要选大王,选举方法是,所有猴子按1,2,……,n编号围坐一圈,从第1号开始按1,2,……,m报数,凡报到m号的退出圈外,如此循环报数,直到圈内剩下一只猴子时,这只猴子就是大王。编写一个程序求猴子出列的次序,其中n和m由键盘输入。
解:这里采用顺序表进行存储,使用一个数组mon,最多可存放MaxSize个元素,初始时mon[i]中存放猴子的编号i+1(猴子的编号为1~n),将出列猴子个数计数器count置为0。d置为0,从mon[0](其编号为1)开始循环报数,每报一次,d值加1,凡报到m(条件d==m成立)时便输出mon[i]的值,同时将mon[i]的值改为0(表示该猴子已出列)。该过程一直进行到n只猴子全部退出圈外为止(条件count==n成立),最后退出的便是大王。实现本题功能的程序如下:
void jose(int n,int m)
{
int mon[MaxSize]; /*存放n个猴子的编号*/
int i,d,count;
for (i=0;i<n;i++) /*设置猴子的编号*/
mon[i]=i+1;
printf("出队前:"); /*输出出列前的编号*/
for (i=0;i<n;i++)
printf("%d ",mon[i]);
printf("\n");
printf("出队后:");
count=0; /*记录退出圈外的猴子个数*/
i=-1; /*从0号位置的猴子开始计数*/
while (count<n)
{
d=0;
while (d<m) /*累计m个猴子*/
{
i=(i+1)%n; /*循环选取*/
if (mon[i]!=0)
d++;
}
printf("%d ",mon[i]); /*猴子出列*/
mon[i]=0;
count++; /*出列数加1*/
}
printf("\n");
}
执行本程序,在输入猴子个数分别是10和4时输出结果如下。
出队前:1 2 3 4 5 6 7 8 9 10
出队后:4 8 2 7 3 10 9 1 6 5
(3)算法只需扫描一次链表,同时设立一个计数变量用来计数即可。
int Count ( )
{
int i;
LinkList *p;
p=head;
i=0;
while ( p->next!=head )
{
p=p->next;
i++;
}
return ( i );
}