【数据结构】循环链表

目录

单向循环链表

单向循环链表插入操作

单向链表删除操作

单向循环链表实现

约瑟夫问题


单向循环链表

 最后一个结点指向头结点,循环就需要边界来控制

有两种方法:

  1. 判断当前 next 是否等于 头结点(每次都判断很费时)
  2. 通过 size 进行判断(循环方式遍历)

单向循环链表插入操作

让新结点的指针域指向要插入位置前一个结点的指向下一个结点的指针,在让要插入位置的前一个结点的指针域指向新结点

单向链表删除操作

创建新结点(保存待删除结点),新结点的前一个结点 pCurrent 的指针域指向新结点的下一个结点,完成删除操作

单向循环链表实现

  • 框架
// 链表结点
typedef struct CIRCLELINKNODE {
    struct CIRCLELINKNODE* next;
}CircleLinkNode;

// 链表结构体
typedef struct CIRCLELINKLIST {
    CircleLinkNode head;
    int size;
}CircleLinkList;
  • 函数声明
// 比较回调
typedef int(*COMPARE)(CircleLinkNode*, CircleLinkNode*);


// 打印回调
typedef void(*PRINTNODE)(CircleLinkNode*);


// 初始化
CircleLinkList* Init_CircleLinkList();

// 插入
void Insert_CircleLinkList(CircleLinkList* clist, int pos, CircleLinkNode* data);


// 获取第一个元素
CircleLinkNode* Front_CircleLinkList(CircleLinkList* clist);


// 位置 删除
void RemoveByPos_CircleLinkList(CircleLinkList* clist, int pos);


// 数据 删除
void RemoveByVal_CircleLinkList(CircleLinkList* clist, CircleLinkNode* data, COMPARE);


// 链表长度
int Size_CircleLinkList(CircleLinkList* clist);


// 判断是否为空
int IsEmpty_CircleLinkList(CircleLinkList* clist);


// 数据 查找
int Find_CircleLinkList(CircleLinkList* clist, CircleLinkNode* data, COMPARE);


// 打印
void Print_CircleLinkList(CircleLinkList* clist, PRINTNODE);


// 释放结点
void Free_CircleLinkList(CircleLinkList* clist);
  • 函数实现
// 初始化
CircleLinkList* Init_CircleLinkList(){
    
    CircleLinkList* clist = (CircleLinkList*)malloc(sizeof(CircleLinkList));
    clist->head.next = &(clist->head);
    clist->size = 0;
    return clist;
}

// 插入
void Insert_CircleLinkList(CircleLinkList* clist, int pos, CircleLinkNode* data){
    
    if (clist == NULL) return;
    if (data == NULL) return;
    if (pos < 0 || pos > clist->size) {
        pos = clist->size;
    }

    // 根据位置查找结点
    // 辅助指针
    CircleLinkNode* pCurrent = &(clist->head);
    for (int i = 0; i < pos; i++) {
        pCurrent = pCurrent->next;
    }
    // 新数据入链表
    data->next = pCurrent->next;
    pCurrent->next = data;
    clist->size++;
}

// 获取第一个元素
CircleLinkNode* Front_CircleLinkList(CircleLinkList* clist){
    return clist->head.next;
}

// 位置 删除
void RemoveByPos_CircleLinkList(CircleLinkList* clist, int pos){
    
    if (clist == NULL) return;
    if (pos < 0 || pos >= clist->size) return;

    // 根据 pos 找结点
    // 辅助指针变量
    CircleLinkNode* pCurrent = &(clist->head);
    for (int i = 0; i < pos; i++) {
        pCurrent = pCurrent->next;
    }
    // 删除
    // 缓存当前结点的下一个结点
    CircleLinkNode* pNext = pCurrent->next;
    pCurrent->next = pNext->next;

    clist->size--;
}

