单循环链表的实现--C 语言版,详细讲解+代码实现

单链表的实现–C 语言版,详细讲解+代码实现



前言

`
继上一篇单链表的讲解和实现,现在进行循环单链表的实现。


一、循环单链表是什么?

所谓循环单链表,就是在单链表的基础上,将序列进行头尾相连,使链表变为逻辑上的环形。
简单来说,循环链表,就是在单链表的基础上,将单链表的最后一个元素的指针,由空,变为了指向头结点。

二、代码实现

1.设计数据结构

为方便讲解和理解,我们还是选择将链表中存储的数据设计为整型,同时头节点的data中存储的是整个循环单链表的长度。

typedef struct Node
{
    int data;
    struct Node* next;
}Node;```

2.循环单链表的初始化

由于循环单链表是逻辑上的环形结构,首位相连,所以当我们初始化的时候,链表中实际上只有一个头节点,这时,头节点的指针指向自己。
同时,由于我们设计的单链表的头指针存储的数据是链表的长度,所以,我们初始化的时候也将头节点的data初始化为0.

Node* init(){
    Node* node=(Node*)malloc(sizeof(Node));
    node->data=0;
    node->next=node;
    return node;
}

3.头插法的实现

个人认为,单循环链表的头插法和单链表的头插法几乎是一样的
思路和单链表的头插法一样

  1. 首先定义一个结点用来容纳数据
  2. 将这个结点的next指针指向头节点的next
  3. 将头指针的next指向新定义的结点
  4. 将头指针的data+1
//头插法
void head_insert(Node* node , int data){
    Node* curnode=(Node*)malloc(sizeof(Node));
    curnode->data=data;
    curnode->next=node->next;
    node->next=curnode;
    node->data++;
}

4.尾插法的实现

尾插法好像也单链表基本一样(手动捂脸)。
思路步骤如下:

  1. 定义一个结点来容纳新的数据
  2. 定义一个辅助结点用来辅助操作,首先将辅助结点赋值为首元结点(头节点后的第一个结点)用来循环寻找最后一个节点
  3. 通过辅助结点来循环,直到辅助结点的next的next为头节点的next,这就说明当前辅助结点的位置为头节点的前一个,辅助结点的next就是头节点,也就是说他就是理论上链表的最后一个。
  4. 此时将新的结点的指针指向头节点,同时将辅助结点的指针指向新结点实现拼接。
  5. 将头指针的data+1
//尾插法
void tail_insert(Node* node,int data){
    Node* curnode=(Node*)malloc(sizeof(Node));
    Node* helpnode=(Node*)malloc(sizeof(Node));
    curnode->data=data;
    helpnode = node->next;
    while(helpnode){
        if(helpnode->next->next==node->next){
            curnode->next = helpnode->next;
            helpnode->next = curnode;
            node->data++;
            break;
        }
        helpnode = helpnode->next;
    }
}

5. 结点的删除

删除好像也和单链表一样?(手动思考)
思路步骤如下

  1. 初始化一个当前节点curnode和一个当前结点的前一个结点prenode,
  2. 用当前节点curnode来进行循环,当curnode的next和头节点的next地址一样时,说明循环经过一周,停止循环。
  3. 在每一次循环时,判断当前结点的data和要删除的data是否一样,当一样的时候,将prenode的next指向curnode的next,并释放curnode
  4. 将头节点的data值+1
//删除
void delete(Node* node,int data){
    Node* curnode=(Node*)malloc(sizeof(Node));
    Node* prenode=(Node*)malloc(sizeof(Node));
    prenode = node;
    curnode= node->next;
    while(curnode){
        if(curnode->next==node->next){
            break;
        }
        if(curnode->data == data){
            prenode->next = curnode->next;
            free(curnode);
            node->data--;
            break;
        }
    }    
}

6. 结点的遍历

感觉…单链表和循环链表,好像,都一样啊,是我的错觉吗?
遍历的步骤:

  1. 初始化一个结点用来存储当前结点的地址
  2. 用该节点进行循环,并输出当前结点的data。
//遍历
void show(Node* node){
    Node* curnode=(Node*)malloc(sizeof(Node));
    curnode=node->next;
    while (curnode)
    {
        if(curnode->next==node->next){
            break;
        }else{
            printf("%d\n",curnode->data);
            curnode=curnode->next;
        }
    }  
}

总结

这单链表和循环单链表,实际上就是多了一个最后一个结点地址指向头节点,没了。
(doge)(doge)(doge)(doge)(doge)(doge)

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
当然可以!下面是C语言实现约瑟夫环的完整代码: ```c #include <stdio.h> #include <stdlib.h> // 定义循环链表的节点结构 typedef struct Node { int data; struct Node* next; } Node; // 创建循环链表 Node* createCircularLinkedList(int n) { Node* head = NULL; Node* prev = NULL; for (int i = 1; i <= n; i++) { Node* newNode = (Node*)malloc(sizeof(Node)); newNode->data = i; if (head == NULL) { head = newNode; } else { prev->next = newNode; } newNode->next = head; prev = newNode; } return head; } // 删除指定位置的节点 Node* deleteNode(Node* head, int position) { if (head == NULL) { return NULL; } Node* current = head; Node* prev = NULL; // 找到要删除的节点 for (int i = 1; i < position; i++) { prev = current; current = current->next; } // 删除节点 if (prev == NULL) { prev = current; while (prev->next != head) { prev = prev->next; } prev->next = current->next; head = current->next; } else { prev->next = current->next; } free(current); return head; } // 约瑟夫环算法 void josephusCircle(Node* head, int m, int n) { Node* current = head; // 找到起始位置 for (int i = 1; i < m; i++) { current = current->next; } // 开始约瑟夫环 while (n > 0) { printf("%d ", current->data); head = deleteNode(head, m); current = current->next; n--; } } int main() { int n, m; printf("请输入总人数n:"); scanf("%d", &n); printf("请输入报数m:"); scanf("%d", &m); Node* head = createCircularLinkedList(n); printf("约瑟夫环的顺序为:"); josephusCircle(head, m, n); return 0; } ``` 希望对你有帮助!如果还有其他问题,请随时提问。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值