1-单向链表

笔记

链表是一种线性的链式存储结构,可以不用事先确定节点的个数,插入删除节点需要的操作量较少。但只能通过遍历链表来查找想找的节点。

每个节点用一个结构体表示,节点结构体内分成两部分(数据域、指针域)。指针域用来指向下一个节点、数据域存放数据。

单向链表需要维护一个头节点,之后所有的操作都需要通过头节点。定义一个结构体来管理链表,管理结构体包含一个头节点和记录链表长度的变量。头节点里不存放数据,只用来指向下一节点。最好手动维护链表长度(插入和删除时手动计数),这样不用每次遍历到next==NULL来确认链表结束。

单向链表的结构示意图

要实现的功能

初始化、遍历、插入、按位置删除、按值删除、清空链表、释放链表

代码

myLinkList.c

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

void SayHello(){
    printf("Hello\n");
}

ManageLinkListType* init_ll(){
    ManageLinkListType* pmll = malloc(sizeof( ManageLinkListType));
    pmll->head.data = NULL;
    pmll->head.next = NULL;
    pmll->m_szie = 0;
    return pmll;
}

//按位置插入数据,这里的data要保证生存周期正常,链表并不维护data的释放
void insert_ll(ManageLinkListType* pmll,int pos, void * data){
    if(NULL == pmll){
        return;
    }

    if(pos < 0 || pos > pmll->m_szie){
        pos = pmll->m_szie;
    }

    //创建临时节点,赋值为头节点
    struct lNodeStruct * currNode = &(pmll->head);
    //将临时节点移动到要插入位置
    for(int i=0; i<pos; i++){
        currNode = currNode->next;
    }

    struct lNodeStruct * newNode = malloc(sizeof(struct lNodeStruct));
    newNode->data = data;

    //插入临时节点所在的位置
    newNode->next = currNode->next;
    currNode->next = newNode;

    pmll->m_szie++;
}

//遍历函数
void foreach_ll(ManageLinkListType* pmll, void(*myForeach)(void*)){
    if(NULL == pmll || NULL == myForeach){
        return;
    }

    struct lNodeStruct * currNode = &(pmll->head);
    for(int i=0; i<pmll->m_szie; i++){
        currNode = currNode->next;
        myForeach(currNode->data);
    }
}

//删除,通过位置
void remove_ll(ManageLinkListType* pmll, int pos){
    if(NULL == pmll || pos>=pmll->m_szie){
        return;
    }

    struct lNodeStruct* currNode = &(pmll->head);
    struct lNodeStruct* delNode = NULL;

    //找到前驱节点
    for(int i=0; i<pos; i++){
        currNode = currNode->next;  
    }

    //要删除的节点
    delNode = currNode->next;

    //将前驱节点的next指向本节点的next(即后驱节点)
    currNode->next = delNode->next;

    //释放要删除的节点
    free(delNode);
    delNode = NULL;

    pmll->m_szie--;
}

//通过值删除
void removeByVal_ll(ManageLinkListType* pmll,void* data, int (*myCompare)(void*,void*)){
    if(NULL==pmll || NULL==data){
        return;
    }

    struct lNodeStruct* currNode = &(pmll->head);
    struct lNodeStruct* perNode = &(pmll->head);
    for(int i=0;i<pmll->m_szie;i++){
        perNode = currNode;
        currNode = currNode->next;

        if(myCompare(currNode->data,data) ){
            perNode->next = currNode->next;
            free(currNode);
            currNode = NULL;
            pmll->m_szie--;
            break;
        }
    }
}

//清除链表
void clear_ll(ManageLinkListType* pmll){
    if(NULL==pmll || pmll->m_szie==0){
        return;
    }

    struct lNodeStruct* currNode = pmll->head.next;
    struct lNodeStruct* nextNode = NULL;
    for(int i=0;i<pmll->m_szie;i++){

        nextNode = currNode->next;

        free(currNode);
        currNode = NULL;

        currNode = nextNode;
    }

    pmll->m_szie = 0;
}

myLinkList.h

#ifndef __MY_LINK_LIST_H
#define __MY_LINK_LIST_H

struct lNodeStruct
{
    void * data;
    struct lNodeStruct * next;
};

typedef struct 
{
    struct lNodeStruct head;
    int m_szie;
}ManageLinkListType;

void SayHello(void);

ManageLinkListType* init_ll(void);
void insert_ll(ManageLinkListType* pmll,int pos, void * data);
void foreach_ll(ManageLinkListType* pmll, void(*myForeach)(void*));
void remove_ll(ManageLinkListType* pmll, int pos);
void removeByVal_ll(ManageLinkListType* pmll,void* data, int (*myCompare)(void*,void*));
void clear_ll(ManageLinkListType* pmll);

#endif

start0.c

#include "myLinkList.h"
#include<stdio.h>
#include<string.h>

struct Persion{
    int m_age;
    char m_name[64];
};

void myPrint(void * data){
    struct Persion *p = data;
    printf("age=%d\tname=%s\n",p->m_age,p->m_name);
}

void test0(ManageLinkListType* pmll){
    struct Persion p0={100,"hhhh"};
    insert_ll(pmll,0,&p0);
}

int myCompare(void* data1,void* data2){
    struct Persion *p1 = data1;
    struct Persion *p2 = data2;

    if(p1->m_age == p2->m_age){
        if(strcmp(p1->m_name,p2->m_name) == 0){
            return 1;
        }
    }
    return 0;
}

int main(){
    ManageLinkListType* pmll = init_ll();
    //test0(pmll);

    struct Persion p1={10,"aaaa"};
    struct Persion p2={11,"bbbb"};
    struct Persion p0={100,"hhhh"};
    

    insert_ll(pmll,0,&p1);
    insert_ll(pmll,0,&p2);
    insert_ll(pmll,0,&p0);
    

    foreach_ll(pmll,myPrint);

    printf("------------------------\n");
    //remove_ll(pmll,0);
    struct Persion p4={10,"aaaa"};
    removeByVal_ll(pmll,&p4,myCompare);

    foreach_ll(pmll,myPrint);

    printf("----------------------\n");
    clear_ll(pmll);
    foreach_ll(pmll,myPrint);

    free(pmll);

    return 0;
}
posted @ 2022-01-25 20:48  WuYunTaXue  阅读(71)  评论(0编辑  收藏  举报