单链表的增、删、查、改

单链表是一种链式存取的数据结构,用申请的地址存放每个节点,这些地址可能是连续,也可能是不连续的。每个结点的构成:元素(数据元素的映象,data) + 指针(指示后继元素存储位置,next)。通过指针将线性表的数据一个个串联起来,要想访问一个数据,就要知道前一个指针,想知道前一个就要知道前前一个,依次向前找。所以,一般访问是从头指针开始向后查找目标,方向是单向的。
头指针一般是固定的,而尾指针随着链表的增加或删除可能会改变,但是尾指针的后继节点一定是指向空,即NULL的。

下面便是单链表的增、删、查、改操作。

SingleLinkedList.h(头文件)

#pragma once

#include<stdlib.h>
#include<stdio.h>
#include<assert.h>
#include<Windows.h>

typedef int DataType;

typedef struct SListNode
{
    struct SListNode* _next;
    DataType _data;
}SListNode;

SListNode* pStructInit();//结构体指针初始
SListNode* BuySListNode(DataType x);//创建节点
void SListPrint(SListNode* pHead);//打印
void SListDestory(SListNode** ppHead);//销毁

void SListPushBack(SListNode** ppHead, DataType x);//尾插
void SListPopBack(SListNode** ppHead);//尾删
void SListPushFront(SListNode** ppHead, DataType x);//头插
void SListPopFront(SListNode** ppHead);//头删
SListNode* SListFind(SListNode* pHead, DataType x);//查找
void SListInsert(SListNode** ppHead, SListNode* pos, DataType x);//pos前插入
void SListErase(SListNode** ppHead, SListNode* pos);//pos位置删除
void SListAt(SListNode** ppHead, SListNode *pos, DataType x);//替换

SingleLinkedList.c(功能函数的实现)

#include"SingleLinkedList.h"


SListNode* pStructInit()//结构体指针初始
{
    SListNode* pStruct = (SListNode*)malloc(sizeof(SListNode));

    if (pStruct == NULL)
    {
        perror("Initialize fail");
        exit(1);
    }

    pStruct->_next = NULL;

    return pStruct;
}

SListNode* BuySListNode(DataType x)//创建节点
{
    SListNode* tmp = (SListNode*)malloc(sizeof(SListNode));
    if (tmp == NULL)
    {
        perror("Malloc fail");
        exit(1);
    }

    tmp->_data = x;
    tmp->_next = NULL;

    return tmp;
}

void SListPrint(SListNode* pHead)//打印单链表
{
    assert(pHead);

    SListNode* pnode = pHead->_next;
    while (pnode)
    {
        printf("%d ", pnode->_data);
        pnode = pnode->_next;
    }
    printf("\n");
}

void SListDestory(SListNode** ppHead)//销毁
{
    SListNode* tmp = NULL;

    while (*ppHead)
    {
        tmp = (*ppHead)->_next;
        free(*ppHead);
        (*ppHead) = tmp; 
    }

}

void SListPushBack(SListNode** ppHead, DataType x)//尾插
{
    assert(ppHead);

    SListNode* tmp = *ppHead;

    if (ppHead == NULL)
    {
        *ppHead = BuySListNode(x);
        return;
    }

    while (tmp->_next)
    {
        tmp = tmp->_next;
    }

    tmp->_next = BuySListNode(x);
}

void SListPopBack(SListNode** ppHead)//尾删
{
    assert(ppHead);
    SListNode* tmp = *ppHead;

    if ((tmp->_next)==NULL)//无节点
    {
        return;
    }
    else//有节点
    {
        while (tmp->_next->_next)
        {
            tmp = tmp->_next;
        }
        //将最后一个元素销毁置空
        free(tmp->_next);
        tmp->_next = NULL;
    }

}

void SListPushFront(SListNode** ppHead, DataType x)//头插
{
    assert(ppHead);

    if ((*ppHead) == NULL)
    {
        *ppHead = BuySListNode(x);
        (*ppHead)->_next = NULL;
    }
    else
    {
        SListNode *tmp = BuySListNode(x);
        tmp->_next = (*ppHead)->_next;
        (*ppHead)->_next = tmp;
    }

}

void SListPopFront(SListNode** ppHead)//头删
{
    assert(ppHead);

    if ((*ppHead)->_next == NULL)
    {
        return;
    }
    else
    {
        SListNode *tmp = (*ppHead)->_next;
        (*ppHead)->_next = tmp->_next;
        free(tmp);
        tmp = NULL;
    }

}


SListNode* SListFind(SListNode* pHead, DataType x)//查找
{
    SListNode* tmp = pHead;

    while (tmp)
    {
        if (tmp->_data == x)
            return tmp; 
        else
            tmp = tmp->_next;
    }

    return NULL;
}

void SListInsert(SListNode** ppHead, SListNode* pos, DataType x)//pos前插入
{
    assert(ppHead && pos);

    SListNode *p = (*ppHead);
    SListNode *q = BuySListNode(x);

    while (p->_next != pos)
    {
        p = p->_next;
    }
    p->_next = q;
    q->_next = pos;
}

void SListErase(SListNode** ppHead, SListNode* pos)//pos位置删除
{
    assert(ppHead && pos);

    SListNode* tmp = *ppHead;
    while (tmp->_next != pos)
    {
        tmp = tmp->_next;
    }
    tmp->_next = pos->_next;

    free(pos);
    pos = NULL;
}

