写在前面:
又是一篇学习记录。
单链表算是很经典的一种数据结构了,记得数据结构课本开篇就讲的它。但当时虽然想明白了,却没有用代码实现出来。这次“朝花夕拾”,又碰到这家伙,就决定写下来。(:з)∠)
好了,先附上结构体代码,如下:
typedef struct _NODE
{
int value;
struct _NODE* next;
}NODE, *PNODE;
struct _NODE包括一个int 型 value,和一个指向本类型的指针。
为方便使用,又用typedef给这个结构起了俩别名~。
其实我写的单链表的基本操作的基本思想是跟数组类似的,当然也有很多不同,比如插入,删除操作,单链表不用依次移位。
c语言数组基本操作
偷偷写个自己的链接。 []~( ̄▽ ̄)~*
下面是开始进入正题。(严肃脸)
先附上list.h,包含所有函数声明。
list.h ?
#ifndef _LIST_H_
#define _LIST_H_
typedef struct _NODE
{
int value;
struct _NODE* next;
}NODE, *PNODE;
void InsertHead(PNODE* ppHead, int value);
void InsertTail(PNODE* ppHead, int value);
void InsertByIndex(PNODE* ppHead, int index, int value);
void DeleteHead(PNODE* ppHead);
void DeleteTail(PNODE* ppHead);
void DeleteByIndex(PNODE* ppHead,int index);
void DeleteByValue(PNODE* ppHead,int value);
PNODE FindByIndex(PNODE pHead, int index);
PNODE FindByValue(PNODE pstart, int value);
void ModifyByIndex(PNODE pHead, int index, int value);
void ModifyByValue(PNODE pHead,int oldvalue, int newvalue);
void Showlist(PNODE pHead);
#endif
一个一个来,( ╯□╰ )
查找 ?
第一个按位置查找:
PNODE FindByIndex(PNODE pHead,int index)
{
if (index < 0)
{
return NULL; //查找第0个之前的结点则返回NULL
}
PNODE pfbi = pHead;
for (int i = 0; i < index && pfbi != NULL; ++i)
{
pfbi = pfbi->next; //从第一个开始依次遍历
}
return pfbi; //找到返回指向该位置的指针,否则返回NULL
}
第二个按值查找:
PNODE FindByValue(PNODE pstart, int value)
{
PNODE pfbv = pstart;
while (pfbv != NULL && pfbv->value != value)
{
pfbv = pfbv->next; //从第起点开始依次遍历
}
return pfbv; //找到返回指向该位置的指针,否则返回NULL
}
修改 ?
第一个按位置修改:
void ModifyByIndex(PNODE pHead,int index, int value)
{
PNODE pfind = FindByIndex(pHead, index); //调用按位置查找
if (pfind != NULL)
{
pfind->value = value; //找到则修改
}
}
第二个按值修改:
void ModifyByValue(PNODE pHead, int oldvalue, int newvalue)
{
PNODE pfind = pHead; //将头指针赋给新建指针
while (pfind != NULL)
{
pfind = FindByValue(pfind, oldvalue); //调用按值查找,每次起点为上次终点
if (pfind != NULL)
{
pfind->value = newvalue; //找到则修改
}
}
}
删除 ?
第一个删除头结点:
void DeleteHead(PNODE* ppHead)
{
if (*ppHead != NULL) //不为空链表
{
PNODE pdel = *ppHead;
*ppHead = pdel->next; //头指针指向第一个节点的指向节点
free(pdel); //释放节点空间
//pdel = NULL; //指针置空
}
}
第二个删除尾结点:
void DeleteTail(PNODE* ppHead)
{
if (NULL == *ppHead || NULL == (*ppHead)->next)
{
DeleteHead(ppHead); //如果是空指针,或只有一个节点调用头删函数
}
else
{
PNODE pdel = *ppHead;
while (pdel->next->next != NULL)
{
pdel = pdel->next; //下下个节点不为空,则指针后移
}
free(pdel->next); //释放节点空间
pdel->next = NULL; //将此时尾节点next值置空
}
}
第三个按位置删除:
void DeleteByIndex(PNODE* ppHead, int index)
{
if (index < 0)
{
return; //index小于0则结束函数
}
else if (index == 0)
{
DeleteHead(ppHead); //index等于0则调用头删函数
}
else
{
PNODE ppre = *ppHead; //前驱指针
PNODE pdbi = ppre->next;
for (int i = 1; i < index && pdbi != NULL; ++i)
{ //从第二个节点开始
ppre = ppre->next;
pdbi = pdbi->next; //两指针后移
}
if (pdbi != NULL)
{ //如果存在该位置结点
ppre->next = pdbi->next;//上一个结点指向本结点下一个结点
free(pdbi); //释放该结点空间
}
}
}
第四个按值删除:
void DeleteByValue(PNODE* ppHead, int value)
{
if (*ppHead != NULL)
{
while ((*ppHead)->value == value)
{
DeleteHead(ppHead); //如果第一个结点是要删结点则调用头删函数
}
if (*ppHead == NULL)
{
return; //防止所有结点都是要删结点
}
PNODE ppre = *ppHead; //前驱指针
PNODE pdbv = ppre->next;
while (pdbv != NULL)
{
if (pdbv->value == value)
{
ppre->next = pdbv->next;//前驱指针指向本结点的下个结点
free(pdbv); //释放本结点空间
pdbv = ppre->next; //pdbv指向前驱指针指向结点的下个结点
continue;
}
ppre = ppre->next;
pdbv = pdbv->next; //每次循环两指针后移
}
}
}
插入 ?
第一个头插:
void InsertHead(PNODE* ppHead, int value)
{
PNODE pnew = (PNODE)malloc(sizeof(NODE));
//新建结点并让pnew指向它
pnew->value = value;
pnew->next = *ppHead;//新建结点指向头指针指向结点
*ppHead = pnew;//头指针指向新建结点
}
第二个尾插:
void InsertTail(PNODE* ppHead, int value)
{
if (NULL == *ppHead)
{
InsertHead(ppHead, value);//空链表则调用头插函数
}
else
{
PNODE pnew = (PNODE)malloc(sizeof(NODE));
//新建结点并让pnew指向它
pnew->value = value;
pnew->next = NULL;//因为尾插所以next置为NULL
PNODE pTail = *ppHead;
while (pTail->next != NULL)
{
pTail = pTail->next;//找到最后一个结点
}
pTail->next = pnew;//让最后一个结点指向新结点
}
}
第三个按位置插入:
void InsertByIndex(PNODE* ppHead, int index, int value)
{
if (index <= 0)
{
InsertHead(ppHead, value); //默认将index小于等于0的都当头插处理
}
else
{
PNODE pnew = (PNODE)malloc(sizeof(NODE));
//新建结点并让pnew指向它
pnew->value = value;
PNODE pleft = *ppHead; //pleft意为指向插入点前一个结点
PNODE pright = pleft->next; //pright意为指向插入点后一个结点
for (int i = 1; i < index && pright != NULL; ++i)
{
pleft = pleft->next;
pright = pright->next; //在找到前两指针一直后移
}
if (pright != NULL)
{//如果找到目标位置
pnew->next = pright;//新结点指向pright指向结点
pleft->next = pnew;//pleft指向结点指向新结点
}
else
{//如果是插到最后
pnew->next = NULL;//新结点next置为NULL
pleft->next = pnew;//pleft指向结点指向新结点
}
}
}
输出 ?
还有个输出函数也写上吧,(:з)∠)
void Showlist(PNODE pHead)
{
PNODE pshow = pHead;//“接收”头指针
while (pshow != NULL)
{//挨个儿输出
printf("%d,", pshow->value);
pshow = pshow->next;
}
puts("\b;");
}
写完啦哈哈哈哈红红火火恍恍惚惚。
自己给自己放个烟花!
谢观~