【数据结构】

单向循环链表

单向循环链表的特点

单链表最后一个节点的next指针指向的NULL,但是单向循环链表的next指针指向了头节点,这样它就形成了一个环状的效果。通过这个环可以一直获取next的成员,而不用每次都记录h节点的位置。

单向循环链表的结构

在这里插入图片描述

#define datatype int
typedef struct node{
    datatype data;
    struct node *next;  
}linklist_t;

单向循环链表的操作

单向循环链表的创建

在这里插入图片描述

looplink_t* LoopLinkCreate(void)
{   
    looplink_t *h;

    h = (looplink_t *)malloc(sizeof(*h));
    if(h == NULL){
        printf("malloc head memory error\n");
        return NULL;
    }

    h->data = (datatype)0;
    h->next = h;

    return h;
}
单向循环链表节点插入
单向循环链表头插法

在这里插入图片描述

int LoopLinkInsertHead(looplink_t* h, datatype data)
{
    looplink_t* tmp;

    tmp = (looplink_t*)malloc(sizeof(*tmp));
    if (tmp == NULL) {
        printf("malloc node memory error\n");
        return -1;
    }
    tmp->data = data;

    //进行头插法
    tmp->next = h->next;
    h->next = tmp;

    return 0;
}
单向循环链表尾插法

在这里插入图片描述

int LoopLinkInsertTail(looplink_t* h, datatype data)
{
    looplink_t* tmp;
    looplink_t* th = h;
    // 1.分配tmp节点,当data存入
    tmp = (looplink_t*)malloc(sizeof(*tmp));
    if (tmp == NULL) {
        printf("malloc node memory error\n");
        return -1;
    }
    tmp->data = data;
    // 2.通过循环找到尾部节点
    while(h->next != th){
        h = h->next;
    }
    // 3.将节点插入到当前位置
    tmp->next = h->next;
    h->next = tmp;

    return 0;
}
单向循环链位置插入

在这里插入图片描述

int LoopLinkInsertPos(looplink_t* h, int pos, datatype data)
{
    looplink_t *tmp, *th = h;
    // 1.判断pos是否合法
    if (pos < 0) {
        printf("插入的位置不合法\n");
        return -1;
    }

    // 2.通过循环找出插入节点的位置
    while (h->next != th || pos == 0) {
        if (pos != 0) {
            pos--;
            h = h->next;
        } else {
            // 3.找到了插入节点的位置,将节点插入即可。
            tmp = (looplink_t*)malloc(sizeof(*tmp));
            if (tmp == NULL) {
                printf("malloc memory error\n");
                return -1;
            }
            tmp->data = data;

            tmp->next = h->next;
            h->next = tmp;
            return 0;
        }
    }

    printf("插入的位置不合法\n");
    return -1;
}
单向循环链表的删除(位置)
datatype LoopLinkDeleteByPos(looplink_t* h, int pos)
{
    datatype data;
    looplink_t* tmp,*th=h;

    // 1.判断pos是否合法
    if (pos < 0) {
        printf("删除的位置不合法\n");
        return (datatype)-1;
    }

    // 2.通过循环找出删除节点的位置
    while (h->next != th) {
        if (pos != 0) {
            pos--;
            h = h->next;
        } else {
            // 4.找到了删除节点的位置,将节点删除即可。
            tmp = h->next;
            h->next = h->next->next;

            data = tmp->data;
            if (tmp != NULL) {
                free(tmp);
                tmp = NULL;
            }
            return data;
        }
    }

    printf("删除的位置不合法\n");
    return (datatype)-1;
}
单向循环链表的遍历
void LoopLinkShow(looplink_t* h)
{
    looplink_t *th=h;
    while (h->next != th) {
        printf("-%d", h->next->data);
        h = h->next;
    }
    printf("-\n");
}
单向循环链表的查询
datatype LoopLinkCheckDataByPos(looplink_t* h, int pos)
{
    datatype data;
    looplink_t* th = h;
    // 1.判断pos是否合法
    if (pos < 0) {
        printf("查询的位置不合法\n");
        return (datatype)-1;
    }
    // 2.通过循环找到查询的位置
    while (h->next != th) {
        if (pos != 0) {
            pos--;
            h = h->next;
        } else {
            // 查询到了位置
            data = h->next->data;
            return data;
        }
    }
    printf("查询的位置不合法\n");
    return (datatype)-1;
}
单向循环链表的更新
int LoopLinkUpdateDataByPos(looplink_t* h, int pos, datatype data)
{
    looplink_t* th = h;
    // 1.判断pos是否合法
    if (pos < 0) {
        printf("更新的位置不合法\n");
        return -1;
    }
    // 2.通过循环找到更新的位置
    while (h->next != th) {
        if (pos != 0) {
            pos--;
            h = h->next;
        } else {
            // 更新数据
            h->next->data = data;
            return 0;
        }
    }
    printf("更新的位置不合法\n");
    return -1;
}

