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