单链表

本文详细介绍了单链表的基本概念及其实现方法,包括初始化、插入、删除等核心功能,并通过示例代码展示了如何进行尾插、尾删、头插、头删等操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

链表

链表:一种链式存储的线性表,用一组地址任一的存储单元存放线性表的数据元素,称存储单元为一各节点

单链表

1 . 结构

typedef int DataType;

typedef struct SListNode
{
    DataType _data;           // 当前节点中所保存的元素
    struct SListNode* _pNext; // 指向下一个结点的指针 
}Node, *PNode;

2 . 功能函数

包含链表的建立,初始化,头删,尾删,头插,尾插,任意位置的插入和删除,链表的输出,链表的判空等

// 初始化单链表 
void SListInit(PNode* ppHead);

// 尾插 
void SListPushBack(PNode* ppHead, DataType data);

// 尾删 
void SListPopBack(PNode* ppHead);

// 头插 
void SListPushFront(PNode* ppHead, DataType data);

// 头删 
void SListPopFront(PNode* ppHead);

// 在链表中查找元素data,返回该结点在链表中的位置 
PNode Find(PNode pHead, DataType data);
// data插入在pos之前 
void SListInsert(PNode* ppHead, PNode pos, DataType data);

// 删除链表中pos位置的结点 
void SListErase(PNode* ppHead, PNode pos);

// 获取链表中结点的个数 
size_t Size(PNode pHead);

// 判断链表是否为空,若为空,返回true,否则返回false 
size_t Empty(PNode pHead);

// 销毁单链表 
void SListDestroy(PNode* pHead);

// 创建结点 
PNode BuySListNode(DataType data);

// 打印单链表 
void SListPrint(PNode pHead);

各部分功能的实现

  • 初始化单链表
void SListInit(PNode* ppHead)
{
    *ppHead = NULL;
}
  • 尾插
// 尾插 
void SListPushBack(PNode* ppHead, DataType data)
{
    assert(ppHead);
    PNode newP = BuySListNode(data);
    PNode P = *ppHead;
    if (*ppHead == NULL)
    {
        *ppHead = newP;
    }
    else 
    {
        while (P->_pNext != NULL)
        {
            P = P->_pNext;
        }
        P->_pNext = newP;
    }
}
  • 尾删
// 尾删 
void SListPopBack(PNode* ppHead)
{
    assert(ppHead);
    PNode Pre = NULL;
    PNode Del = NULL;
    if (*ppHead && (*ppHead) -> _pNext == NULL )
    {
        free((*ppHead));
        *ppHead = NULL;
    }
    else if(*ppHead)
    {
        Del = *ppHead;
        while (Del->_pNext != NULL)
        {
            Pre = Del;
            Del = Del->_pNext;
        }
        Pre->_pNext = NULL;
        free(Del);
    }
}
  • 头插
// 头插 
void SListPushFront(PNode* ppHead, DataType data)
{
    assert(ppHead);
    PNode newP = BuySListNode(data);
    newP->_pNext = *ppHead;
    *ppHead = newP;
}
  • 头删
// 头删 
void SListPopFront(PNode* ppHead)
{
    assert(ppHead);

    PNode Del = NULL;
    if((*ppHead) != NULL)
    {
        Del = *ppHead;
        *ppHead = (*ppHead)->_pNext;
        free(Del);
    }

}
  • 在链表中查找元素data,返回该结点在链表中的位置
// 在链表中查找元素data,返回该结点在链表中的位置 
PNode Find(PNode pHead, DataType data)
{
    while (pHead != NULL)
    {
        if (pHead->_data == data)
        {
            return pHead;
        }
        pHead = pHead->_pNext;
    }
    return NULL;
}
  • data插入在pos之前
// data插入在pos之前 
void SListInsert(PNode* ppHead, PNode pos, DataType data)
{
    assert(ppHead);
    assert(pos);

    PNode Pnew = BuySListNode(data);
    PNode per = NULL;

    if (pos == *ppHead)
    {
        Pnew->_pNext = *ppHead;
        *ppHead = Pnew;
    }
    else
    {
        per = *ppHead;
        while (pos && per  && per->_pNext != pos)
        {
            per = per->_pNext;
        }
        if (per->_pNext == pos)
        {
            Pnew->_pNext = pos;
            per->_pNext = Pnew;
        }
    }
}
  • 删除链表中pos位置的结点
