单向循环链表实现约瑟夫环(java版)
上一篇 / 下一篇 2008-05-07 16:20:14 / 个人分类:数据结构
1.背景资料
&Z3EbM%CZ&X/Zq:Q0
是一个数学的应用问题:ITPUB个人空间;M:T?L"~ ITPUB个人空间N9](|5Y9E8u 已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围。从编号为k的人开始报数,数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;依此规律重复下去,直到圆桌周围的人全部出列。ITPUB个人空间}9P/pK1`/SA7~0v kKX(ZK i d^0 'rvo9Y/dn0 这个就是约瑟夫环问题的实际场景,有一种是要通过输入n,m,k三个正整数,来求出列的序列。这个问题采用的是典型的循环链表的数据结构,就是将一个链表的尾元素指针指向队首元素。 p->link=headITPUB个人空间4KBh?s/\[9@ GO-rbZ7a+Q ZP0 解决问题的核心步骤: (YcW iN8?nj E0 1.建立一个具有n个链结点,无头结点的循环链表 [t guN|-JIc0 2.确定第1个报数人的位置 C;j)zV8II0 3.不断地从链表中删除链结点,直到链表为空 ZYHt+M[0 5M[EdR3{!w2y6N0void JOSEPHUS(int n,int k,int m) //n为总人数,k为第一个开始报数的人,m为出列者喊到的数 1KP;o#Za#R0{ 7I:^n d%T;Q7[ SNC0 /* p为当前结点 r为辅助结点,指向p的前驱结点 list为头节点*/ hED"lM h0 LinkList p,r,list; D~#b0DD|0ITPUB个人空间&~g V,s4Sc$g /*建立循环链表*/ cK-Q8K9s&z W0 for(int i=0,i<n,i++)ITPUB个人空间"sHL-v$RU8C0I7~u { $Pb Yt Y;^^*r ^a S0 p=(LinkList)malloc(sizeof(LNode)); 'g V(yh k l?|0 p->data=i;ITPUB个人空间\-I_,F Y$l0F g if(list==NULL)ITPUB个人空间#O`K}8H2kqE list=p;ITPUB个人空间6r`5c)Rv D$Fd6A~/C elseITPUB个人空间7M*x3vo#r,r9{-B'c u r->link=p;ITPUB个人空间v#UWu2wRR r=p; 0]2Y"C:O&x `0 } |.`G"]lUfqa0 p>link=list; /*使链表循环起来*/ITPUB个人空间5e9p af*@;J p=list; /*使p指向头节点*/ITPUB个人空间9|)U"W],a!j/L{ V4SmZ6vA0 /*把当前指针移动到第一个报数的人*/ITPUB个人空间)r5O^I*abZ0n$I^#JIS for(i=0;i<k;i++)ITPUB个人空间AiR3`a7Yk&{ {ITPUB个人空间6Vlt}G r=p;ITPUB个人空间+X$\$M6CY p=p->link; t7Sg!c'Pc _M.C0 }ITPUB个人空间sT6i|5`N ITPUB个人空间DR#t HH6Z2v-e)[-I*n /*循环地删除队列结点*/ 0a[nbS*p&q6s"A{0 while(p->link!=p)ITPUB个人空间SD"C%B6~ y(h0g"qy7g5s {ITPUB个人空间3q&Yj Z0Mui^ for(i=0;i<m;i++)ITPUB个人空间O ah2ua {ITPUB个人空间6d\;i|Ja4{ h5Y6C r=p;ITPUB个人空间 ^~npE%v6|pkWq} p=p->link; v/t0}L0Z&Qaxp0 }ITPUB个人空间2{6K*H?}p%n D:r4_6Y r->link=p->link;ITPUB个人空间7?s7\sl/[)i printf("被删除的元素:%4d ",p->data);ITPUB个人空间 |YWs X it free(p);ITPUB个人空间3k3C-L(JY p=r->link; IMtm\6P s0 }ITPUB个人空间L~;e5Eu` U)X0cX printf("\n最后被删除的元素是:%4d",P->data); D^g3Nx-K0}ITPUB个人空间7Zb'Mk:I ITPUB个人空间$DG\$Fc y+zU A ITPUB个人空间,v| B+c5Q ITPUB个人空间C,mTep-y9G |1`'G ITPUB个人空间#\ j'\n3I^:T;XK M ITPUB个人空间2z o_Q2D ?;X 无论是用链表实现还是用数组实现都有一个共同点:要模拟整个ITPUB个人空间e-tAH/m{!l3IX 游戏过程,不仅程序写起来比较烦,而且时间复杂度高达O(nm),当nITPUB个人空间K? vMG ,m非常大(例如上百万,上千万)的时候,几乎是没有办法在短时间ITPUB个人空间DnhT3vL_B 内出结果的。我们注意到原问题仅仅是要求出最后的胜利者的序号, L!i dBbO3|IYl9B;[0而不是要读者模拟整个过程。因此如果要追求效率,就要打破常规, |