C语言链表

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


一、pandas是什么?

1.介绍

链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。

在这里插入图片描述

2.具体思路

我们可以设计一个链表结构体,记录链表的头结点和长度,再设计一个节点结构体,包含指向下一节点的指针和记录的数据,在需要添加或删除节点时,从头节点遍历到相应位置修改节点指针指向,再进行开辟新节点和释放旧节点的操作。

二、程序

1.代码

#include <iostream>
#include "./link_list.h"
using namespace std;

typedef struct LinkNode //链表节点
{
    void *data;     //数据域,指向自定义数据类型
    LinkNode *next; //指针域
} LinkNode;

typedef struct //链表结构体
{
    LinkNode header;
    int length;
} Header;

struct Person //数据结构体
{
    int age;
    char name[20];
};

Header *init_link_list(void);
void insert(Header *list, int pos, void *data);
void remove(Header *list, int pos);
void print(Header *list, void (*my_print)(void *data));
void my_print(void *data);
int get_length(Header *list);
void empty(Header *list);
void destroy_list(Header *list);

//初始化
Header *init_link_list(void)
{
    Header *my_list = new Header;

    if (my_list == NULL)
    {
        return NULL;
    }
    my_list->length = 0;
    my_list->header.next = NULL;
    my_list->header.data = NULL;

    return my_list;
}

//插入节点
void insert(Header *list, int pos, void *data)
{
    if (list == NULL || data == NULL)
    {
        return;
    }
    if (pos < 0 || pos > list->length)
    {
        pos = list->length;
    }

    LinkNode *prev_node = &list->header;        //前驱节点
    LinkNode *current_node = list->header.next; //后继节点
    LinkNode *new_node = new LinkNode;

    new_node->data = data;
    new_node->next = NULL;
    for (int i = 0; i < pos; i++)
    {
        current_node = current_node->next;
        prev_node = prev_node->next;
    }
    prev_node->next = new_node;
    new_node->next = current_node;
    list->length++;
}

//删除节点
void remove(Header *list, int pos)
{
    if (list == NULL)
    {
        return;
    }
    if (pos < 0 || pos > list->length)
    {
        return;
    }

    LinkNode *prev_node = &list->header;        //前驱节点
    LinkNode *current_node = list->header.next; //后继节点

    for (int i = 0; i < pos; i++)
    {
        current_node = current_node->next;
        prev_node = prev_node->next;
    }
    prev_node->next = current_node->next;
    delete current_node;
    current_node = NULL;
    list->length--;
}

//打印链表
void print(Header *list, void (*my_print)(void *data))
{
    if (list == NULL)
    {
        return;
    }

    LinkNode *current_node = list->header.next;

    for (int i = 0; i < list->length; i++)
    {
        my_print(current_node->data);
        current_node = current_node->next;
    }
}

//自定义类型打印(回调)
void my_print(void *data)
{
    if (data == NULL)
    {
        return;
    }
    struct Person *p = (struct Person *)data;
    cout << p->name << " " << p->age << endl;
}

//返回链表长度
int get_length(Header *list)
{
    if (list == NULL)
    {
        return -1;
    }
    return list->length;
}

//清空链表
void empty(Header *list)
{
    if (list == NULL)
    {
        return;
    }

    LinkNode *current = list->header.next;

    for (int i = 0; i < list->length; i++)
    {
        LinkNode *next = current->next;
        delete current;
        current = next;
    }
    list->header.next = NULL;
    list->length = 0;
}

//销毁链表
void destroy_list(Header *list)
{
    if (list == NULL)
    {
        return;
    }
    empty(list);
    delete list;
    list = NULL;
}

int main(int argc, char const *argv[])
{
    Header *list = init_link_list();

    struct Person p1 = {20, "老王"};
    struct Person p2 = {21, "老张"};
    struct Person p3 = {22, "老李"};

    insert(list, 0, &p1);
    insert(list, 0, &p2);
    insert(list, 1, &p3);
    cout << "删除前长度:" << get_length(list) << endl;
    remove(list, 0);
    cout << "删除后长度:" << get_length(list) << endl;
    cout << "打印:" << endl;
    print(list, my_print);
    empty(list);
    cout << "清空后长度:" << get_length(list) << endl;
    destroy_list(list);
    return 0;
}

2.运行结果

删除前长度:3
删除后长度:2
打印:
老李 22
老王 20
清空后长度:0

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值