双链表应用之约瑟夫环问题

来源:互联网 发布:linux定时执行脚本 编辑:程序博客网 时间:2024/05/21 19:14


约瑟夫约瑟夫环(约瑟夫问题)是一个数学的应用问题:已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围,从编号为1的人开始报数,数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;依此规律重复下去,直到圆桌周围的人全部出列。通常解决这类问题时我们把编号从1~n,最后结果即为原问题的解。


在下面的例子中,我就先以5人的约瑟夫环进行测试:


约瑟夫环问题,你可以用顺序表解决,你也可以用双链表来解决,在时间复杂度上,毋庸置疑,肯定是双莲表复杂度底,那就以双链表为例吧!

      假设你拿到一个已经初始化的双链表,那么肯定对这个双链表加工成为环:只需标记尾部tmp,然后tmp->next = phead->next;  phead->next->pre = tmp;这一步主要让双联表成环。下来就是杀人了。

    假设是第一个人,报数从1开始,每次报到 m 的人就被杀死,对应到链表里就是每走 m-1 步后指向的结点被删除,(用简单的5个人,报到3的人退出,p刚开始指向头节点的下个结点--首元结点,p往后走2步,到达的结点就该被删除,

    最后你这个循环的终止条件为4自己指向自己或者phead的id变成计数,

phead->id == 1终止,那么就剩代码了!

  代码:

D_JOSEPH.h

#ifndef _D_JOSEPH_H_#define _D_JOSEPH_H_typedef int elem_type;typedef struct _NODE {elem_type id;struct _NODE *next;struct _NODE *pre;}NODE;NODE * init_double_list();bool insert_head(NODE *phead,elem_type id);NODE *CreateLoopList(int num);int Kill(NODE *phead, int gap);#endif

D_JOSEPH.cpp

#include"D_JOSEPH.h"#include<stdio.h>#include<stdlib.h>#include<assert.h>#define ERROR -1static int getlength(NODE *phead){NODE *p = phead;int i = 0;if(phead == NULL){return ERROR;}while(p->next){i++;p = p->next;}return i;}static NODE *alloc(elem_type e){NODE *tmp = (NODE *)malloc(sizeof(NODE));assert(tmp != NULL);tmp->id = e;tmp->next = NULL;tmp->pre = NULL;return tmp;}NODE * init_double_list(){NODE *phead = (NODE *)malloc(sizeof(NODE));assert(phead != NULL);phead->id = 0;phead->next = NULL;phead->pre = NULL;return phead;}bool insert_head(NODE *phead,elem_type id){NODE *tmp = alloc(id);if(phead == NULL){return false;}tmp->next = phead->next;if(phead->next != NULL)//是空表{phead->next->pre = tmp;}phead->next = tmp;tmp->pre = phead;phead->id ++;return true;}NODE *CreateLoopList(int num){NODE *phead = init_double_list();NODE *tmp = alloc(num);    phead->next = tmp;tmp->pre = phead;phead->id ++;for(int i = num-1;i>= 1;i --){insert_head(phead,i);}tmp->next = phead->next;//双链表成环phead->next->pre = tmp;return phead;}int Kill(NODE *phead, int gap){NODE *p = phead->next;NODE *s = phead->next;if(phead == NULL){return ERROR;}while(p->next != p){for(int i = 0;i < gap-1;i ++){p = p->next;}s = p;p->pre->next = p->next;p->next->pre = p->pre;p = p->next;printf("id-%d被杀\n",s->id);phead->id--;free(s);}int rs = p->id;free(p);free(phead);return rs;}
main.cpp

#include<stdio.h>#include"D_JOSEPH.h"int main(){int m = 13;//总数int ag = 3;//按照多少来报数NODE *phead = CreateLoopList(m);//成环函数int i = Kill(phead,3);printf("最后活着的人id-%d\n",i);return 0;}
结果:




1 0
原创粉丝点击