单向循环链表的整体代码

looplink.h

#ifndef __LOOPLINK_H__
#define __LOOPLINK_H__

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

#define datatype int
typedef struct node {
    datatype data;
    struct node* next;
    // 这个指针指向的是下一个节点,节点是结构体类型,所以指针也要定义成结构体指针
} looplink_t;

looplink_t* LoopLinkCreate(void);
int LoopLinkInsertHead(looplink_t *h,datatype data);
int LoopLinkInsertTail(looplink_t *h,datatype data);
int LoopLinkInsertPos(looplink_t *h,int pos,datatype data);
void LoopLinkShow(looplink_t *h);
datatype LoopLinkDeleteByPos(looplink_t *h,int pos);
datatype LoopLinkCheckDataByPos(looplink_t *h,int pos);
int LoopLinkUpdateDataByPos(looplink_t *h,int pos,datatype data);
#endif

looplink.c

#include "looplink.h"

looplink_t* LoopLinkCreate(void)
{
    looplink_t* h;

    h = (looplink_t*)malloc(sizeof(*h));
    if (h == NULL) {
        printf("malloc head memory error\n");
        return NULL;
    }
    h->data = (datatype)0;
    h->next = h;

    return h;
}

int LoopLinkInsertHead(looplink_t* h, datatype data)
{
    looplink_t* tmp;

    tmp = (looplink_t*)malloc(sizeof(*tmp));
    if (tmp == NULL) {
        printf("malloc node memory error\n");
        return -1;
    }
    tmp->data = data;

    // 进行头插法
    tmp->next = h->next;
    h->next = tmp;

    return 0;
}
int LoopLinkInsertTail(looplink_t* h, datatype data)
{
    looplink_t* tmp;
    looplink_t* th = h;
    // 1.分配tmp节点,当data存入
    tmp = (looplink_t*)malloc(sizeof(*tmp));
    if (tmp == NULL) {
        printf("malloc node memory error\n");
        return -1;
    }
    tmp->data = data;
    // 2.通过循环找到尾部节点
    while (h->next != th) {
        h = h->next;
    }
    // 3.将节点插入到当前位置
    tmp->next = h->next;
    h->next = tmp;

    return 0;
}
int LoopLinkInsertPos(looplink_t* h, int pos, datatype data)
{
    looplink_t *tmp, *th = h;
    // 1.判断pos是否合法
    if (pos < 0) {
        printf("插入的位置不合法\n");
        return -1;
    }

    // 2.通过循环找出插入节点的位置
    while (h->next != th || pos == 0) {
        if (pos != 0) {
            pos--;
            h = h->next;
        } else {
            // 3.找到了插入节点的位置,将节点插入即可。
            tmp = (looplink_t*)malloc(sizeof(*tmp));
            if (tmp == NULL) {
                printf("malloc memory error\n");
                return -1;
            }
            tmp->data = data;

            tmp->next = h->next;
            h->next = tmp;
            return 0;
        }
    }

    printf("插入的位置不合法\n");
    return -1;
}
void LoopLinkShow(looplink_t* h)
{
    looplink_t* th = h;
    while (h->next != th) {
        printf("-%d", h->next->data);
        h = h->next;
    }
    printf("-\n");
}

