数据结构—单向链表—C语言描述

单向链表

** 注释非常丰富,并给出了测试例子,可直接编译运行!**

//
// Created by szw on 2021/9/17.
//


//
// Created by wen on 2021/9/15.
//
#define MISTAKE_1 1
#include "stdio.h"
#include "stdlib.h"
#include "string.h"

//定义节点结构
typedef struct LinkNode{
    //数据域
    void *data;
    //指针域
    struct LinkNode* next;

}LinkNode;

//定义链表结构
typedef struct LList{
    //头节点
    struct LinkNode pHeader;
    //链表长度
    int m_size;
}LList;

//保持数据操作安全性
typedef void * LinkList;

//初始化链表
LinkList init_LinkList(){

    LList *myList = malloc(sizeof (LList));
    //内存分配失败
    if(myList==NULL)
    {
        return NULL;
    }
    //链表头结点数据初始化
    myList->pHeader.data=NULL;
    //链表头节点指针初始化
    myList->pHeader.next=NULL;
    myList->m_size =0;

    //返回初始化链表
    return myList;
}

//链表插入
void insert_LList(LList* list, int pos, void *data){
    if(list==NULL)
    {
        return;
    }
    if(data==NULL)
    {
        return;
    }
    // 将地址还原成链表结构体
    LList * myList = list;
    //如果插入位置不准确
    if(pos<0||pos >myList->m_size)
    {
        //无效的位置变成尾插
        pos = myList->m_size;
    }
    //从头节点开始一步寻找到插入位置前的节点
    LinkNode* pCurrent = &(myList->pHeader);
    //开始寻找
    for (int i = 0; i < pos; ++i) {
        pCurrent = pCurrent->next;
    }
    //创立新节点
    LinkNode * new_Linknode = malloc(sizeof (LinkNode));
    //新节点赋值
    new_Linknode->data =data;
    new_Linknode->next =NULL;

    //更新链表关系
    new_Linknode->next=pCurrent->next;
    pCurrent->next = new_Linknode;
    //更新链表长度
    myList->m_size ++;
}

//遍历链表
void foreach_Linklist(LinkList * list, void (*my_foreach_print)(void *)){
    if(list == NULL){
        return;
    }
    //链表结构体转换
    LList *mylist = list;
    //找一个临时节点指向链表的头节点的下一个节点的地址
    LinkNode * tmp_node = mylist->pHeader.next;
    for (int i = 0; i <mylist->m_size ; ++i) {

        //不知道数据类型交给回调函数打印
        my_foreach_print(tmp_node->data);
        //找完数据继续往后移动
        tmp_node = tmp_node->next;
    }
}

//删除链表
//按着位置删除数据
void remove_Bypos_Linklist(LinkList* list, int pos){
    if(list == NULL)
    {
        return;
    }
    //还原链表结构
    LList *mylist = list;
    //取链表的头指针
    LinkNode *pCurrent = &(mylist->pHeader);
    //判断无效位置
    if(pos<0 ||pos >mylist->m_size-1)
    {
        return;
    }
    //进行循环查找出删除位置的前一个
    for (int i = 0; i <pos ; ++i) {
        pCurrent = pCurrent->next;
    }
    //记录待删除的节点
    LinkNode * del_node = pCurrent->next;
    //更改节点关系
    pCurrent->next = del_node->next;
    //释放节点
    free(del_node);
    del_node =NULL; //避免出现野指针
    //更新链表长度
    mylist->m_size -- ;


}
//按照值来进行删除数据
void remove_ByValue_Linklist(LinkList * list, void *data,int(*DataCompare)(void *,void *)){
    //判断数据有效性
    if(list == NULL)
    {
        return;
    }
    if(data == NULL)
    {
        return;
    }
    //还原链表
    LList* myList = list;

    //创建两个辅助指针
    LinkNode * prev_node =&(myList->pHeader);//用来存储删除元素前一个元素
    LinkNode *pCurrent_node = prev_node->next;//存储删除元素
    //循环查找
    for (int i = 0; i < myList->m_size; ++i) {
        //将两个指针 pCurrent_node->data 与 data 比较交给回调函数
        if(DataCompare(pCurrent_node->data,data))
        {
            //如果判断成立建立关系
            prev_node->next = pCurrent_node->next;
            //释放
            free(pCurrent_node);
            pCurrent_node = NULL;
            //更新链表长度
            myList->m_size --;
            break;
        }
        //辅助指针后移
        prev_node = pCurrent_node;
        pCurrent_node = pCurrent_node->next;
    }
}
//清空链表
void clear_LinkList(LinkList list){
    if (list==NULL)
    {
        return;
    }
    //还原链表
    LList *mylist = list;
    //先找到有数据的那个结点
    LinkNode * pCurrent = mylist->pHeader.next;
    //一层层递进查找
    for (int i = 0; i <mylist->m_size ; ++i) {
        //创建指针,保存下一个位置
        LinkNode * pNext = pCurrent->next;
        free(pCurrent);
        pCurrent = pNext;
    }
    //更新链表
    mylist->pHeader.next = NULL;
    mylist->m_size=0;
}

//返回链表长度
int size_LinkList(LinkList list){
    if (list ==NULL)
    {
        return NULL;
    }
    //还原链表
    LList * myList =list;
    return myList->m_size;

}
//销毁链表
void destroy_LinkList(LinkList * list){
    if (list== NULL)
    {
        return;
    }
    //首先清空
    clear_LinkList(list);
//    删除掉
    free(list);
    list ==NULL;
    printf("销毁链表成功\n");
}


typedef struct Person{
    char name[64];
    int age;
}Person;

//打印的回调函数
void Person_print(void *data){
    Person *P =data;
    printf("name:%s,age:%d\n",P->name,P->age);

}
//值比较的回调函数
int ComparePerson(void *data1,void *data2){
    Person * P1 = data1;
    Person *P2 =data2;
    return strcmp(P1->name,P2->name)==0 && P2->age == P1->age;
}
//测试
void test01(){
    //测试数据
    Person P1 ={"tom1",1};
    Person P2 ={"tom2",2};
    Person P3 ={"tom3",3};
    Person P4 ={"tom4",4};
    Person P5 ={"tom5",5};
    Person P6 ={"tom6",6};
    Person P7 ={"tom7",7};
    Person P8 ={"tom8",8};
    Person P9 ={"tom9",9};
    Person P10 ={"tom10",10};

    Person a[10]={P1,P2,P3,P4,P5,P6,P7,P8,P9,P10};

    //初始化链表
    LinkList mylist = init_LinkList();
    for (int i = 0; i <10; ++i) {
        insert_LList(mylist,0,(a+i));
    }
    foreach_Linklist(mylist,Person_print);
    //测试删除
//    remove_Bypos_Linklist(mylist,3);
    remove_ByValue_Linklist(mylist,&P1,ComparePerson);
    printf("删除后\n");
    foreach_Linklist(mylist,Person_print);
    //测试返回链表长度
    printf("链表长度:%d\n", size_LinkList(mylist));
    //测试清空
    clear_LinkList(mylist);
    printf("链表长度:%d\n", size_LinkList(mylist));
    //测试销毁
    destroy_LinkList(mylist);
}
//清空链表

int main(){
    test01();
    return 0;
}

测试

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

toptap8_nn

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值