单链表基本操作

思维导图

这里写图片描述

SList.h

#pragma once
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>


typedef int DataType;

typedef struct SNode
{
    DataType data;
    struct SNode *_pNext;//保存下个节点的地址

}SNode, *PNode;


void SListInit(PNode* pHead);// 链表的初始化 
void SListPushBack(PNode* pHead, DataType data);// 尾插 
void SListPopBack(PNode* pHead);// 尾删 
void SListPushFront(PNode* pHead, DataType data);// 头插 
void SListPopFront(PNode* pHead);// 头删 
PNode SListFind(PNode pHead, DataType data);// 在链表中查找值为data的元素,找到后返回值为data的结点
void SListInsert(PNode* pHead, PNode pos, DataType data);// 在pos位置插入值为data的结点 
void SListErase(PNode* pHead, PNode pos);// 删除pos位置的结点 
int SListSize(PNode pHead);// 获取链表中节点总数
int SListEmpty(PNode pHead);// 判断链表是否为空 
void SListDestroy(PNode* pHead);// 销毁链表
void PrintfList(PNode pHead);//打印链表

SList.c

#include "SList.h"

//初始化就是将链表头指针赋空,
//注意这里要传头指针的地址才能改变头指针的值
void SListInit(PNode* pHead)
{
    assert(pHead);//判断链表是否存在
    *pHead = NULL;
}
//创建新节点
PNode BuyNewNode(DataType data)
{
    PNode ptr = NULL;
    ptr = (PNode)malloc(sizeof(DataType)+sizeof(PNode));

    if (NULL == ptr)
    {
        printf("BuyNewNode failed!!!\n");
        return NULL;
    }
    //申请成功  
    ptr->data = data;
    ptr->_pNext = NULL;
    return ptr;
}

//打印链表
void PrintfList(PNode pHead)
{
    PNode ptr = pHead;
    if (pHead == NULL)
        return;
    while (ptr)
    {
        printf("%d-->", ptr->data);
        ptr = ptr->_pNext;
    }
    printf("NULL\n");

}

//尾插
void SListPushBack(PNode* pHead, DataType data)
{
    PNode pCur = NULL;
    assert(pHead);//判断链表是否存在

    if (*pHead == NULL)//判断链表是否为空
    {
        *pHead = BuyNewNode(data);//空就让头节点指向新节点
        return;
    }

    //1.先找到链表最后一个节点
    pCur = *pHead;
    while (pCur->_pNext)
    {
        pCur = pCur->_pNext;//朝后走一步
    }
    pCur->_pNext = BuyNewNode(data);

}

//尾删
void SListPopBack(PNode* pHead)
{
    assert(pHead);
    PNode pPre = *pHead;
    PNode pCur = *pHead;

    if (*pHead == NULL)
    {
        printf("链表已空,删除失败!!!\n");
        return;
    }

    //1.只有一个节点
    if (pCur->_pNext == NULL)
    {
        free(*pHead);
        *pHead = NULL;
        return;
    }
    //2.有一个以上节点
    while (pCur->_pNext)
    {
        pPre = pCur;//因为要找到倒数第二个节点,所以每走一步之前先保存
        pCur = pCur->_pNext;
    }
    free(pPre->_pNext);
    pPre->_pNext = NULL;
}

//头插
void SListPushFront(PNode* pHead, DataType data)
{
    PNode ptr = NULL;
    assert(pHead);
    //1.链表为空
    if (NULL == *pHead)
    {
        *pHead = BuyNewNode(data);
        return;
    }

    //2.链表不为空
    ptr = *pHead;//先保存第一个节点地址
    *pHead = BuyNewNode(data);//头指针指向新节点
    (*pHead)->_pNext = ptr;//新节点的_pNext指向原来的头节点

}

//头删
void SListPopFront(PNode* pHead)// 头删
{
    assert(pHead);
    PNode ptr = NULL;
    if (NULL == pHead)
    {
        printf("链表已空,删除失败!!!\n");
        return;
    }

    //1.只有一个节点
    if ((*pHead)->_pNext == NULL)
    {
        free(*pHead);
        *pHead = NULL;
        return;
    }

    //2.有一个以上的节点
    ptr = *pHead;//先保存头节点地址
    *pHead = (*pHead)->_pNext;//头指针朝后走一步;
    free(ptr);//释放原头节点空间
}
//查找为data的节点
PNode SListFind(PNode pHead, DataType data)
{
    PNode ptr = pHead;
    if (NULL == pHead)
    {
        printf("对不起,为空链表!!!\n");
        return NULL;
    }

    while ((ptr) && (ptr->data != data))//ptr中的data不是要找的且不为空就进入循环
    {
        ptr = ptr->_pNext;
    }

    //1.ptr为空,证明找不到
    if (NULL == ptr)
    {
        printf("对不起,找不到!!!\n");
        return NULL;
    }
    else
        return ptr;
}