// 删除链表中pos位置的结点 
void SListErase(PNode* ppHead, PNode pos)
{
    assert(ppHead);
    PNode pre = *ppHead;

    if(pos == NULL || *ppHead == NULL)
    {
        return 0;
    }
    else if (pos == *ppHead)
    {
        *ppHead = pos->_pNext;
        free(pos);
    }
    else
    {
        while (pre && pre->_pNext != pos)
        {
            pre = pre->_pNext;
        }
        if (pre)
        {
            pre->_pNext = pos->_pNext;
            free(pos);
        }
    }
}
  • 获取链表中结点的个数
// 获取链表中结点的个数 
size_t Size(PNode pHead)
{
    size_t num = 0;
    while (NULL != pHead)
    {
        num++;
        pHead = pHead->_pNext;
    }
    return num;
}
  • 判断链表是否为空,若为空,返回true,否则返回false
// 判断链表是否为空,若为空,返回true,否则返回false 
size_t Empty(PNode pHead)
{
    if (NULL == pHead)
    {
        return 1;
    }
    else return 0;
}
  • 销毁单链表
// 销毁单链表 
void SListDestroy(PNode* pHead)
{
    assert(pHead);

    if ((*pHead) != NULL)
    {
        SListDestroy(&((*pHead)->_pNext));
    }
    if((*pHead) != NULL)
    {
        free((*pHead));
    }
}
  • 创建结点
// 创建结点 
PNode BuySListNode(DataType data)
{
    PNode newP =  NULL;
    newP = (PNode)malloc(sizeof(Node));
    if (newP == NULL)
    {
        printf("error\n");
        return 0;
    }
    newP->_data = data;
    newP->_pNext = NULL;
    return newP;
}
  • 打印单链表
// 打印单链表 
void SListPrint(PNode pHead)
{
    while (pHead != NULL)
    {
        printf("%d ", pHead->_data);
        pHead=pHead->_pNext;
    } 
    printf("\n");
}

代码


代码实现(Visual studio 2017)

  • test.c 文件

//主函数
int main()
{
    //尾插测试
    PushBack_test();
    //尾删测试
    PopBack_test();
    //头插测试
    PushFront_test();
    //头删测试
    PophFront_test();
    //data插入在pos之前测试
    SListInsert_test();
    // 删除链表中pos位置的结点 
    SListErase_test();
    // 链表中结点个数测试
    Size_test();
    // 销毁单链表测试 
    SListDestroy_test();

    system("pause");
    return 0;
}
  • SListNode.h 文件
#pragma once

#ifndef _SLISTNODE_H_
#define _SLISTNODE_H_



typedef int DataType;

typedef struct SListNode
{
    DataType _data;
    struct SListNode* _pNext; // 指向下一个结点的指针 
}Node, *PNode;


// 初始化单链表 
void SListInit(PNode* ppHead);

// 尾插 
void SListPushBack(PNode* ppHead, DataType data);

// 尾删 
void SListPopBack(PNode* ppHead);

// 头插 
void SListPushFront(PNode* ppHead, DataType data);

// 头删 
void SListPopFront(PNode* ppHead);

// 在链表中查找元素data,返回该结点在链表中的位置 
PNode Find(PNode pHead, DataType data);
// data插入在pos之前 
void SListInsert(PNode* ppHead, PNode pos, DataType data);

// 删除链表中pos位置的结点 
void SListErase(PNode* ppHead, PNode pos);

// 获取链表中结点的个数 
size_t Size(PNode pHead);

// 判断链表是否为空,若为空,返回true,否则返回false 
size_t Empty(PNode pHead);

// 销毁单链表 
void SListDestroy(PNode* pHead);

// 创建结点 
PNode BuySListNode(DataType data);

// 打印单链表 
void SListPrint(PNode pHead);

#endif
  • SListNode.c 文件
#include <stdio.h>
#include <windows.h>
#include <assert.h>
#include <stdlib.h>
#include "SListNode.h"

// 初始化单链表 
void SListInit(PNode* ppHead)
{
    *ppHead = NULL;
}

// 尾插 
void SListPushBack(PNode* ppHead, DataType data)
{
    assert(ppHead);
    PNode newP = BuySListNode(data);
    PNode P = *ppHead;
    if (*ppHead == NULL)
    {
        *ppHead = newP;
    }
    else 
    {
        while (P->_pNext != NULL)
        {
            P = P->_pNext;
        }
        P->_pNext = newP;
    }
}

