今天我们来学习一波有关链表的基本算法。
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<Windows.h>
// 值类型
typedef int DataType;
typedef struct SListNode {
DataType data; // 值
struct SListNode *pNext; // 指向下一个结点
} SListNode;
// 初始化
void SListInit(SListNode **ppFirst)
{
SListNode *pNode=*ppFirst;
assert(ppFirst!=NULL); //初始化一个空链表。
pNode=NULL;
}
void SListsetup(DataType data)
{
SListNode *NewNode=(SListNode *)malloc(sizeof(SListNode));
assert(NewNode);
NewNode->data=data;
NewNode->pNext=NULL;
}
// 尾部插入
void SListPushBack(SListNode** ppFirst, DataType data)
{
SListNode *pNode;
SListNode *pNewNode=(SListNode *)malloc(sizeof(SListNode)); //开辟一个空间,将data赋给它,并将pNext赋成NULL。
pNewNode->data=data;
pNewNode->pNext=NULL;
pNode=*ppFirst; //定义一个变量指向首元素。
if(pNode==NULL)
{
pNode->data=data; //可简写为 *pNode=pNewNode;
pNode->pNext=NULL;
}
while(pNode->pNext!=NULL)
{
pNode=pNode->pNext; //循环得到最后一位数。将它的pNext赋值成data。
}
pNode->pNext=pNewNode;
free(pNewNode); //释放。
}
// 头部插入
void SListPushFront(SListNode **ppFirst, DataType data)
{
SListNode *pNewNode=(SListNode *)malloc(sizeof(SListNode));
if(ppFirst==NULL)
{ //如果为空,就直接赋值。
pNewNode->data=data;
pNewNode->pNext=NULL;
}
else{
pNewNode->data=data; //否则将开辟出来的空间的pNext赋值为原来第一个元素的地址。
pNewNode->pNext=*ppFirst;
}
free(pNewNode);
}
// 尾部删除
void SListPopBack(SListNode **ppFirst)
{
SListNode *pNode,*q;
assert(ppFirst!=NULL);
if((*ppFirst)->pNext==NULL) //如果只有一个元素,那就直接删除。
{
free(*ppFirst);
*ppFirst=NULL;
}
pNode=*ppFirst;
while(pNode->pNext->pNext!=NULL) //这一步是为了找到倒数第二个数。将它的pNext赋值成NULL。
{
pNode=pNode->pNext;
}
q=pNode->pNext;
pNode->pNext=NULL;
free(q);
}
// 头部删除
void SListPopFront(SListNode **ppFirst)
{
SListNode *pNode,*m;
assert(ppFirst!=NULL);
pNode=*ppFirst;
m=pNode->pNext;
free(pNode);
*ppFirst=m;
}
// 给定结点插入,插入到结点前
void SListInsert(SListNode **ppFirst, SListNode *pPos, DataType data)
{
SListNode *pNode=*ppFirst;
SListNode *pNewNode=(SListNode *)malloc(sizeof(SListNode));
assert(ppFirst!=NULL);
pNewNode->pNext=pPos;
pNewNode->data=data; //要插入的空间的data赋值data,pNext赋值为pPos。
if(*ppFirst==pPos) //如果第一个是指定节点就直接调用头插函数。
{
SListPushFront(ppFirst,data);
return;
}
while(pNode->pNext!=pPos) //循环找到给定节点前的那个数。
{
pNode=pNode->pNext;
}
pNode->pNext=pNewNode; //将它的pNext赋值成要插入的值。
free(pNewNode);
}
// 给定结点删除
void SListErase(SListNode **ppFirst, SListNode *pPos)
{
SListNode *pNode=*ppFirst;
if(*ppFirst==pPos) //如果给定节点为第一个,就直接调用头删函数。
{
SListPopFront(ppFirst);
return;
}
while(pNode->pNext!=pPos) //循环找到给定节点的上一个数。
{
pNode=pNode->pNext;
}
pNode->pNext=pNode->pNext->pNext; //pNode->pNext=pPos->pNext
free(pPos);
}
// 按值查找,返回第一个找到的结点指针,如果没找到,返回 NULL
SListNode *SListFind(SListNode *pFirst, DataType data)
{
SListNode *pNode;
assert(pFirst!=NULL);
for(pNode=pFirst;pNode!=NULL;pNode=pNode->pNext) //循环寻找这个值第一次出现的位置。
{
if(pNode->data==data)
{
return pNode; //找到返回它的节点指针,否则返回NULL。
}
}
return NULL;
}
// 按值删除,只删遇到的第一个
void SListRemove(SListNode **ppFirst, DataType data)
{
SListNode *pNode;
assert(ppFirst!=NULL);
pNode=SListFind(*ppFirst, data); //调用查找函数。
if(pNode==NULL)
{
printf("This data is not exit!\n"); //如果为NULL,则表示没这个值。
}
else{
SListErase(ppFirst,pNode); //否则调用根据节点删除函数。
}
}
// 按值删除,删除所有的
void SListRemoveAll(SListNode **ppFirst, DataType data)
{
SListNode *pNode,*x;
assert(ppFirst!=NULL);
x=SListFind(*ppFirst, data);
if(x==NULL)
{
printf("This data is not exit!\n");
}
else{
for(pNode=*ppFirst;pNode!=NULL;pNode=pNode->pNext) //从头开始寻找与值一样的节点所在位置,然后分别删除它们。
{
if(pNode->data==data)
{
SListErase(ppFirst,pNode);
}
}
}
}
int SListSize(SListNode **ppFirst)//统计链表中一共有多少个数
{
int size=0;
SListNode *pNode=*ppFirst;
for(;pNode!=NULL;pNode=pNode->pNext) //循环计算链表中有几个数。
{
size++;
}
printf("The nnumber is %d\n",size); //输出结果。
return 0;
}
// 销毁
void SListDestroy(SListNode **ppFirst)
{
SListNode *r;
SListNode *pNode=*ppFirst;
for(;pNode!=NULL;pNode=r)
{
r=pNode->pNext;
free(pNode);
}
*ppFirst=NULL;
}
以上就是我所编写的算法,其中可能有很多错误,希望大家给些意见。