本期的链表继续进行,上期我们完成了链表的增加和删除。
现在接下来,我们进行链表的查改与优化
头文件“SList.h”
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
typedef int SLTDataType;
typedef struct SListNode
{
SLTDataType data;
struct SListNode* next;
}SLTNode;
//打印
void SLTPrint(SLTNode* phead);
//开辟空间
SLTNode* SLT_BUY(SLTDataType x);
//尾插数据
void SLTPushBack(SLTNode** pphead, SLTDataType x);
//尾删数据
void SLTPopBack(SLTNode** pphead);
//头插数据
void SLTPushFront(SLTNode** pphead, SLTDataType x);
//头删数据
void SLTPopFront(SLTNode** pphead);
//查找指定数值
SLTNode* SLT_FIND(SLTNode** pphead, SLTDataType x);
//删除数据
void SLTErase(SLTNode** pphead, SLTNode* pos);
测试环节“Test.c”
#include "SList.h"
void test_01()
{
SLTNode* plist = NULL; //由于一个链表单元只存储一个数值,因此直接初始化即可
//而顺训表有多个变量,比如,sz, capcity需要进行初始化,因此需要分装一个初始化函数
SLTPushBack(&plist, 21);
SLTPushBack(&plist, 23);
SLTPushBack(&plist, 25);
SLTPushBack(&plist, 27);
SLTPushBack(&plist, 29); //尾插数据
SLTPrint(plist);
SLTNode* ret = SLT_FIND(&plist, 25);
SLTErase(&plist, ret); //指定数据25进行删除
SLTPrint(plist);
}
int main()
{
test_01();
}
优化实现环节“SList.c”
#include "SList.h"
//打印
void SLTPrint(SLTNode* phead)
{
SLTNode* cur = phead;
while(cur)
{
printf("%d->", cur ->data);
cur = cur ->next;
}
printf("NULL\n");
}
//开辟空间
SLTNode* SLT_BUY(SLTDataType x)
{
SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));
if(newnode == NULL)
{
perror("malloc::fail");
return NULL;
}
newnode ->data = x;
newnode ->next = NULL; //防止野指针乱窜
return newnode;
}
//尾插数据
void SLTPushBack(SLTNode** pphead, SLTDataType x)
{
//开辟空间
SLTNode* newnode = SLT_BUY(x);
if(*pphead == NULL)
{
*pphead = newnode;
}
else
{
SLTNode* tail = *pphead;
while(tail != NULL)
{
tail = tail ->next;
}
tail = newnode;
}
}
//头插数据
void SLTPushFront(SLTNode** pphead, SLTDataType x)
{
SLTNode* newnode = SLT_BUY(x);
newnode ->next = *pphead;
*pphead = newnode;
}
//尾删数据
void SLTPopBack(SLTNode** pphead)
{
assert(pphead);
assert(*pphead);
//1.只有一个节点
//2.有两个及多个节点
if(*pphead == NULL)
{
free(*pphead);
*pphead = NULL;
}
else
{
SLTNode* tail = *pphead;
SLTNode* prev = NULL;
while(tail ->next != NULL)
{
prev = tail;
tail = tail ->next;
}
free(tail);
tail = NULL;
prev ->next = NULL; //防止野指针乱窜
}
}
//头删数据
void SLTPopFront(SLTNode** pphead)
{
SLTNode* first = *pphead;
*pphead = first ->next; //运用了值覆盖原理
free(first);
first = NULL; //防止野指针乱窜
}
//查找指定数值
SLTNode* SLT_FIND(SLTNode** pphead, SLTDataType x)
{
assert(pphead);
assert(*pphead);
SLTNode* cur = *pphead;
while(cur)
{
if(cur -> data == x)
{
return cur;
}
cur = cur ->next;
}
return NULL;
}
//删除数据
void SLTErase(SLTNode** pphead, SLTNode* pos)
{
assert(pphead);
assert(*pphead);
if(*pphead == pos)
{
SLTPopFront(pphead);
}
else
{
SLTNode* prev = *pphead;
while(prev ->next != pos)
{
prev = prev ->next;
}
prev ->next = pos ->next;
free(pos);
}
}
下面是优化后的指定删除的运行结果 :>
下面再进一步完善
1.在指定位置pos之前进行插入数据
//在pos之前插入数据
void SLTInsertBefore(SLTNode** pphead, SLTNode* pos, SLTDataType x)
{
assert(pphead);
assert(*pphead);
if(*pphead == pos)
{
SLTPushFront(pphead, x);
}
else
{
SLTNode* prev = *pphead;
SLTNode* newnode = SLT_BUY(x);
while(prev ->next != pos)
{
prev = prev ->next;
}
prev ->next = newnode;
newnode ->next = pos;
}
}
2.在指定位置pos之后进行插入数据
//在pos之后插入数据
void SLTInsertAfter(SLTNode* pos, SLTDataType x)
{
SLTNode* newnode = SLT_BUY(x);
newnode ->next = pos ->next;
pos ->next = newnode;
}
3.在指定位置pos之后进行删除数据
//在pos位置之后进行删除
void SLTEraseAfter(SLTNode* pos)
{
SLTNode* del = pos ->next;
pos ->next = del ->next;
free(del);
del = NULL;
}
现在补充头文件“SList.h”
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
typedef int SLTDataType;
typedef struct SListNode
{
SLTDataType data;
struct SListNode* next;
}SLTNode;
//打印
void SLTPrint(SLTNode* phead);
//开辟空间
SLTNode* SLT_BUY(SLTDataType x);
//尾插数据
void SLTPushBack(SLTNode** pphead, SLTDataType x);
//尾删数据
void SLTPopBack(SLTNode** pphead);
//头插数据
void SLTPushFront(SLTNode** pphead, SLTDataType x);
//头删数据
void SLTPopFront(SLTNode** pphead);
//查找指定数值
SLTNode* SLT_FIND(SLTNode** pphead, SLTDataType x);
//删除数据
void SLTErase(SLTNode** pphead, SLTNode* pos);
//在pos之前插入数据
void SLTInsertBefore(SLTNode** pphead, SLTNode* pos, SLTDataType x);
//在pos之后插入数据
void SLTInsertAfter(SLTNode* pos, SLTDataType x);
//在pos位置之后进行删除
void SLTEraseAfter(SLTNode* pos);
现在进入测试环节“Test.c”
---->pos之前插数据 :>
#include "SList.h"
void test_02()
{
SLTNode* plist = NULL; //由于一个链表单元只存储一个数值,因此直接初始化即可
//而顺训表有多个变量,比如,sz, capcity需要进行初始化,因此需要分装一个初始化函数
SLTPushBack(&plist, 31);
SLTPushBack(&plist, 33);
SLTPushBack(&plist, 35);
SLTPushBack(&plist, 37);
SLTPushBack(&plist, 39); //尾插数据
SLTPrint(plist);
SLTNode* ret = SLT_FIND(&plist, 39);
SLTInsertBefore(&plist, ret, 38); //在39之前进行插入数据38
SLTPrint(plist);
}
int main()
{
test_02();
}
测试运行结果 :>
---->pos之后插数据 :>
#include "SList.h"
void test_03()
{
SLTNode* plist = NULL; //由于一个链表单元只存储一个数值,因此直接初始化即可
//而顺训表有多个变量,比如,sz, capcity需要进行初始化,因此需要分装一个初始化函数
SLTPushBack(&plist, 31);
SLTPushBack(&plist, 33);
SLTPushBack(&plist, 35);
SLTPushBack(&plist, 37);
SLTPushBack(&plist, 39); //尾插数据
SLTPrint(plist);
SLTNode* ret = SLT_FIND(&plist, 35);
SLTInsertAfter(ret, 36); //在指定位置35后面插入数据36
SLTPrint(plist);
}
int main()
{
test_03();
}
测试运行结果 :>
---->pos之后删除数据 :>
#include "SList.h"
void test_05()
{
SLTNode* plist = NULL; //由于一个链表单元只存储一个数值,因此直接初始化即可
//而顺训表有多个变量,比如,sz, capcity需要进行初始化,因此需要分装一个初始化函数
SLTPushBack(&plist, 31);
SLTPushBack(&plist, 33);
SLTPushBack(&plist, 35);
SLTPushBack(&plist, 37);
SLTPushBack(&plist, 39); //尾插数据
SLTPrint(plist);
SLTNode* ret = SLT_FIND(&plist, 31);
SLTInsertAfter(ret); //在指定位置31后面删除数据33
SLTPrint(plist);
}
int main()
{
test_05();
}
测试运行结果 :>
本期链表的增删查改及其优化测试就已经结束了!!
下一期,会对本文中链表的一些代码进行解读和分析!!
感谢小伙伴们的阅读!!