// 尾删 
void SListPopBack(PNode* ppHead)
{
    assert(ppHead);
    PNode Pre = NULL;
    PNode Del = NULL;
    if (*ppHead && (*ppHead) -> _pNext == NULL )
    {
        free((*ppHead));
        *ppHead = NULL;
    }
    else if(*ppHead)
    {
        Del = *ppHead;
        while (Del->_pNext != NULL)
        {
            Pre = Del;
            Del = Del->_pNext;
        }
        Pre->_pNext = NULL;
        free(Del);
    }
}

// 头插 
void SListPushFront(PNode* ppHead, DataType data)
{
    assert(ppHead);
    PNode newP = BuySListNode(data);
    newP->_pNext = *ppHead;
    *ppHead = newP;
}

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

    PNode Del = NULL;
    if((*ppHead) != NULL)
    {
        Del = *ppHead;
        *ppHead = (*ppHead)->_pNext;
        free(Del);
    }

}

// 在链表中查找元素data,返回该结点在链表中的位置 
PNode Find(PNode pHead, DataType data)
{
    while (pHead != NULL)
    {
        if (pHead->_data == data)
        {
            return pHead;
        }
        pHead = pHead->_pNext;
    }
    return NULL;
}

// data插入在pos之前 
void SListInsert(PNode* ppHead, PNode pos, DataType data)
{
    assert(ppHead);
    assert(pos);

    PNode Pnew = BuySListNode(data);
    PNode per = NULL;

    if (pos == *ppHead)
    {
        Pnew->_pNext = *ppHead;
        *ppHead = Pnew;
    }
    else
    {
        per = *ppHead;
        while (pos && per  && per->_pNext != pos)
        {
            per = per->_pNext;
        }
        if (per->_pNext == pos)
        {
            Pnew->_pNext = pos;
            per->_pNext = Pnew;
        }
    }
}

// 删除链表中pos位置的结点 
void SListErase(PNode* ppHead, PNode pos)
{
    assert(ppHead);
    PNode pre = *ppHead;

    if(pos == NULL || *ppHead == NULL)
    {
        return 0;
    }
    else if (pos == *ppHead)
    {
        *ppHead = pos->_pNext;
        free(pos);
    }
    else
    {
        while (pre && pre->_pNext != pos)
        {
            pre = pre->_pNext;
        }
        if (pre)
        {
            pre->_pNext = pos->_pNext;
            free(pos);
        }
    }
}


// 获取链表中结点的个数 
size_t Size(PNode pHead)
{
    size_t num = 0;
    while (NULL != pHead)
    {
        num++;
        pHead = pHead->_pNext;
    }
    return num;
}

// 判断链表是否为空,若为空,返回true,否则返回false 
size_t Empty(PNode pHead)
{
    if (NULL == pHead)
    {
        return 1;
    }
    else return 0;
}

// 销毁单链表 
void SListDestroy(PNode* pHead)
{
    assert(pHead);

    if ((*pHead) != NULL)
    {
        SListDestroy(&((*pHead)->_pNext));
    }
    if((*pHead) != NULL)
    {
        free((*pHead));
    }
}

// 创建结点 
PNode BuySListNode(DataType data)
{
    PNode newP =  NULL;
    newP = (PNode)malloc(sizeof(Node));
    if (newP == NULL)
    {
        printf("error\n");
        return 0;
    }
    newP->_data = data;
    newP->_pNext = NULL;
    return newP;
}

// 打印单链表 
void SListPrint(PNode pHead)
{
    while (pHead != NULL)
    {
        printf("%d ", pHead->_data);
        pHead=pHead->_pNext;
    } 
    printf("\n");
}

//尾插测试
void PushBack_test()
{
    PNode pHead;
    SListInit(&pHead);

    printf("尾插测试\n");
    SListPushBack(&pHead, 0);
    SListPrint(pHead);
    SListPushBack(&pHead, 1);
    SListPrint(pHead);
    SListPushBack(&pHead, 2);
    SListPrint(pHead);
    SListPushBack(&pHead, 3);
    SListPrint(pHead);
    SListPushBack(&pHead, 4);
    SListPrint(pHead);
}
//尾删测试
void PopBack_test()
{
    PNode pHead;
    SListInit(&pHead);

    printf("尾删测试\n");
    SListPushBack(&pHead, 0);
    SListPushBack(&pHead, 1);
    SListPushBack(&pHead, 2);
    SListPushBack(&pHead, 3);
    SListPushBack(&pHead, 4);
    SListPrint(pHead);

    SListPopBack(&pHead);
    SListPrint(pHead);
    SListPopBack(&pHead);
    SListPrint(pHead);
    SListPopBack(&pHead);
    SListPrint(pHead);
    SListPopBack(&pHead);
    SListPrint(pHead);
    SListPopBack(&pHead);
    SListPrint(pHead);
    SListPopBack(&pHead);
    SListPrint(pHead);
    SListPopBack(&pHead);
    SListPrint(pHead);
}

