Chinaunix首页 | 论坛 | 博客
  • 博客访问: 822453
  • 博文数量: 92
  • 博客积分: 1498
  • 博客等级: 上尉
  • 技术积分: 993
  • 用 户 组: 普通用户
  • 注册时间: 2009-09-18 18:31
文章分类

全部博文(92)

文章存档

2013年(2)

2012年(3)

2011年(3)

2010年(61)

2009年(23)

分类: LINUX

2010-06-10 20:21:27

今天突然看到书上的数据结构课本上的一个约瑟夫环的问题,记得当初我好像是没有做出来,现在做做。
这个题我首先想了想,就按照书上说的使用循环单链表,具体实现过程如下:

/*
 * Copyright (c) 2010-~ zhouyongfei
 *
 * The source code is released for free distribution under the terms of the GNU General Public License
 *
 *
 * Author: alen Chou
 * Created Time: 2010年06月10日 星期四 11时58分23秒
 * File Name: yusefu.c
 * Description: 约瑟夫问题描述:编号为1,2,3,4....n的n个人顺时针方向围坐一圈,每人持有一个密码(正整数)
 * 一开始选择一个数字作为报数的上限值m,从第一个人开始顺序报数,报道m的时候停止报数,报到m的人出列,将
 * 他持有的密码作为心的上限m值,并从他的下一个人从1开始报数,如此下去,直到所有人出列,设计一个程序,求出出列的顺序
 * 例如m的初值为20,n=7,7个人的密码一次是3,1,7,2,4,8,4,出列的顺序为6,1,4,7,2,3,5
 *
 */


#include<stdio.h>
#include<stdlib.h>
#include <unistd.h>

typedef struct node{
    int number;
    int pass;
    struct node *next;
}Node,*List;

/*
 *    初始化循环单链表
 *
 * */

void initList(List L)
{
    L->number = 0;
    L->pass = 0;
    L->next = L;
}

/*
 *    尾插法建立循环单链表
 *
 * */

void createFromTail(List head,int num[],int pas[],int length)
{
    int i;
    Node *pri;
    Node *tmp;
    head->number = num[0];
    head->pass = pas[0];
    pri = head ;
    for(i = 1;i<length;i++){
        tmp = (Node *)malloc(sizeof(Node));
        tmp->number = num[i];
        tmp->pass = pas[i];
        pri->next = tmp;
        pri = tmp;
        pri->next = head;
    }
}

/*
 *    从链表中删除
 *
 * */

void deleteFromList(List *head,Node *tmp)
{

    Node *tmp1;
    Node *tmp2;
    tmp1 = *head;
    tmp2 = tmp1;
    
    //如果链表剩了一个元素

    if(tmp->next == tmp){
        tmp->number = 0 ;
        tmp->pass = 0;
        return;
    }
    
    //如果此时删除了头节点,此时将头节点转移到头节点的下一个结点

    if((*head)->number == tmp->number){
        Node *x;
        Node *y;
        x = (*head)->next;
        while(x != (*head)){
            y = x;
            x = x->next;
        }
        y->next = (*head)->next;
        *head = (*head)->next;
    }else{
        //找到这个节点,删除他

        while(tmp1->number != tmp->number){
            tmp2 = tmp1;
            tmp1 = tmp1->next;
        }
        tmp2->next = tmp1->next;
    }
    

}


/*
 *    约瑟夫计数
 *
 * */

void yuesefu(List head, int m)
{
    Node *tmp;
    tmp = head;
    int time;
    time = m-1;
    int i = 0;
    printf("出队的顺序:(初始化的m=20)\n");
    
    while(tmp->number != 0){ //链表中此时没有结点,则退出


        for(i=0;i<time;i++){ //找到要删除的结点

            tmp = tmp->next;
        }
        printf("%d ",tmp->number);
        time = tmp->pass - 1;
        deleteFromList(&head,tmp);//删除结点

        tmp = tmp->next;//从下一个结点又开始计算

    }    
}

int main(int argc, char *argv[])
{
    int i;
    Node *p;
    
    int num[7] = {1,2,3,4,5,6,7};
    int pas[7] = {3,1,7,2,4,8,4};
    List head;
    head = (List)malloc(sizeof(List));
    initList(head);
    createFromTail(head,num,pas,sizeof(num)/sizeof(num[0]));

    p = head;
    printf("\n约瑟夫计数前,每个数和他的密码:\n");
    for(i = 0;i<sizeof(num)/sizeof(num[0]);i++){
        printf("%d,%d\n",p->number,p->pass);
        p = p->next;
    }

    printf("\n");
    yuesefu(head,20);
    printf("\n");
    return 0;
}


实现的过程中竟然遇到了一些问题,后来仔细考虑,终于实现了,数据结构还是要好好学习的。好了,今天这个只作记录,重要的地方程序中有详细的注释。有什么问题留言讨论。
阅读(12157) | 评论(1) | 转发(0) |
给主人留下些什么吧!~~

嗨_小萱2014-04-20 16:06:03

我还只是大一的学生,刚学c没多久,这个约瑟夫让我好痛苦,网上找灵感无意间看见了你的这篇博客,不明觉厉!!!!复制下来好好研究研究,定有大收获。我得代表我全家谢谢这位大神!!!