有关操作单链表的函数

slist.h

#ifndef __SLIST_H__
#define __SLIST_H__

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

typedef int DataType;

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

void SListDestory(SListNode** ppHead);  //销毁链表
void SListPrint(SListNode* pHead);   //打印
SListNode* BuySListNode(DataType x);  //创建一个节点

void SListPushBack(SListNode** ppHead, DataType x); //尾插
void SListPopBack(SListNode** ppHead);   //尾删

void SListPushFront(SListNode** ppHead, DataType x); //头插
void SListPopFront(SListNode** ppHead);  //头删

void SListInsest(SListNode** ppHead, SListNode* pos, DataType x);//任意位置插入
void SListErase(SListNode** ppHead, SListNode* pos);//任意位置删


#endif//__SLIST_H__

slist.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"slist.h"

//打印
void SListPrint(SListNode* pHead)
{
    SListNode* cur = pHead;  // 创建一个临时变量 防止打印完链表 pHead 指向了尾
    //assert(pHead);         //这里不需要断言, 因为可以打印空链表
    while(cur)       //不能是cur->_next   会跳过第一个数据
    {
        printf("%d ",cur->_data);
        cur = cur->_next;
    }
    printf("\n");
}

//创建一个节点
SListNode* BuySListNode(DataType x)
{
    SListNode* node = (SListNode*)malloc(sizeof(SListNode));
    node->_data = x;
    node->_next = NULL;  //要将它里面的指针置空  
    return node;
}

//尾插
void SListPushBack(SListNode** ppHead, DataType x)
{
    SListNode* tail = *ppHead;
    assert(ppHead);
    if(*ppHead == NULL)
    {
        *ppHead = BuySListNode(x);
    }
    else
    {
        while(tail->_next)   //
        {
            tail = tail->_next;
        }
        tail->_next = BuySListNode(x);
    }
}

//尾删
void SListPopBack(SListNode** ppHead)
{
    SListNode* prev = NULL;
    SListNode* tail = *ppHead;
    assert(ppHead);
    if(*ppHead == NULL)  //空链表
    {
        return;
    }
    else
    {
        while(tail->_next)
        {
            prev = tail;      //先将tail保存
            tail = tail->_next;
        }
        if(prev == NULL)      //只有一个节点,只需要将头结点置空
        {
            *ppHead = NULL;
        }
        else                //有2个或2个以上的节点
        {
            prev->_next = NULL;
        }

        free(tail);  //要将最后一个free掉
    }
}

//头插
void SListPushFront(SListNode** ppHead, DataType x)
{
    SListNode* pHead = NULL;
    assert(ppHead);
    if(*ppHead == NULL)  //空链表
    {
        *ppHead = BuySListNode(x);
    }
    else
    {
        pHead = BuySListNode(x);
        pHead->_next = *ppHead;

        *ppHead = pHead;  //将头节点刷新
    }
}

//头删
void SListPopFront(SListNode** ppHead)
{
    SListNode* tail = *ppHead;
    //SListNode* prev = *ppHead;
    assert(ppHead);
    if(*ppHead == NULL)  //空链表
    {
        return;
    }
    //else if((*ppHead)->_next == NULL) //只有一个节点
    //{
    //  free(*ppHead);
    //  *ppHead = NULL;
    //}
    else       // 多个节点  这个可以将只有一个节点的情况处理掉
    {
        *ppHead = (*ppHead)->_next;
        free(tail);
        //tail = (*ppHead)->_next;
        //free(*ppHead);
        //*ppHead = tail;         
    }
}

//任意位置插入(插在该位置的前面)
void SListInsest(SListNode** ppHead, SListNode* pos, DataType x)
{
    SListNode* tail = pos;  //保存pos 

    //如果是空链表的情况已经在Find中处理

    if(pos == *ppHead)  //如果在头部       
    {
        SListPushFront(ppHead, x);      //SListPushFront(&pos, x)->插不进去,为什么
    }
    //else if(pos == NULL)         //如果在尾部   和在中间一样
    //{
    //  SListPushBack(&pos, x);
    //}
    else
    {
        pos = BuySListNode(pos->_data);  //  先将pos 这个位置的数插到pos后面 
        pos->_next = tail->_next;                   
        tail->_next = pos;                   
        tail->_data = x;  //将pos 位置的数改为要插入的数
    }

}

//任意位置删除
void SListErase(SListNode** ppHead, SListNode* pos)
{
    SListNode* tail = *ppHead;
    assert(ppHead);
    //assert(pos);
    if(*ppHead == NULL)  //如果空
    {
        return;
    }
    else
    {
         if(pos == *ppHead)  //如果在头
         {
             SListPopFront(ppHead);    //SListPopFront(&pos) -> 打印随机值程序崩溃,为什么?
         }
         else if(pos== NULL)  //如果在尾
         {
             SListPopBack(&pos);
         }
         else               //在中间
         {
             while(tail->_next != pos)
             {
                 tail = tail->_next;  //找到pos的前一个
             }
             tail->_next = pos->_next;
             free(pos);
         }
    }
}

//销毁链表(还可以用递归法)
void SListDestory(SListNode** ppHead)
{
    SListNode *tail = *ppHead;

    assert(*ppHead);
    while(*ppHead)      //不能是((*ppHead->_next)) 程序会崩溃
    {
        (*ppHead) = (*ppHead)->_next;
        free(tail);
        tail = (*ppHead);
    }
    free(tail);
    free(*ppHead);  

    //free(ppHead);   //不能有这一句  程序会崩溃   
}

test.c

“`

define _CRT_SECURE_NO_WARNINGS 1

include”slist.h”

static SListNode* Find(SListNode *pHead, DataType x)
{
if(pHead == NULL) //防止在任意位置插入的时候崩溃
{
printf(“链表为空,无法插入\n”);
exit(0);
}
while((pHead->_data != x) && (pHead->_next != NULL)) //2个判断条件都不能少否则程序崩溃
{
pHead = pHead->_next;
}

//if(pHead->_next == NULL)    //判断不能少,防止在任意删除时 如果这个数不存在,会删错(将最后一个删掉)
//{
//  printf("链表中找不到您要的数\n");
//  exit(0);
//}
//加上上面的会使任意删删不掉尾
return pHead;

}

int main()
{
SListNode *list = NULL;
SListNode *pos = NULL;

//SListPopBack(&list);
SListPushBack(&list, 1);
//SListPrint(list);
SListPushBack(&list, 2);
SListPushBack(&list, 3);
SListPushBack(&list, 4);
SListPrint(list);

//SListPopBack(&list);

//SListPushFront(&list, 0);
//SListPopFront(&list);

//pos = Find(list, 1);

//SListErase(&list, pos);

//SListInsest(&list,pos,25);
SListDestory(&list);
SListPrint(list);

return 0;

}

仍然存在的bug:在任意位置删除的时候,如果这个数不存在,则会删掉最后一个数。在任意插入数的时候,如果是空链表则不能插入。
希望有大佬可以帮修我改一下

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值