数据结构——单向循环链表

一、单向循环链表

单向循环链表也称约瑟夫链表。据说著名犹太历史学家 Josephus有过以下的故事:在罗马人占领乔塔帕特后,39个犹太人与Josephus及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被敌人抓到,于是决定了一个自杀方式,41个人排成一个圆圈,由第1个人开始报数,每报数到第3人该人就必须自杀,然后再由下一个重新报数,直到所有人都自杀身亡为止。然而Josephus和他的朋友并不想遵从。首先从一个人开始,越过k-2个人(因为第一个人已经被越过),并杀掉第k个人。接着,再越过k-1个人,并杀掉第k个人。这个过程沿着圆圈一直进行,直到最终只剩下一个人留下,这个人就可以继续活着。问题是,给定了和,一开始要站在什么地方才能避免被处决?Josephus要他的朋友先假装遵从,他将朋友与自己安排在第16个与第31个位置,于是逃过了这场死亡游戏。

单向循环链表

二、用C语言实现单向循环链表

1、构造存储结构

typedef int datatype;
typedef struct josephus
{
    datatype data;  /* 数据域 */
    struct josephus *next;  /* 指针域 */
}josephus_list, *josephus_plist;

2、初始化

初始化主要工作:①申请头结点空间;②head->next=head

初始化

/* 初始化 */
void init_josephus_list(josephus_plist *list)
{
    *list = (josephus_plist)malloc(sizeof(josephus_list));
    if(NULL == *list)
    {
        printf("内存申请失败\n");
        perror("malloc");   /* 打印内存申请失败原因 */
        exit(1);
    }
    (*list)->next = *list;   /* 将next设为NULL,建立空链表 */
}

3、插入
链表插入

void insert_josephus_list(josephus_plist head, josephus_plist new)
{
    new->next = head->next;
    head->next = new;
}

4、删除

删除结点和单向链表的删除思想一样。

链表删除

void delete_josephus_list(josephus_plist pnode)
{
    josephus_plist dnode;

    dnode = pnode->next;
    pnode->next = dnode->next;
    free(dnode);
}

5、判断链表是否为空

即判断head是否等于head->next

/* 判断是否为空 */
bool isempty(josephus_plist head)
{
    if(head == head->next)
    {
        return true;
    }
    else
    {
        return false;
    } 
}

5、打印链表

void show_josephus_list(josephus_plist head)
{
    josephus_plist p = NULL;
    
    for(p = head; p->next != head; p = p->next)
    {
        printf("%d\t", p->data);
    }
    printf("%d\n", p->data);
}

三、练习题:实现约瑟夫环

1、创建链表

/* 创建单向循环链表 */
void create_josephus_list(josephus_plist head)
{
    josephus_plist new = NULL;
    josephus_plist p = head;
    int len = 0;
    int i = 0;

    printf("输入要插入数据的个数:");
    scanf("%d", &len);

    for(i = 0; i < len; i++)
    {
        if (0 == i)
        {
            scanf("%d", &(head->data));
        }
        else
        {
            new = (josephus_plist)malloc(sizeof(josephus_list));
            if(NULL == new)
            {
                printf("内存申请失败\n");
                perror("malloc");
                exit(1);
            }
            printf("输入要插入的第%d个数据:", (i+1));
            scanf("%d", &(new->data));
            insert_josephus_list(p, new);
            p = p->next;
        }
        show_josephus_list(head);   /* 打印 */
    }
}

2、实现约瑟夫

/* n是第n个要删除的结点 */
void josephus(josephus_plist head, int n)
{
    int i = 0;
    josephus_plist p = head;

    while(p != p->next)
    {
        for(i = 0; i < n-2; i++)
        {
            p = p->next;
        }
        printf("-->%d", p->next->data);
        delete_josephus_list(p);
        p = p->next;
    }
    printf("-->%d\n", p->data);
}

3、main函数

int main(void)
{
    josephus_plist head = NULL;        /* 定义一个头指针 */

    init_josephus_list(&head);   /* 初始化 */
    create_josephus_list(head);  /* 创建单向链表 */
    josephus(head, 3);
    return 0;
}

4、实验结果

实验结果

发布了54 篇原创文章 · 获赞 92 · 访问量 7万+

猜你喜欢

转载自blog.csdn.net/Sanjay_Wu/article/details/103445135