// 数据 删除
void RemoveByVal_CircleLinkList(CircleLinkList* clist, CircleLinkNode* data, COMPARE compare){
    
    if (clist == NULL) return;
    if (data == NULL) return;

    // 循环链表
    CircleLinkNode* pPrev = &(clist->head);
    CircleLinkNode* pCurrent = pPrev->next;
    for (int i = 0; i < clist->size; i++) {
        if (compare(data, pCurrent) == 0) {
            pPrev->next = pCurrent->next;
            break;
        }
        pPrev = pPrev->next;
        pCurrent = pPrev->next;
    }
    
    clist->size--;
}

// 链表长度
int Size_CircleLinkList(CircleLinkList* clist){
    if (clist == NULL) return 0;
    return clist->size;
}

// 判断是否为空
int IsEmpty_CircleLinkList(CircleLinkList* clist){
    return Size_CircleLinkList(clist) ? CIRCLELINKLIST_TRUE : CIRCLELINKLIST_FALSE;
}

// 数据 查找
int Find_CircleLinkList(CircleLinkList* clist, CircleLinkNode* data, COMPARE compare){
    
    if (clist == NULL) return -1;
    if (data == NULL) return -1;

    CircleLinkNode* pCurrent = clist->head.next;
    for (int i = 0; i < clist->size; i++) {
        if (compare(data, pCurrent) == 0) {
            return i;
        }
        pCurrent = pCurrent->next;
    }
    return -1;
}

// 打印
void Print_CircleLinkList(CircleLinkList* clist, PRINTNODE printnode){
    
    if (clist == NULL) return;
    
    CircleLinkNode* pCurrent = clist->head.next;
    for (int i = 0; i < clist->size; i++) {
        if (pCurrent == &(clist->head)) {
            break;
            pCurrent = pCurrent->next;
        }
        printnode(pCurrent);
        pCurrent = pCurrent->next;
    }
}

// 释放结点
void Free_CircleLinkList(CircleLinkList* clist){
    
    if (clist == NULL) return;

    free(clist);
    clist = NULL;
}
  • 测试代码
typedef struct PERSON {
    CircleLinkNode node;
    char name[64];
    int age;
}Person;

int MyCompare(CircleLinkNode* data1, CircleLinkNode* data2) {
    Person* node1 = (Person*)data1;
    Person* node2 = (Person*)data2;

    if ((strcmp(node1->name, node2->name) == 0) && node1->age == node2->age) {
        return 0;
    }
    else {
        return -1;
    }
}

void MyPrint(CircleLinkNode* data) {
    Person* node = (Person*)data;
    printf("%s %d\n", node->name, node->age);
}


void test() {
    Person p1, p2, p3;
    strcpy(p1.name, "张三");
    strcpy(p2.name, "李四");
    strcpy(p3.name, "王五");

    p1.age = 10;
    p2.age = 20;
    p3.age = 30;

    CircleLinkList* list = Init_CircleLinkList();
    Insert_CircleLinkList(list, 0, (CircleLinkNode*)&p1);
    Insert_CircleLinkList(list, 0, (CircleLinkNode*)&p2);
    Insert_CircleLinkList(list, 0, (CircleLinkNode*)&p3);

    printf("链表长度: %d\n", Size_CircleLinkList(list)); // 3

    RemoveByVal_CircleLinkList(list, (CircleLinkNode*)&p3, MyCompare); // 删除 p3

    printf("链表长度: %d\n", Size_CircleLinkList(list)); // 2

    RemoveByPos_CircleLinkList(list, 0); // 删除 p2

    printf("链表长度: %d\n", Size_CircleLinkList(list)); // 1

    Print_CircleLinkList(list, MyPrint);

    Person find_p;
    strcpy(find_p.name, "张三");
    find_p.age = 10;
    int ret = Find_CircleLinkList(list, (CircleLinkNode*)&find_p, MyCompare);
    if (ret >= 0) printf("pos = %d", ret);
    else printf("未找到");
    Free_CircleLinkList(list);
}

运行结果:


约瑟夫问题

n 个人围成一圈,首先第 1 个人从 1 开始顺序

报数,报到第 m 个人,令其出列,然后再从下一个人开始从 1 开始报数,报到第 m 个人,再令其出列,求出列顺序。

方法:

