Tear a linked list by hand (add, delete, check, modify, insert)

SList.h

#pragma once
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<assert.h>
typedef int SLTDateType;
typedef struct SListNode
{
    SLTDateType data;
    struct SListNode* next;
}SListNode;

// 动态申请一个节点
SListNode* BuySListNode(SLTDateType x);
// 单链表打印
void SListPrint(SListNode* plist);
// 单链表尾插
void SListPushBack(SListNode** pplist, SLTDateType x);
// 单链表的头插
void SListPushFront(SListNode** pplist, SLTDateType x);
// 单链表的尾删
void SListPopBack(SListNode** pplist);
// 单链表头删
void SListPopFront(SListNode** pplist);
// 单链表查找
SListNode* SListFind(SListNode* plist, SLTDateType x);
// 单链表在pos位置之后插入x
void SListInsertAfter(SListNode* pos, SLTDateType x);
// 单链表删除pos位置之后的值
void SListEraseAfter(SListNode* pos);
// 单链表的销毁
void SListDestroy(SListNode* plist);

SList.c

#include"SL.h"
// 动态申请一个节点
SListNode* BuySListNode(SLTDateType x) {
    SListNode* newnode = malloc(sizeof(SListNode));
    if (newnode == NULL)
    {
        perror("malloc::faill");
    }
    newnode->data=x;
    newnode->next = NULL;
    return newnode;
}
// 单链表打印
void SListPrint(SListNode* plist) {
    
    assert(plist);
    while(plist)
    {

        printf("%d->", plist->data);
        plist = plist->next;
    }
    printf("null\n");
}

// 单链表的头插
void SListPushFront(SListNode** pplist, SLTDateType x)
{
    if (*pplist == NULL)
    {
        SListNode* newnode = BuySListNode(x);
        *pplist = newnode;

    }
    else
    {
        SListNode *newnode = BuySListNode(x);
        newnode->next=*pplist;
        *pplist = newnode;
    }
}
// 单链表头删
void SListPopFront(SListNode** pplist)
{
    assert(*pplist);
    if ((*pplist)->next == NULL)//对结构体指针的地址传值时访问该结构体的成员先得对结构体地址解引用
    {
        SListNode* cur = *pplist;
        //直接free(*pplist),会使得pplist被置为随机值
        free(cur);
        *pplist = NULL;
    }
    else
    {
        SListNode *cur = *pplist;
        *pplist = (*pplist)->next;//左右两边的星号都不要漏。
        free(cur);
    }
}

// 单链表尾插
void SListPushBack(SListNode** pplist, SLTDateType x)
{
    if (*pplist == NULL)
    {
        SListNode* newnode = BuySListNode(x);
        *pplist = newnode;
    }
    else
    {
        SListNode* tail = *pplist;
        SListNode* newnode = BuySListNode(x);
        while (tail->next)
        {
            tail = tail->next;
        }
        tail->next = newnode;
    }
}
// 单链表的尾删
void SListPopBack(SListNode** pplist) {
    assert(*pplist);
    SListNode* tail=*pplist,*prev=*pplist;
    if (tail->next == NULL)
    {
        free(tail);
        *pplist = NULL;
    }
    else 
    {
        while (tail->next)
        {
            prev = tail;
            tail = tail->next;
        }
        prev->next = NULL;
        free(tail);
        tail = NULL;
    }
}

// 单链表查找
SListNode* SListFind(SListNode* plist, SLTDateType x) {
        assert(plist);
        SListNode* cur = plist;
        while (cur)
        {
            if (cur->data == x)
            {
                return cur;
            }
            cur = cur->next;
        }
        return NULL;
}
// 单链表在pos位置之后插入x
// 分析思考为什么不在pos位置之前插入?因为找pos之前的位置需要O(n)的时间复杂度
void SListInsertAfter(SListNode* pos, SLTDateType x) {
    assert(pos);
    SListNode* newnode = BuySListNode(x);
    newnode->next = pos->next;
    pos->next = newnode;
}
// 单链表删除pos位置之后的值
void SListEraseAfter(SListNode* pos) {
    assert(pos&&pos->next);
    SListNode* next = pos->next;
    pos->next = next->next;
    free(next);
    next = NULL;
}
// 单链表的销毁
void SListDestroy(SListNode* plist) {
    while (plist)
    {
        SListNode* next = plist;
        free(plist);
        plist = next;
    }
}

test.c

#include "SL.h"

void test()
{
    SListNode* plist = NULL;
    SListPushFront(&plist, 1);
    SListPushFront(&plist, 2);
    SListPushFront(&plist, 4);
    SListPushFront(&plist, 7);
    SListPrint(plist);
}
int main()
{
    test();
    //SListNode* plist = NULL;
    //SListPushFront(&plist, 1);
    //SListPushFront(&plist, 2);
    //SListPushFront(&plist, 4);
    //SListPushFront(&plist, 7);
    //SListPrint(plist);
    //SListPopFront(&plist);
    //SListPopFront(&plist);
    //SListPopFront(&plist);
    //SListPopFront(&plist);
    SListPrint(&plist);
    //SListPushFront(&plist, 1);
    //SListPushFront(&plist, 2);
    //SListPushBack(&plist, -1);
    //SListPushBack(&plist, -2);
    //SListPushBack(&plist, -7);
    //SListPrint(plist);
    //SListPopBack(&plist);
    //SListPopBack(&plist);
    //SListPopBack(&plist);
    //SListPopBack(&plist);
    //SListPopBack(&plist);
    SListPrint(plist);
    //SListPushFront(&plist, 1);
    //SListPushFront(&plist, 1);
    //SListPushFront(&plist, 2);
    //SListPushBack(&plist, -4);
    //SListPushBack(&plist, -2);
    //SListPushBack(&plist, -7);
    //SListPrint(plist);
    //SListNode* ret = SListFind(plist, 2);
    //SListInsertAfter(ret, 3);
    //SListPrint(plist);
    //SListEraseAfter(ret);
    //SListPrint(plist);

    return 0;
}

For practice reference, with some own insights

Guess you like

Origin blog.csdn.net/m0_74234485/article/details/129219940