O(1)时间删除单向循环链表给定结点

//O(1)时间删除单向循环链表给定结点(已知指向该结点的指针)
/*若是不带哨兵的单链表,删除非最后结点可以在O(1)完成。
但是,若删除的是最后结点,则必须修改最后结点的前驱的next为NULL,
故此时不得不得到p的前驱(需要O(n))。
单向循环链表则不一样了,每一个结点的next都非NULL(即都有后继)。
*/
//带哨兵的单向循环链表。NIL的next是头结点,尾结点的next是NIL
#include<stdio.h>
#include<stdlib.h>
typedef struct NODE{
    char key;struct NODE* next;
}NODE;
NODE *NIL=NULL;
void insert(NODE* p)
{//插入到头结点
    p->next=NIL->next;
    NIL->next=p;
}
void delete(NODE* p)
{//把p下一结点next的值给p,然后删除next
    if(!p) return ;
    NODE* next=p->next;
    p->key=next->key;
    p->next=next->next;
    if(next==NIL) NIL=p;//若p是最后结点,因为p->next=NIL,故NIL要指向p原来的内存空间
    free(next);
}
NODE* search(char key)
{
    NODE*p=NIL->next;NIL->key=key;
    while(p->key!=key) p=p->next;
    return p==NIL?NULL:p;
}
NODE* createnode(char key)
{
    NODE*p=(NODE*)malloc(sizeof(NODE));
    if(!p){
        puts("memory exhausted.");exit(1);
    }
    p->key=key;
    return p;
}
void traverse()
{
    NODE*p;
    for(p=NIL->next;p!=NIL;p=p->next)
        putchar(p->key);
    putchar('\n');
}
int main(void)
{
    //初始化NIL链表
    NIL=createnode('?');NIL->next=NIL;

    insert(createnode('a'));
    delete(search('a'));
    traverse();
    insert(createnode('b'));
    insert(createnode('c'));
    insert(createnode('d'));
    insert(createnode('e'));
    delete(search('e'));
    traverse();
    delete(search('b'));
    delete(search('c'));
    delete(search('b'));
    //delete(search('d'));
    //delete(search('b'));
    traverse();
    return 0;
}




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
意人可以指定一个起始编号,从这个编号的人开始从 1 报数,依次往下,数到给定的密码的人出圈,直到圈中只剩下一个人为止。请你用 C 语言实现这个约瑟夫环问题的求解。 以下是 C 语言实现代码: ```c #include <stdio.h> #include <stdlib.h> typedef struct node { int num; int password; struct node *next; } Person; Person *createList(int n) { // 创建循环链表 Person *head, *tail, *p; head = tail = (Person *)malloc(sizeof(Person)); // 创建头结点 head->num = 1; printf("Please input the password for Person %d: ", 1); scanf("%d", &head->password); for (int i = 2; i <= n; i++) { // 创建 n 个结点 p = (Person *)malloc(sizeof(Person)); p->num = i; printf("Please input the password for Person %d: ", i); scanf("%d", &p->password); tail->next = p; // 将新结点插入到链表尾部 tail = p; } tail->next = head; // 将链表尾部指向头结点,形成循环链表 return head; } void josephus(int n, int m, Person *head) { // 约瑟夫环问题求解 Person *p = head, *q; int count = 0; while (p->next != p) { // 当链表中只有一个结点时跳出循环 count++; if (count == m) { // 找到要出圈的结点 printf("Person %d is out!\n", p->num); q->next = p->next; // 删除结点 free(p); p = q->next; count = 0; } else { q = p; p = p->next; } } printf("Person %d is the last one!\n", p->num); // 输出最后留下的结点 free(p); } int main() { int n, m; printf("Please input the number of persons: "); scanf("%d", &n); printf("Please input the password to count off: "); scanf("%d", &m); Person *head = createList(n); // 创建循环链表 josephus(n, m, head); // 约瑟夫环问题求解 return 0; } ``` 这段代码中,我们首先定义了一个 `Person` 结构体,用于存储每个人的编号和密码。然后,我们定义了 `createList` 函数,用于创建循环链表。在 `createList` 函数中,我们先创建头结点,然后依次创建 n 个结点并插入到链表尾部,最后将链表尾部指向头结点,形成循环链表。 接着,我们定义了 `josephus` 函数,用于求解约瑟夫环问题。在 `josephus` 函数中,我们用一个循环来遍历链表,每次数到给定的密码就将该结点删除。具体实现中,我们用两个指针 p 和 q 分别指向当前结点和当前结点的前一个结点,便于删除结点后修改链表指针。 最后,在 `main` 函数中,我们先读入人数和密码,然后调用 `createList` 函数创建循环链表,最后调用 `josephus` 函数求解约瑟夫环问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值