主要运用循环链表,创建一个值 index 存放每次报到数(从 1 开始初始化为 1),运用循环直到链表长度等于 1 停止循环,在循环内做判断,当 index 等于 m 时执行执行打印操作,再删除操作,将 index重置为 1,循环链表遍历需要借助辅助指针,辅助指针指向头结点时需要进行移动(指向第一个结点)

  • 框架
typedef struct LINKLISTNODE {
    struct LINKLISTNODE* next;
}ListNode;


typedef struct CIRCLELINKLIST {
    ListNode head;
    int size;
}CircleLinkList;
  • 函数声明
typedef void(*PRINTNODE)(ListNode*);

typedef int(*COMPARE)(ListNode*, ListNode*);

// 初始化
CircleLinkList* Init_List();

// 插入
void Insert_List(CircleLinkList* list, int pos, ListNode* data);

// 数据 查找
int FindByVal_List(CircleLinkList* list, ListNode* data, COMPARE compare);

// 位置 查找
ListNode* FindByPos_List(CircleLinkList* list, int pos);

// 数据 删除
void RemoveByVal_List(CircleLinkList* list, ListNode* data, COMPARE compare);

// 位置 删除
void RemoveByPos_List(CircleLinkList* list, int pos);

// 获取长度
int Size_List(CircleLinkList* list);

// 获取第一个结点
ListNode* Front_List(CircleLinkList* list);

// 打印
void Print_List(CircleLinkList* list, PRINTNODE print);

// 销毁
void FreeSpace_List(CircleLinkList* list);
  • 函数实现
// 初始化
CircleLinkList* Init_List(){
    CircleLinkList* list = (CircleLinkList*)malloc(sizeof(CircleLinkList));
    list->head.next = &(list->head);
    list->size = 0;
    return list;
}

// 插入
void Insert_List(CircleLinkList* list, int pos, ListNode* data){
    if (list == NULL) return;
    if (data == NULL) return;
    if (pos < 0 || pos > list->size) {
        pos = list->size;
    }
    // 辅助指针
    ListNode* pCurrent = &(list->head);
    for (int i = 0; i < pos; i++) {
        pCurrent = pCurrent->next;
    }
    data->next = pCurrent->next;
    pCurrent->next = data;
    list->size++;
}

// 数据 查找
int FindByVal_List(CircleLinkList* list, ListNode* data, COMPARE compare){
    int flag = -1;
    if (list == NULL) return flag;
    if (data == NULL) return flag;
    ListNode* pCurrent = list->head.next;
    for (int i = 0; i < list->size; i++) {
        if (compare(data, pCurrent) == 0) {
            flag = i;
            break;
        }
        pCurrent = pCurrent->next;
    }
    return flag;
}

// 位置 查找
ListNode* FindByPos_List(CircleLinkList* list, int pos){
    if (list == NULL) return NULL;
    if (pos < 0 || pos > list->size) {
        return NULL;
    }

    ListNode* pCurrent = &(list->head);
    for (int i = 0; i < pos; i++) {
        pCurrent = pCurrent->next;
    }
    return pCurrent->next;
}

// 数据 删除
void RemoveByVal_List(CircleLinkList* list, ListNode* data, COMPARE compare) {
    if (list == NULL) return;
    if (data == NULL) return;

    ListNode* pPrev = &(list->head);
    ListNode* pDele = pPrev->next;
    for (int i = 0; i < list->size; i++) {
        if (compare(data, pDele) == 0) {
            pPrev->next = pDele->next;
            break;
        }
        pPrev = pPrev->next;
        pDele = pPrev->next;
    }
    list->size--;
}

// 位置 删除
void RemoveByPos_List(CircleLinkList* list, int pos){
    if (list == NULL) return;
    if (pos < 0 || pos > list->size) return;

    ListNode* pCurrent = &(list->head);
    for (int i = 0; i < pos; i++) {
        pCurrent = pCurrent->next;
    }
    pCurrent->next = pCurrent->next->next;
    list->size--;
}

// 获取长度
int Size_List(CircleLinkList* list) {
    if (list == NULL) return 0;
    return list->size;
}

// 获取第一个结点
ListNode* Front_List(CircleLinkList* list) {
    if (list == NULL) return NULL;
    return list->head.next;
}