//头插测试
void PushFront_test()
{
    PNode pHead;
    SListInit(&pHead);
    printf("头插测试\n");

    SListPushFront(&pHead, 1);
    SListPrint(pHead);
    SListPushFront(&pHead, 2);
    SListPrint(pHead);
    SListPushFront(&pHead, 3);
    SListPrint(pHead);
    SListPushFront(&pHead, 4);
    SListPrint(pHead);
    SListPushFront(&pHead, 5);
    SListPrint(pHead);
    SListPushFront(&pHead, 6);
    SListPrint(pHead);
}

//头删测试
void PophFront_test()
{
    PNode pHead;
    SListInit(&pHead);
    printf("头删测试\n");

    SListPushFront(&pHead, 1);
    SListPushFront(&pHead, 2);
    SListPushFront(&pHead, 3);
    SListPushFront(&pHead, 4);
    SListPushFront(&pHead, 5);
    SListPushFront(&pHead, 6);
    SListPrint(pHead);

    SListPopFront(&pHead);
    SListPrint(pHead);
    SListPopFront(&pHead);
    SListPrint(pHead);
    SListPopFront(&pHead);
    SListPrint(pHead);
    SListPopFront(&pHead);
    SListPrint(pHead);
    SListPopFront(&pHead);
    SListPrint(pHead);
    SListPopFront(&pHead);
    SListPrint(pHead);
    SListPopFront(&pHead);
    SListPrint(pHead);
    SListPopFront(&pHead);
    SListPrint(pHead);
}

//data插入在pos之前测试
void SListInsert_test()
{
    PNode pHead;
    SListInit(&pHead);
    printf("插入测试\n");

    SListPushBack(&pHead, 0);
    SListPushBack(&pHead, 1);
    SListPushBack(&pHead, 2);
    SListPushBack(&pHead, 3);
    SListPushBack(&pHead, 4);
    SListPrint(pHead);

    SListInsert(&pHead, Find(pHead,0), 9);
    SListPrint(pHead);
    SListInsert(&pHead, Find(pHead, 2), 9);
    SListPrint(pHead);
    SListInsert(&pHead, Find(pHead, 4), 9);
    SListPrint(pHead);
}

// 删除链表中pos位置的结点 
void SListErase_test()
{
    PNode pHead;
    SListInit(&pHead);
    printf("删除测试\n");

    SListPushBack(&pHead, 0);
    SListPushBack(&pHead, 1);
    SListPushBack(&pHead, 2);
    SListPushBack(&pHead, 3);
    SListPushBack(&pHead, 4);
    SListPrint(pHead);

    SListErase(&pHead, Find(pHead, 0));
    SListPrint(pHead);
    SListErase(&pHead, Find(pHead, 2));
    SListPrint(pHead);
    SListErase(&pHead, Find(pHead, 4));
    SListPrint(pHead);
    SListErase(&pHead, Find(pHead, 1));
    SListPrint(pHead);
    SListErase(&pHead, Find(pHead, 3));
    SListPrint(pHead);
}

// 链表中结点个数测试
void Size_test()
{
    int num = 0;
    PNode pHead;
    SListInit(&pHead);
    printf("个数测试\n");


    SListPushBack(&pHead, 0);
    SListPushBack(&pHead, 1);
    SListPushBack(&pHead, 2);
    SListPushBack(&pHead, 3);
    SListPushBack(&pHead, 4);
    SListPrint(pHead);

    num = Size(pHead);
    printf("节点个数为:%d \n", num);
}

// 销毁单链表测试 
void SListDestroy_test()
{

    PNode pHead;
    SListInit(&pHead);
    printf("销毁测试\n");


    SListPushBack(&pHead, 0);
    SListPushBack(&pHead, 1);
    SListPushBack(&pHead, 2);
    SListPushBack(&pHead, 3);
    SListPushBack(&pHead, 4);
    SListPrint(pHead);

    SListDestroy(&pHead);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值