单向链表原理与C语言实现

本文详细介绍了单向链表的数据结构,包括节点的组成、链表的初始化、插入、删除和查找操作。同时讨论了链表的优点(如指针操作和动态扩容)和缺点(如单向遍历和数据耦合)。
摘要由CSDN通过智能技术生成

链式存储结构:
        不连续的存储空间(链表)
            链表是由一系列的节点组成的每个节点包含两个域:指针域、数据域
            节点的next指针指向空NULL则为最后一个节点。
        插入新节点
            找到插入的上一个节点,让其指针指向插入节点
            再让插入节点指针指向下一个节点
        删除新节点
            找到删除的上一个节点,让其指针指向删除元素的下一个节点
            回收删除元素的内存。

单向链表:

        节点之间只有单向连接关系,可以递归查找下一个节点

        数据层面相关的操作需要通过回调函数接口,用户自定义实现,但是在链表的节点层面包含有用户数据层,没有做到完全数据解耦合。

        

头文件的实现

//
// Created by zmj on 2024/1/16. 单向链表 传统链表
//
#ifndef TEST_LINKLIST_H
#define TEST_LINKLIST_H
#include "stdlib.h"
#include "stdio.h"
//链表节点
typedef struct LINKNODE{
    void* data;//void* 可以指向任何类型数据
    struct LINKNODE* next;
}LinkNode;
//链表
typedef struct LINKLIST{
    LinkNode *head;
    int size;
}LinkList;
typedef void(*PRINTLINKNODE)(void*);
//链表操作函数
//初始化
LinkList * Init_LinkList(){
    LinkList *list = (LinkList*)malloc(sizeof(LinkList));
    list->size=0;
    //头节点是不保存数据,避免头结点判断,简化逻辑
    list->head=(LinkNode*) malloc(sizeof(LinkNode));
    list->head->data = NULL;
    list->head->next = NULL;
    return list;
};
//指定位置插入
void Insert_LinkList(LinkList* list,int pos,void* data){
    if(list==NULL){
        return;
    }
    if(data==NULL){
        return;
    }
    if(pos<0||pos>list->size){
        pos = list->size;
    }
    //创建新的节点
    LinkNode *newnode = (LinkNode*)malloc(sizeof(LinkNode));
    newnode->data = data;
    newnode->next = NULL;
    //找到插入的上一个节点
    //先定义一个辅助节点,让其指向链表头。
    LinkNode *pFrontNode = list->head;
    for(int i=0;i<pos;i++){
        pFrontNode = pFrontNode->next;
    }
    //插入新节点
    newnode->next = pFrontNode->next;
    pFrontNode->next = newnode;
    list->size++;
};
//删除指定位置元素
void Remove_LinkList(LinkList* list,int pos){
    if(list==NULL){
        return;
    }
    if(pos<0||pos>list->size){
        return;
    }
    //查找删除节点的前一个节点
    LinkNode *pFrontNode = list->head;
    for(int i=0;i<pos;i++){
        pFrontNode = pFrontNode->next;
    }
    //辅助删除的节点指向下一个节点
    LinkNode *pDel = pFrontNode->next;
    pFrontNode->next = pDel->next;
    free(pDel);
    list->size--;
};
//获得链表的长度
int Size_LinkList(LinkList* list){
    return list->size;
};
//查找
int Find_LinkList(LinkList* list,void* data){
    if(list==NULL){
        return -1;
    }
    if(data==NULL){
        return -1;
    }
    LinkNode *pCurrent = list->head->next;
    int i=0;
    while (pCurrent!=NULL){
        if(pCurrent->data==data){
            break;
        }
        i++;
        pCurrent = pCurrent->next;
    }
};
//返回链表的第一个节点
void *Front_LinkList(LinkList* list){
    return list->head->next->data;
};
//打印链表
void Print_LinkList(LinkList* list,PRINTLINKNODE print){
    if(list==NULL){
        return;
    }
    LinkNode *pCurrent = list->head->next;
    while (pCurrent!=NULL){
        print(pCurrent->data);
        pCurrent = pCurrent->next;
    }
};
//释放链表的内存
void FreeSpace_LinkList(LinkList* list){
    if(list==NULL){
        return;
    }
    LinkNode *pCurrent =list->head;
    while (pCurrent!=NULL){
        LinkNode *pNext = pCurrent->next;
        free(pCurrent);
        pCurrent = pNext;
    }
    list->size=0;
    free(list);
};

#endif //TEST_LINKLIST_H

测试程序:

typedef struct PERSON{
    char name[64];
    int age;
    int score;
}Person;
//链表用户自定义打印回调函数
void MyPrint(void* data){
    Person *p = (Person*)data;
    printf(" name: %s, age: %d, score: %d\n",p->name,p->age,p->score);
}
int main(){
    //测试单向链表
    LinkList *list =Init_LinkList();
    Person p1 = {"aaa",22,90};
    Person p2 = {"bbb",18,100};
    Person p3 = {"ccc",16,86};
    Person p4 = {"ddd",20,105};
    Person p5 = {"eee",24,77};
    Insert_LinkList(list,0,&p1);
    Insert_LinkList(list,0,&p2);
    Insert_LinkList(list,0,&p3);
    Insert_LinkList(list,0,&p4);
    Insert_LinkList(list,0,&p5);
    Print_LinkList(list,MyPrint);
    Remove_LinkList(list,3);
    printf("------------------------\n");
    Print_LinkList(list,MyPrint);
    FreeSpace_LinkList(list);
    return 0;
}

优点:

        没有大量的数据操作,均是指针操作,可以无限扩容

缺点:

        只能单向迭代遍历,不能快捷访问,插入等操作仍然不够简洁

        数据定义在node里面,初始化释放均比较需要进行两次内存操作

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值