// 打印
void Print_List(CircleLinkList* list, PRINTNODE print){
    if (list == NULL) return;
    ListNode* pCurrent = list->head.next;
    for (int i = 0; i < list->size; i++) {
        print(pCurrent);
        pCurrent = pCurrent->next;
    }
}

// 销毁
void FreeSpace_List(CircleLinkList* list){
    if (list == NULL) return;
    free(list);
}
  • 测试代码
#define M 8
#define N 3

typedef struct Person {
    ListNode node;
    int num;
}Person;

int MyCompare(ListNode* node1, ListNode* node2) {
    Person* p1 = (Person*)node1;
    Person* p2 = (Person*)node2;
    if (p1->num == p2->num) return 0;
    else return -1;
}

void MyPrint(ListNode* node) {
    Person* p = (Person*)node;
    printf("%d ", p->num);
}

void Joseph() {
    // 创建循环链表 并初始化
    CircleLinkList* list = Init_List(); 
    // M 个人的数组
    Person num[M];
    // 1-M 初始化数组,并尾插插入循环链表
    for (int i = 0; i < M; i++) {
        num[i].num = i + 1;
        Insert_List(list, i, (ListNode*)&num[i]);
    }
    Print_List(list, MyPrint);
    printf("\n");
    // 默认从 1 开始数
    int index = 1;
    // 辅助指针指向头结点的下一个位置
    ListNode* pCurrent = list->head.next;
    // 直到 链表长度 == 1 时结束
    while (Size_List(list) > 1) {
        // 当数到的数等于 N 执行删除
        if (index == N) {
            // 类型转化
            Person* tempPerson = (Person*)pCurrent;
            // 输出
            printf("%d ", tempPerson->num);
            // 缓存待删除结点的下一个结点
            ListNode* pNext = pCurrent->next;
            // 数据 删除
            RemoveByVal_List(list, pCurrent, MyCompare);
            // 移动指针
            pCurrent = pCurrent->next;
            // 跳过头结点
            if (pCurrent == &(list->head)) {
                pCurrent = pCurrent->next;
            }
            // 重新开始数
            index = 1;
        }
        // 报数加 1
        index++;
        // 移动指针
        pCurrent = pCurrent->next;
        // 跳过头节点
        if (pCurrent == &(list->head)) {
            pCurrent = pCurrent->next;
        }
    }
    // 输出最后一个人
    if (Size_List(list) == 1) {
        MyPrint(Front_List(list));
        printf("\n");
    }
    else {
        printf("ERROR");
    }
    FreeSpace_List(list);
}

运行结果:

  • 单文件
#include<stdio.h>
#include<stdlib.h>

// 结点
typedef struct LinkListNode {
    struct LinkListNode* next;
}LinkListNode;

// 链表
typedef struct CircleLinkList {
    LinkListNode head;
    int size;
}CircleLinkList;

typedef struct Person {
    LinkListNode node;
    int num;
}Person;

// 比较函数指针
typedef int(*COMPARE)(LinkListNode* node1, LinkListNode* node2);

// 打印函数指针
typedef void(*PRINTNODE)(LinkListNode* node);

int MyCompare(LinkListNode* node1, LinkListNode* node2);

void MyPrint(LinkListNode* node);

// 初始化
CircleLinkList* Init_List() {
    CircleLinkList* list = (CircleLinkList*)malloc(sizeof(CircleLinkList));
    list->head.next = &(list->head);
    list->size = 0;
    return list;
}

// 插入
void Insert_List(CircleLinkList* list, LinkListNode* newNode, int pos) {
    if (list == NULL)    return;
    if (newNode == NULL) return;
    if (pos < 0 || pos > list->size) {
        pos = list->size;
    }
    // 辅助指针
    LinkListNode* pCurrent = &(list->head);
    for (int i = 0; i < pos; i++) {
        pCurrent = pCurrent->next;
    } // 找到插入位置的前一个位置
    newNode->next = pCurrent->next;
    pCurrent->next = newNode;
    // 更新长度
    list->size++;
}