int SListSize(PNode pHead)
{
    int count = 0;
    while (pHead)
    {
        pHead = pHead->_pNext;
        count++;
    }
    return count;
}

void SListInsert(PNode* pHead, PNode pos, DataType data)
{
    assert(pHead);

    //1.链表为空
    if (NULL == *pHead)
    {
        //1.如果链表为空,插入位置与头节点地址不相同,那么位置不合法
        if (pos == *pHead)
        {
            *pHead = BuyNewNode(data);
            return;
        }
        else
        {
            printf("位置不合法,插入失败!!!\n");
            return;
        }
    }

    //2.链表不为空
    //(1)头插:pos与头节点地址相等
    if (pos == *pHead)
        SListPushFront(pHead, data);
    //(2)pos与头节点位置不相等
    else
    {
        PNode pPre = *pHead;
        PNode pCur = *pHead;
        while ((pCur) && (pCur->_pNext != pos))
        {
            pCur = pCur->_pNext;
        }
        if (pCur == NULL)
        {
            printf("对不起,找不到该节点!!!\n");
            return;
        }
        else
        {
            pCur->_pNext = BuyNewNode(data);//插入新节点
            pCur->_pNext->_pNext = pos;//新节点链接pos处的节点
            pos = pCur->_pNext;//pos指向新节点
        }

    }
}


// 删除pos位置的结点 
void SListErase(PNode* pHead, PNode pos)
{
    assert(pHead);
    PNode ptr = *pHead;

    if (NULL == *pHead)
    {
        printf("链表已空,删除失败!!!\n");
        return;
    }

    //1.只有一个节点
    if ((*pHead)->_pNext == NULL)
    {
        if (*pHead == pos)
        {
            free(pos);
            *pHead = NULL;
            return;
        }

        else
        {
            printf("位置不合法,删除失败!!!\n");
            return;
        }
    }

    //2.有一个以上节点
    //(1)如果pos是头节点
    if (pos == *pHead)
    {
        *pHead = (*pHead)->_pNext;
        free(pos);
        return;
    }

    //(2)不是头结点
    while ((ptr) && (ptr->_pNext != pos) && (pos))
    {
        ptr = ptr->_pNext;
    }

    if ((ptr == NULL) || (pos == NULL))
    {
        printf("节点不存在,删除失败!!!\n");
        return;
    }
    else
    {
        ptr->_pNext = pos->_pNext;//链接起pos的下个节点
        free(pos);
    }
}
// 判断链表是否为空 
int SListEmpty(PNode pHead)
{
    if (pHead)
        return 1;
    return 0;
}

// 销毁链表
void SListDestroy(PNode* pHead)
{
    assert(pHead);
    PNode ptr = *pHead;
    PNode pMsg = *pHead;

    while (ptr)
    {
        ptr = ptr->_pNext;//ptr朝后走
        free(pMsg);//释放pMsg指向的空间

        if (ptr)
            pMsg = ptr;//pMsg跟着ptr走
    }
    *pHead = NULL;
}

test.c

#include "SList.h"
#include <windows.h>


int main()
{
    SNode SList;
    PNode pHead = &SList;
    SListInit(&pHead);// 链表的初始化
    SListEmpty(pHead);// 判断链表是否为空 
    SListInsert(&pHead, pHead, 40);
    PrintfList(pHead);
    //SListPushFront(&pHead, 0);
    //PrintfList(pHead);
    SListPushBack(&pHead, 5);//尾插
    SListPushBack(&pHead, 10);
    SListPushBack(&pHead, 3);
    //PrintfList(pHead);
    //SListPopBack(&pHead);//尾删
    //PrintfList(pHead);
    SListPushFront(&pHead, 0);//头插
    //PrintfList(pHead);
    //SListPopFront(&pHead);//头删
    PrintfList(pHead);
    // 在链表中查找值为data的元素,找到后返回值为data的结点
    SListFind(pHead, 3);
    SListSize(pHead);// 获取链表中节点总数
    SListInsert(&pHead, pHead->_pNext->_pNext , 20);// 在pos位置插入值为data的结点 
    PrintfList(pHead);
    SListErase(&pHead, pHead->_pNext->_pNext);// 删除pos位置的结点
    PrintfList(pHead);
    //SListDestroy(&pHead);// 销毁链表

    system("pause");
    return 0;
}
阅读更多
个人分类: 数据结构
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