void SListAt(SListNode** ppHead, SListNode *pos, DataType x)//替换
{
    assert(ppHead && pos);

    SListNode *tmp = *ppHead;

    while (tmp->_next != pos)
    {
        tmp = tmp->_next;
    }
    tmp->_next->_data = x;
}

Test.c(测试)

#include"SingleLinkedList.h"

void TestPushBack(SListNode *list)//尾插
{


    SListPushBack(&list, 1);
    SListPrint(list);

    SListPushBack(&list, 2);
    SListPrint(list);

    SListPushBack(&list, 3);
    SListPrint(list);

    SListDestory(&list);
}

void TestPopBack(SListNode *list)//尾删
{
    SListNode*tmp = list;
    //先插入3个数字
    SListPushBack(&list, 1);
    SListPushBack(&list, 2);
    SListPushBack(&list, 3);
    SListPrint(list);

    list = tmp;
    //开始尾删
    SListPopBack(&tmp);
    SListPrint(tmp);

    SListPopBack(&tmp);
    SListPrint(tmp);

    SListPopBack(&tmp);
    SListPrint(tmp);


    SListDestory(&list);
}

void TestPushFront(SListNode *list)//头插
{


    SListPushFront(&list, 1);
    SListPrint(list);

    SListPushFront(&list, 2);
    SListPrint(list);

    SListPushFront(&list, 3);
    SListPrint(list);

    SListDestory(&list);
}

void TestPopFront(SListNode *list)//头删
{
    SListPushFront(&list, 1);
    SListPushFront(&list, 2);
    SListPushFront(&list, 3);
    SListPrint(list);

    SListPopFront(&list);
    SListPrint(list);//删掉3剩下2和1
    SListPopFront(&list);
    SListPrint(list);//剩下1
    SListPopFront(&list);
    SListPrint(list);//空
    SListPopFront(&list);
    SListPrint(list);//空

    SListDestory(&list);
}


void TestInsert(SListNode *list)//pos前插入
{

    SListNode*pos = NULL;

    //尾插
    SListPushBack(&list, 7);
    SListPushBack(&list, 8);
    SListPushBack(&list, 9);
    //头插
    SListPushFront(&list, 3);
    SListPushFront(&list, 2);
    SListPushFront(&list, 1);

    SListPrint(list);

    pos = SListFind(list,7);
    SListInsert(&list,pos, 6);
    SListPrint(list);

    pos = SListFind(list, 6);
    SListInsert(&list, pos, 5);
    SListPrint(list);

    pos = SListFind(list, 5);
    SListInsert(&list, pos, 4);
    SListPrint(list);

    /*pos = SListFind(list, 20);//因为链表没有20,pos为空指针,在SListInsert函数的断言会报错
    SListInsert(&list, pos, 10);
    SListPrint(list);*/

    SListDestory(&list);
}


void TestErase(SListNode *list)//pos位置删除
{
    SListNode*pos = NULL;

    //尾插
    SListPushBack(&list, 7);
    SListPushBack(&list, 8);
    SListPushBack(&list, 9);
    //头插
    SListPushFront(&list, 3);
    SListPushFront(&list, 2);
    SListPushFront(&list, 1);

    SListPrint(list);

    pos = SListFind(list,1);
    SListErase(&list, pos);
    SListPrint(list);

    pos = SListFind(list, 2);
    SListErase(&list, pos);
    SListPrint(list);

    pos = SListFind(list, 3);
    SListErase(&list, pos);
    SListPrint(list);

    pos = SListFind(list, 7);
    SListErase(&list, pos);
    SListPrint(list);

    pos = SListFind(list, 8);
    SListErase(&list, pos);
    SListPrint(list);

    pos = SListFind(list, 9);
    SListErase(&list, pos);
    SListPrint(list);

    SListDestory(&list);
}


void TestFind(SListNode *list)//查找
{
    SListPushBack(&list, 1);
    SListPushBack(&list, 2);
    SListPushBack(&list, 3);

    //数据存在,打印该数据;查找不存在数据会发生异常
    printf("%d\n", SListFind(list, 3)->_data);
    printf("%d\n", SListFind(list, 2)->_data);
    printf("%d\n", SListFind(list, 1)->_data);
    //printf("%d\n", SListFind(list, 0)->_data);//链表内没有数据data存放0,因此返回NULL,而用空指针访问data数据会异常

    SListDestory(&list);
}



void TestAt(SListNode *list)//替换
{
    SListNode*pos = NULL;

    //头插
    SListPushFront(&list, 3);
    SListPushFront(&list, 2);
    SListPushFront(&list, 0);

    //尾插
    SListPushBack(&list, 4);
    SListPushBack(&list, 8);
    SListPushBack(&list, 9);

    SListPrint(list);

    pos = SListFind(list, 0);
    SListAt(&list, pos, 1);
    SListPrint(list);

    pos = SListFind(list, 8);
    SListAt(&list, pos, 5);
    SListPrint(list);

    pos = SListFind(list, 9);
    SListAt(&list, pos, 6);
    SListPrint(list);

    SListDestory(&list);
}


int main()//想要测试哪个,则放开前面的双斜线
{
    SListNode *list = pStructInit();

    //TestPushBack(list);//尾插
    //TestPopBack(list);//尾删
    //TestPushFront(list);//头插
    //TestPopFront(list);//头删
    //TestInsert(list);//pos前插入
    //TestErase(list);//pos位置删除
    //TestFind(list);//查找
    //TestAt(list);//替换

    system("pause");
    return 0;
}

最后,那里要是写错了,或者不懂的地方,欢迎评论或者私信给我,谢谢。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值