// 数据 删除
void RemoveByVal(CircleLinkList* list, LinkListNode* delNode, COMPARE compare) {
    if (list == NULL)    return;
    if (delNode == NULL) return;

    // 辅助指针
    LinkListNode* pPrev = &(list->head); // 从第一个数据开始
    LinkListNode* pNext = pPrev->next;
    for (int i = 0; i < list->size; i++) {
        if (compare(delNode, pNext) != 0) {
            pPrev->next = delNode->next;
            break;
        }
        pPrev = pPrev->next;
        pNext = pPrev->next;
    }
    list->size--;
}

// 位置 删除
void RemoveByPos_List(CircleLinkList* list, int pos) {
    if (list == NULL) return;
    if (pos < 0 || pos >list->size) {
        return;
    }
    // 辅助指针
    LinkListNode* pCurrent = &(list->head);
    for (int i = 0; i < pos; i++) {
        pCurrent = pCurrent->next;
    }
    pCurrent->next = pCurrent->next->next;
    list->size--;
}

// 数据 查找
int FindByVal_List(CircleLinkList* list, LinkListNode* findNode, COMPARE compare) {
    if (list == NULL) return -1;
    if (findNode == NULL) return -1;

    // 辅助指针
    LinkListNode* pCurrent = list->head.next;
    for (int i = 0; i < list->size; i++) {
        if (compare(findNode, pCurrent) != 0) {
            return i;
        }
    }
    return -1;
}

// 位置 查找
LinkListNode* FindByVal_list(CircleLinkList* list, int pos) {
    if (list == NULL)   return NULL;
    if (pos < 0 || pos > list->size) {
        return NULL;
    }

    // 辅助指针
    LinkListNode* pCurrent = &(list->head);
    for (int i = 0; i < pos; i++) {
        pCurrent = pCurrent->next;
    }
    return pCurrent->next;
}

// 返回第一个结点
LinkListNode* Front_List(CircleLinkList* list) {
    if (list == NULL) return NULL;
    return list->head.next;
}

// 获取长度
int Size_List(CircleLinkList* list) {
    return list->size;
}

// 输出
void Print_List(CircleLinkList* list) {
    if (list == NULL) return;
    // 辅助指针
    LinkListNode* pCurrent = list->head.next;
    for (int i = 0; i < list->size; i++) {
        MyPrint(pCurrent);
        pCurrent = pCurrent->next;
    }
}

// 释放
void FreeSpace_list(CircleLinkList* list) {
    if (list == NULL) return;
    free(list);
}

int MyCompare(LinkListNode* node1, LinkListNode* node2) {
    Person* p1 = (Person*)node1;
    Person* p2 = (Person*)node2;
    if (p1->num == p2->num) return 1;
    else return 0;
}

void MyPrint(LinkListNode* node) {
    Person* p = (Person*)node;
    printf("%d ", p->num);
}

// 测试函数
void test01(int m) {
    CircleLinkList* list = Init_List();
    Person arr[8];
    for (int i = 0; i < 8; i++) {
        arr[i].num = i + 1;
        Insert_List(list, (LinkListNode*)&arr[i], i);
    }
    Print_List(list);
    printf("\n");
    int index = 1;
    LinkListNode* pCurrent = list->head.next;
    while (Size_List(list) > 1) {
        if (index == m) {
            // 类型转换输出
            Person* tempPerson = (Person*)pCurrent;
            MyPrint((LinkListNode*)tempPerson);
            // 删除
            LinkListNode* pNext = pCurrent->next;
            RemoveByVal(list, pCurrent, MyCompare);
            pCurrent = pCurrent->next;
            // 跳过头节点
            if (pCurrent == &(list->head)) {
                pCurrent = pCurrent->next;
            }
            // 重置 index
            index = 1;
        }
        index++;
        pCurrent = pCurrent->next;
        // 跳过头结点
        if (pCurrent == &(list->head)) {
            pCurrent = pCurrent->next;
        }
    }
    if (Size_List(list) == 1) {
        // 输出最后一个人
        MyPrint(Front_List(list));
        printf("\n");
    }
    else printf("ERROR");
}

int main() {
    test01(3); // 第三个人
    return 0;
}
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值