datatype LoopLinkDeleteByPos(looplink_t* h, int pos)
{
    datatype data;
    looplink_t *tmp, *th = h;

    // 1.判断pos是否合法
    if (pos < 0) {
        printf("删除的位置不合法\n");
        return (datatype)-1;
    }

    // 2.通过循环找出删除节点的位置
    while (h->next != th) {
        if (pos != 0) {
            pos--;
            h = h->next;
        } else {
            // 4.找到了删除节点的位置,将节点删除即可。
            tmp = h->next;
            h->next = h->next->next;

            data = tmp->data;
            if (tmp != NULL) {
                free(tmp);
                tmp = NULL;
            }
            return data;
        }
    }

    printf("删除的位置不合法\n");
    return (datatype)-1;
}
datatype LoopLinkCheckDataByPos(looplink_t* h, int pos)
{
    datatype data;
    looplink_t* th = h;
    // 1.判断pos是否合法
    if (pos < 0) {
        printf("查询的位置不合法\n");
        return (datatype)-1;
    }
    // 2.通过循环找到查询的位置
    while (h->next != th) {
        if (pos != 0) {
            pos--;
            h = h->next;
        } else {
            // 查询到了位置
            data = h->next->data;
            return data;
        }
    }
    printf("查询的位置不合法\n");
    return (datatype)-1;
}
int LoopLinkUpdateDataByPos(looplink_t* h, int pos, datatype data)
{
    looplink_t* th = h;
    // 1.判断pos是否合法
    if (pos < 0) {
        printf("更新的位置不合法\n");
        return -1;
    }
    // 2.通过循环找到更新的位置
    while (h->next != th) {
        if (pos != 0) {
            pos--;
            h = h->next;
        } else {
            // 更新数据
            h->next->data = data;
            return 0;
        }
    }
    printf("更新的位置不合法\n");
    return -1;
}

main.c

#include "looplink.h"

int main(int argc, char const* argv[])
{
    looplink_t* h;

    h = LoopLinkCreate();
    if (h == NULL) {
        printf("create loop link error\n");
        return -1;
    }

    LoopLinkInsertHead(h, 40);
    LoopLinkInsertHead(h, 30);
    LoopLinkInsertHead(h, 20);
    LoopLinkInsertHead(h, 10);
    LoopLinkShow(h);
    // LoopLinkInsertTail(h,50);
    // LoopLinkShow(h);

    // LoopLinkInsertPos(h,0,111);
    // LoopLinkShow(h);

    // printf("delete pos = %d\n", LoopLinkDeleteByPos(h, 3));
    // printf("delete pos = %d\n", LoopLinkDeleteByPos(h, 0));
    // printf("delete pos = %d\n", LoopLinkDeleteByPos(h, 0));
    // printf("delete pos = %d\n", LoopLinkDeleteByPos(h, 0));
    // printf("delete pos = %d\n", LoopLinkDeleteByPos(h, 0));
    // LoopLinkShow(h);
    printf("Check pos = %d\n", LoopLinkCheckDataByPos(h, 3));
    LoopLinkUpdateDataByPos(h,4,444);
    LoopLinkShow(h);
    return 0;
}

单向循环链表的练习

在这里插入图片描述

void joseph(int n,int k,int m)
{

 1.创建一个有头的单向循环链表

 2.循环将1-n的数据插入到单向循环链表中

 3.剪掉单向循环链表的头

4.按照上述的规则循环删除成员,直到循环链表中没有成员为止。
}
单向循环链表去头

在这里插入图片描述

looplink_t* LoopLinkCutHead(looplink_t* h)
{
    looplink_t* th = h;

    // 1.判空
    if (h->next == th) {
        printf("这个链表是空\n");
        free(h);
        return NULL;
    }

    // 2.通过循环找到最后一个节点
    while (h->next != th) {
        h = h->next;
    }

    // 3.让最后一个节点,指向头节点的下一个节点
    h->next = th->next;

    // 4.释放头节点的内存
    if (th != NULL) {
        free(th);
        th = NULL;
    }
    // 5.返回
    return h->next;
}
单向循环链表无头遍历
void LoopLinkNoHeadShow(looplink_t* h)
{
    looplink_t* th = h;
    while (h->next != th) {
        printf("-%d", h->data);
        h = h->next;
    }
    printf("-%d-\n", h->data);
}
约瑟夫环代码实现
void joseph(int n, int k, int m)
{
    datatype data;
    int pos = k + m - 2;
    looplink_t* h;
    // 1.创建一个有头的单向循环链表
    h = LoopLinkCreate();
    if (h == NULL) {
        printf("create loop link error\n");
        return;
    }
    // 2.循环将1-n的数据插入到单向循环链表中
    for (int i = 0; i < n; i++) {
        LoopLinkInsertHead(h, n - i);
    }
    LoopLinkShow(h);

    // 3.剪掉单向循环链表的头
    h = LoopLinkCutHead(h);
    LoopLinkNoHeadShow(h);

    // 4.按照上述的规则循环删除成员,直到循环链表中没有成员为止。
    while(1){
        if(pos > 1){
            pos--;
            h = h->next;
        }else{
            if((data = LoopLinkCheckDataByPos(h,0)) == (datatype)-1){
                break;
            }
            printf("%d\t",data);

            LoopLinkDeleteByPos(h,0);
            pos = m;
        }
    }

    printf("%d\n",h->data);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值