本节复习链表的增删查改

首先, 链表不是连续的, 而是通过指针联系起来的。 如图:线性表——单链表的增删查改-LMLPHP

这四个节点不是连续的内存空间, 但是彼此之间使用了一个指针来连接。 这就是链表。 

现在我们来实现链表的增删查改。

目录

单链表的全部接口:

 准备文件

建立结构体蓝图

申请链表节点函数接口

单链表的打印函数接口

单链表尾插函数接口

单链表头插函数接口

 单链表尾删函数接口

单链表的头删函数接口

 单链表查找函数接口

单链表pos位置之后插入数据接口

单链表删除pos之后位置的数据

单链表在pos位置之前插入数据接口

单链表删除pos位置数据接口

单链表的销毁


---------------------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------------------

建立结构体蓝图

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

typedef int SLTDataType;

---------------------------------------------------------------------------------------------------------------------------------

申请链表节点函数接口

.h函数声明

链表的增删查改///
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>

typedef int SLTDataType;

typedef struct SListNode //创建结构体
{
	struct SListNode* next;
	SLTDataType data;
}SLNode;

//链表接口声明/

//申请链表节点函数接口
SLNode* BuySListNode(SLTDataType x);

.c函数实现

单链表函数实现函数接口

//单链表申请节点函数接口
SLNode* BuySListNode(SLTDataType x) 
{
	SLNode* NewNode = (SLNode*)malloc(sizeof(SLNode));
	if (NewNode == NULL) 
	{
		printf("申请节点失败\n");
		return;
	}
	//
	NewNode->data = x;
	NewNode->next = NULL;
}

---------------------------------------------------------------------------------------------------------------------------------

单链表的打印函数接口

.h函数声明

链表的增删查改///
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>

typedef int SLTDataType;

typedef struct SListNode 
{
	struct SListNode* next;
	SLTDataType data;
}SLNode;

//链表接口声明/

//申请链表节点函数接口
SLNode* BuySListNode(SLTDataType x);
//单链表的打印函数接口
void SListPrint(SLNode* phead);

.c函数实现

单链表函数实现函数接口

//单链表申请节点函数接口
SLNode* BuySListNode(SLTDataType x) 
{
	SLNode* NewNode = (SLNode*)malloc(sizeof(SLNode));
	if (NewNode == NULL) 
	{
		printf("申请节点失败\n");
		return;
	}
	//
	NewNode->data = x;
	NewNode->next = NULL;
}

//单链表的节点打印操作
void SListPrint(SLNode* phead) 
{
	SLNode* cur = phead;

	while (cur != NULL) 
	{
		printf("%d->", cur->data);
		cur = cur->next;
	}
	if (cur == NULL)//最后打印一个NULL
	{
		printf("NULL");
	}
	
}

---------------------------------------------------------------------------------------------------------------------------------

单链表尾插函数接口

.h函数声明

链表的增删查改///
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>

typedef int SLTDataType;

typedef struct SListNode 
{
	struct SListNode* next;
	SLTDataType data;
}SLNode;

//链表接口声明/

//申请链表节点函数接口
SLNode* BuySListNode(SLTDataType x);
//单链表的打印函数接口
void SListPrint(SLNode* phead);
//单链表尾插函数接口
void SListPushBack(SLNode** pphead, SLTDataType x);

.c函数实现

单链表函数实现函数接口

//单链表申请节点函数接口
SLNode* BuySListNode(SLTDataType x) 
{
	SLNode* NewNode = (SLNode*)malloc(sizeof(SLNode));
	if (NewNode == NULL) 
	{
		printf("申请节点失败\n");
		return;
	}
	//
	NewNode->data = x;
	NewNode->next = NULL;
}

//单链表的节点打印操作
void SListPrint(SLNode* phead) 
{
	SLNode* cur = phead;

	while (cur != NULL) 
	{
		printf("%d->", cur->data);
		cur = cur->next;
	}
	if (cur == NULL)//最后打印一个NULL
	{
		printf("NULL");
	}
	
}

//单链表尾插函数接口
void SListPushBack(SLNode** pphead, SLTDataType x) 
{
	assert(pphead);
	SLNode* newnode = BuySListNode(x);//利用申请节点函数申请节点

	SLNode* cur = *pphead; //让cur指向phead所指向空间
	if (cur == NULL) //cur == NULL代表着phead指向NULL, 这时候让phead改变指向。传送phead指针的原因就是
	{                                              //要改变phead的指向。
		*pphead = newnode;//
	}
	else 
	{
		while (cur->next != NULL) //让cur遍历到最后一个节点
		{
			cur = cur->next;
		}
		cur->next = newnode;//最后
	}

}

---------------------------------------------------------------------------------------------------------------------------------

单链表头插函数接口

.h函数接口


链表的增删查改///
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>

typedef int SLTDataType;

typedef struct SListNode 
{
	struct SListNode* next;
	SLTDataType data;
}SLNode;

//链表接口声明/

//申请链表节点函数接口
SLNode* BuySListNode(SLTDataType x);
//单链表的打印函数接口
void SListPrint(SLNode* phead);
//单链表尾插函数接口
void SListPushBack(SLNode** pphead, SLTDataType x);
//单链表头插函数接口
void SListPushFront(SLNode** pphead, SLTDataType x);

.c函数实现

单链表函数实现函数接口

//单链表申请节点函数接口
SLNode* BuySListNode(SLTDataType x) 
{
	SLNode* NewNode = (SLNode*)malloc(sizeof(SLNode));
	if (NewNode == NULL) 
	{
		printf("申请节点失败\n");
		return;
	}
	//
	NewNode->data = x;
	NewNode->next = NULL;
}

//单链表的节点打印操作
void SListPrint(SLNode* phead) 
{
	SLNode* cur = phead;

	while (cur != NULL) 
	{
		printf("%d->", cur->data);
		cur = cur->next;
	}
	if (cur == NULL)//最后打印一个NULL
	{
		printf("NULL");
	}
	
}

//单链表尾插函数接口
void SListPushBack(SLNode** pphead, SLTDataType x) 
{
	assert(pphead);
	SLNode* newnode = BuySListNode(x);//利用申请节点函数申请节点

	SLNode* cur = *pphead; //让cur指向phead所指向空间
	if (cur == NULL) //cur == NULL代表着phead指向NULL, 这时候让phead改变指向。传送phead指针的原因就是
	{                                              //要改变phead的指向。
		*pphead = newnode;//
	}
	else 
	{
		while (cur->next != NULL) //让cur遍历到最后一个节点
		{
			cur = cur->next;
		}
		cur->next = newnode;//最后
	}

}

//单链表头插函数接口
void SListPushFront(SLNode** pphead, SLTDataType x) 
{
	assert(pphead);
	SLNode* newnode = BuySListNode(x);
	//
	SLNode* cur = *pphead;
	newnode->next = cur;
	*pphead = newnode;

}

现在我们来利用打印接口调试一下我们写的是否存在问题。 

在main.c中输入如下代码

void TestSListNode()
{
	SLNode* phead = NULL;
	SListPushBack(&phead, 1);
	SListPushBack(&phead, 2);
	SListPushBack(&phead, 3);
	SListPushBack(&phead, 4);
	SListPushBack(&phead, 5);
	SListPushFront(&phead, 0);




	SListPrint(phead);
	printf("\n");

	/*SListPopFront(&phead);
	SListPopFront(&phead);
	SListPopFront(&phead);
	SListPopBack(&phead);
	SListPrint(phead);
	printf("\n");

	SLTDestory(&phead);
	
	SListPrint(phead);
	printf("\n");*/

}

int main() 
{
//	TestTree();
//	TestStack();
//	TestQueue();
//	TestSeqList();
	TestSListNode();
//	TestDSLNode();
//	TestOJ();
	return 0;
}

运行图如下: 

线性表——单链表的增删查改-LMLPHP 通过检验,没有问题。 继续往下走。 

---------------------------------------------------------------------------------------------------------------------------------

 单链表尾删函数接口

.h文件声明

链表的增删查改///
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>

typedef int SLTDataType;

typedef struct SListNode 
{
	struct SListNode* next;
	SLTDataType data;
}SLNode;

//链表接口声明/

//申请链表节点函数接口
SLNode* BuySListNode(SLTDataType x);
//单链表的打印函数接口
void SListPrint(SLNode* phead);
//单链表尾插函数接口
void SListPushBack(SLNode** pphead, SLTDataType x);
//单链表头插函数接口
void SListPushFront(SLNode** pphead, SLTDataType x);
//单链表尾删函数接口
void SListPopBack(SLNode** pphead);

.c函数实现

代码实现

单链表函数实现函数接口

//单链表申请节点函数接口
SLNode* BuySListNode(SLTDataType x) 
{
	SLNode* NewNode = (SLNode*)malloc(sizeof(SLNode));
	if (NewNode == NULL) 
	{
		printf("申请节点失败\n");
		return;
	}
	//
	NewNode->data = x;
	NewNode->next = NULL;
}

//单链表的节点打印操作
void SListPrint(SLNode* phead) 
{
	SLNode* cur = phead;

	while (cur != NULL) 
	{
		printf("%d->", cur->data);
		cur = cur->next;
	}
	if (cur == NULL)//最后打印一个NULL
	{
		printf("NULL");
	}
	
}

//单链表尾插函数接口
void SListPushBack(SLNode** pphead, SLTDataType x) 
{
	assert(pphead);
	SLNode* newnode = BuySListNode(x);//利用申请节点函数申请节点

	SLNode* cur = *pphead; //让cur指向phead所指向空间
	if (cur == NULL) //cur == NULL代表着phead指向NULL, 这时候让phead改变指向。传送phead指针的原因就是
	{                                              //要改变phead的指向。
		*pphead = newnode;//
	}
	else 
	{
		while (cur->next != NULL) //让cur遍历到最后一个节点
		{
			cur = cur->next;
		}
		cur->next = newnode;//最后
	}

}

//单链表头插函数接口
void SListPushFront(SLNode** pphead, SLTDataType x) 
{
	assert(pphead);
	SLNode* newnode = BuySListNode(x);
	//
	SLNode* cur = *pphead;
	newnode->next = cur;
	*pphead = newnode;

}

//单链表尾删函数接口
void SListPopBack(SLNode** pphead) 
{
	assert(pphead);
	if (*pphead == NULL)
		return;
	//
	SLNode* cur = *pphead;
	SLNode* prev = *pphead;
	while (cur->next != NULL) //对链表进行遍历。 cur最终会指向尾节点。 prev用来维护链表
	{
		prev = cur;
		cur = cur->next;
	}
	if (prev == cur) 
	{
		free(cur);
		*pphead = NULL;
	}
	else 
	{
		free(cur);
		prev = NULL;
	}
	
}

---------------------------------------------------------------------------------------------------------------------------------

单链表的头删函数接口

.h函数声明

链表的增删查改///
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>

typedef int SLTDataType;

typedef struct SListNode 
{
	struct SListNode* next;
	SLTDataType data;
}SLNode;

//链表接口声明/

//申请链表节点函数接口
SLNode* BuySListNode(SLTDataType x);
//单链表的打印函数接口
void SListPrint(SLNode* phead);
//单链表尾插函数接口
void SListPushBack(SLNode** pphead, SLTDataType x);
//单链表头插函数接口
void SListPushFront(SLNode** pphead, SLTDataType x);
//单链表尾删函数接口
void SListPopBack(SLNode** pphead);
//单链表的头删函数接口
void SListPopFront(SLNode** pphead);

.c函数实现 

单链表函数实现函数接口

//单链表申请节点函数接口
SLNode* BuySListNode(SLTDataType x) 
{
	SLNode* NewNode = (SLNode*)malloc(sizeof(SLNode));
	if (NewNode == NULL) 
	{
		printf("申请节点失败\n");
		return;
	}
	//
	NewNode->data = x;
	NewNode->next = NULL;
}

//单链表的节点打印操作
void SListPrint(SLNode* phead) 
{
	SLNode* cur = phead;

	while (cur != NULL) 
	{
		printf("%d->", cur->data);
		cur = cur->next;
	}
	if (cur == NULL)//最后打印一个NULL
	{
		printf("NULL");
	}
	
}

//单链表尾插函数接口
void SListPushBack(SLNode** pphead, SLTDataType x) 
{
	assert(pphead);
	SLNode* newnode = BuySListNode(x);//利用申请节点函数申请节点

	SLNode* cur = *pphead; //让cur指向phead所指向空间
	if (cur == NULL) //cur == NULL代表着phead指向NULL, 这时候让phead改变指向。传送phead指针的原因就是
	{                                              //要改变phead的指向。
		*pphead = newnode;//
	}
	else 
	{
		while (cur->next != NULL) //让cur遍历到最后一个节点
		{
			cur = cur->next;
		}
		cur->next = newnode;//最后
	}

}

//单链表头插函数接口
void SListPushFront(SLNode** pphead, SLTDataType x) 
{
	assert(pphead);
	SLNode* newnode = BuySListNode(x);
	//
	SLNode* cur = *pphead;
	newnode->next = cur;
	*pphead = newnode;

}

//单链表尾删函数接口
void SListPopBack(SLNode** pphead) 
{
	assert(pphead);
	if (*pphead == NULL)
		return;
	//
	SLNode* cur = *pphead;
	SLNode* prev = *pphead;
	while (cur->next != NULL) //对链表进行遍历。 cur最终会指向尾节点。 prev用来维护链表
	{
		prev = cur;
		cur = cur->next;
	}
	if (prev == cur) 
	{
		free(cur);
		*pphead = NULL;
	}
	else 
	{
		free(cur);
		prev = NULL;
	}
	
}

//单链表的头删函数接口
void SListPopFront(SLNode** pphead) 
{
	assert(pphead);
	if (*pphead == NULL)
		return;
	//
	SLNode* cur = *pphead;
	*pphead = cur->next;
	free(cur);
}

---------------------------------------------------------------------------------------------------------------------------------

 单链表查找函数接口

.h接口声明

链表的增删查改///
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>

typedef int SLTDataType;

typedef struct SListNode 
{
	struct SListNode* next;
	SLTDataType data;
}SLNode;

//链表接口声明/

//申请链表节点函数接口
SLNode* BuySListNode(SLTDataType x);
//单链表的打印函数接口
void SListPrint(SLNode* phead);
//单链表尾插函数接口
void SListPushBack(SLNode** pphead, SLTDataType x);
//单链表头插函数接口
void SListPushFront(SLNode** pphead, SLTDataType x);
//单链表尾删函数接口
void SListPopBack(SLNode** pphead);
//单链表的头删函数接口
void SListPopFront(SLNode** pphead);
//单链表查找函数接口
SLNode* SListFind(SLNode* phead, SLTDataType x);

.c接口实现

单链表函数实现函数接口

//单链表申请节点函数接口
SLNode* BuySListNode(SLTDataType x) 
{
	SLNode* NewNode = (SLNode*)malloc(sizeof(SLNode));
	if (NewNode == NULL) 
	{
		printf("申请节点失败\n");
		return;
	}
	//
	NewNode->data = x;
	NewNode->next = NULL;
}

//单链表的节点打印操作
void SListPrint(SLNode* phead) 
{
	SLNode* cur = phead;

	while (cur != NULL) 
	{
		printf("%d->", cur->data);
		cur = cur->next;
	}
	if (cur == NULL)//最后打印一个NULL
	{
		printf("NULL");
	}
	
}

//单链表尾插函数接口
void SListPushBack(SLNode** pphead, SLTDataType x) 
{
	assert(pphead);
	SLNode* newnode = BuySListNode(x);//利用申请节点函数申请节点

	SLNode* cur = *pphead; //让cur指向phead所指向空间
	if (cur == NULL) //cur == NULL代表着phead指向NULL, 这时候让phead改变指向。传送phead指针的原因就是
	{                                              //要改变phead的指向。
		*pphead = newnode;//
	}
	else 
	{
		while (cur->next != NULL) //让cur遍历到最后一个节点
		{
			cur = cur->next;
		}
		cur->next = newnode;//最后
	}

}

//单链表头插函数接口
void SListPushFront(SLNode** pphead, SLTDataType x) 
{
	assert(pphead);
	SLNode* newnode = BuySListNode(x);
	//
	SLNode* cur = *pphead;
	newnode->next = cur;
	*pphead = newnode;

}

//单链表尾删函数接口
void SListPopBack(SLNode** pphead) 
{
	assert(pphead);
	if (*pphead == NULL)
		return;
	//
	SLNode* cur = *pphead;
	SLNode* prev = *pphead;
	while (cur->next != NULL) //对链表进行遍历。 cur最终会指向尾节点。 prev用来维护链表
	{
		prev = cur;
		cur = cur->next;
	}
	if (prev == cur) 
	{
		free(cur);
		*pphead = NULL;
	}
	else 
	{
		free(cur);
		prev = NULL;
	}
	
}

//单链表的头删函数接口
void SListPopFront(SLNode** pphead) 
{
	assert(pphead);
	if (*pphead == NULL)
		return;
	//
	SLNode* cur = *pphead;
	*pphead = cur->next;
	free(cur);
}


//单链表查找函数接口
SLNode* SListFind(SLNode* phead, SLTDataType x) 
{
	SLNode* cur = phead;//定义一个指向头节点的指针, 用于遍历
	while (cur != NULL) //向后遍历
	{
		if (cur->data == x) //找到节点后就返回节点的地址。
		{
			return cur;
		}
		cur = cur->next;
	}
	return NULL;
}

 代码太长, 之后.c文件的代码只展示相应接口的代码

---------------------------------------------------------------------------------------------------------------------------------

单链表pos位置之后插入数据接口

.h接口声明

链表的增删查改///
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>

typedef int SLTDataType;

typedef struct SListNode 
{
	struct SListNode* next;
	SLTDataType data;
}SLNode;

//链表接口声明/

//申请链表节点函数接口
SLNode* BuySListNode(SLTDataType x);
//单链表的打印函数接口
void SListPrint(SLNode* phead);
//单链表尾插函数接口
void SListPushBack(SLNode** pphead, SLTDataType x);
//单链表头插函数接口
void SListPushFront(SLNode** pphead, SLTDataType x);
//单链表尾删函数接口
void SListPopBack(SLNode** pphead);
//单链表的头删函数接口
void SListPopFront(SLNode** pphead);
//单链表查找函数接口
SLNode* SListFind(SLNode* phead, SLTDataType x);
//单链表在pos位置之后插入数据接口
void SListInsertAfter(SLNode* pos, SLTDataType x);

.c接口实现 


//单链表在pos位置之后插入数据接口
void SListInsertAfter(SLNode* pos, SLTDataType x) 
{
	assert(pos);
	SLNode* newnode = BuySListNode(x);
	//
	SLNode* cur = pos->next;
	newnode->next = cur;
	pos->next = newnode;
}

---------------------------------------------------------------------------------------------------------------------------------

单链表删除pos之后位置的数据

.h接口声明

链表的增删查改///
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>

typedef int SLTDataType;

typedef struct SListNode 
{
	struct SListNode* next;
	SLTDataType data;
}SLNode;

//链表接口声明/

//申请链表节点函数接口
SLNode* BuySListNode(SLTDataType x);
//单链表的打印函数接口
void SListPrint(SLNode* phead);
//单链表尾插函数接口
void SListPushBack(SLNode** pphead, SLTDataType x);
//单链表头插函数接口
void SListPushFront(SLNode** pphead, SLTDataType x);
//单链表尾删函数接口
void SListPopBack(SLNode** pphead);
//单链表的头删函数接口
void SListPopFront(SLNode** pphead);
//单链表查找函数接口
SLNode* SListFind(SLNode* phead, SLTDataType x);
//单链表在pos位置之后插入数据接口
void SListInsertAfter(SLNode* pos, SLTDataType x);
//单链表在pos之后的位置删除数据
void SListPopAfter(SLNode* pos);

.c接口实现


//单链表在pos之后的位置删除数据
void SListPopAfter(SLNode* pos) 
{
	assert(pos);
	//
	SLNode* cur = pos->next;
	pos->next = pos->next->next;
	free(cur);
}

---------------------------------------------------------------------------------------------------------------------------------

单链表在pos位置之前插入数据接口

.h接口声明

链表的增删查改///
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>

typedef int SLTDataType;

typedef struct SListNode 
{
	struct SListNode* next;
	SLTDataType data;
}SLNode;

//链表接口声明/

//申请链表节点函数接口
SLNode* BuySListNode(SLTDataType x);
//单链表的打印函数接口
void SListPrint(SLNode* phead);
//单链表尾插函数接口
void SListPushBack(SLNode** pphead, SLTDataType x);
//单链表头插函数接口
void SListPushFront(SLNode** pphead, SLTDataType x);
//单链表尾删函数接口
void SListPopBack(SLNode** pphead);
//单链表的头删函数接口
void SListPopFront(SLNode** pphead);
//单链表查找函数接口
SLNode* SListFind(SLNode* phead, SLTDataType x);
//单链表在pos位置之后插入数据接口
void SListInsertAfter(SLNode* pos, SLTDataType x);
//单链表在pos之后的位置删除数据
void SListPopAfter(SLNode* pos);
//单链表在pos位置之前插入数据接口
void SListInsert(SLNode** pphead, SLNode* pos, SLTDataType x);

.c接口实现


//单链表在pos位置之前插入数据接口
void SListInsert(SLNode** pphead, SLNode* pos, SLTDataType x) 
{
	assert(pphead);

	//
	SLNode* newnode = BuySListNode(x);
	//
	if (*pphead == NULL) 
	{
		*pphead = newnode;
		return;
	}
	//
	if (*pphead == pos) 
	{
		newnode->next = pos;
		*pphead = newnode;
		return;
	}
	SLNode* cur = *pphead;
	while (cur != NULL && cur->next != pos) 
	{
		cur = cur->next;
	}
	newnode->next = pos;
	cur->next = newnode;
}

---------------------------------------------------------------------------------------------------------------------------------

单链表删除pos位置数据接口

.h接口声明

链表的增删查改///
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>

typedef int SLTDataType;

typedef struct SListNode 
{
	struct SListNode* next;
	SLTDataType data;
}SLNode;

//链表接口声明/

//申请链表节点函数接口
SLNode* BuySListNode(SLTDataType x);
//单链表的打印函数接口
void SListPrint(SLNode* phead);
//单链表尾插函数接口
void SListPushBack(SLNode** pphead, SLTDataType x);
//单链表头插函数接口
void SListPushFront(SLNode** pphead, SLTDataType x);
//单链表尾删函数接口
void SListPopBack(SLNode** pphead);
//单链表的头删函数接口
void SListPopFront(SLNode** pphead);
//单链表查找函数接口
SLNode* SListFind(SLNode* phead, SLTDataType x);
//单链表在pos位置之后插入数据接口
void SListInsertAfter(SLNode* pos, SLTDataType x);
//单链表在pos之后的位置删除数据
void SListPopAfter(SLNode* pos);
//单链表在pos位置之前插入数据接口
void SListInsert(SLNode** pphead, SLNode* pos, SLTDataType x);
//单链表在pos位置删除数据接口
void SListPop(SLNode** pphead, SLNode* pos);

.c接口实现


//单链表在pos位置删除数据接口
void SListPop(SLNode** pphead, SLNode* pos) 
{
	assert(pphead);
	//
	if (*pphead == pos) 
	{
		*pphead = (*pphead)->next;
		free(pos);
	}
	else 
	{
		SLNode* cur = *pphead;
		while (cur->next != pos) 
		{
			cur->next = pos->next;
			free(pos);
		}
	}
}

单链表的销毁

.h接口声明

链表的增删查改///
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>

typedef int SLTDataType;

typedef struct SListNode 
{
	struct SListNode* next;
	SLTDataType data;
}SLNode;

//链表接口声明/

//申请链表节点函数接口
SLNode* BuySListNode(SLTDataType x);
//单链表的打印函数接口
void SListPrint(SLNode* phead);
//单链表尾插函数接口
void SListPushBack(SLNode** pphead, SLTDataType x);
//单链表头插函数接口
void SListPushFront(SLNode** pphead, SLTDataType x);
//单链表尾删函数接口
void SListPopBack(SLNode** pphead);
//单链表的头删函数接口
void SListPopFront(SLNode** pphead);
//单链表查找函数接口
SLNode* SListFind(SLNode* phead, SLTDataType x);
//单链表在pos位置之后插入数据接口
void SListInsertAfter(SLNode* pos, SLTDataType x);
//单链表在pos之后的位置删除数据
void SListPopAfter(SLNode* pos);
//单链表在pos位置之前插入数据接口
void SListInsert(SLNode** pphead, SLNode* pos, SLTDataType x);
//单链表在pos位置删除数据接口
void SListPop(SLNode** pphead, SLNode* pos);
//单链表的销毁函数接口
void SLTDestory(SLNode** pphead);

.c接口实现 


//单链表的销毁函数接口
void SLTDestory(SLNode** pphead) 
{
	assert(pphead);
	if (*pphead == NULL) 
	{
		return;
	}
	SLNode* prev = (*pphead);
	SLNode* cur = (*pphead)->next;
	if (cur == NULL) 
	{
		*pphead = NULL;
		free(prev);
	}
	else 
	{
		*pphead = NULL;
		while(cur != NULL)
		{
			free(prev);
			prev = cur;
			cur = cur->next;
		}
		free(prev);
	}

}

现在来看一下总体代码:

.h文件

链表的增删查改///
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>

typedef int SLTDataType;

typedef struct SListNode 
{
	struct SListNode* next;
	SLTDataType data;
}SLNode;

//链表接口声明/

//申请链表节点函数接口
SLNode* BuySListNode(SLTDataType x);
//单链表的打印函数接口
void SListPrint(SLNode* phead);
//单链表尾插函数接口
void SListPushBack(SLNode** pphead, SLTDataType x);
//单链表头插函数接口
void SListPushFront(SLNode** pphead, SLTDataType x);
//单链表尾删函数接口
void SListPopBack(SLNode** pphead);
//单链表的头删函数接口
void SListPopFront(SLNode** pphead);
//单链表查找函数接口
SLNode* SListFind(SLNode* phead, SLTDataType x);
//单链表在pos位置之后插入数据接口
void SListInsertAfter(SLNode* pos, SLTDataType x);
//单链表在pos之后的位置删除数据
void SListPopAfter(SLNode* pos);
//单链表在pos位置之前插入数据接口
void SListInsert(SLNode** pphead, SLNode* pos, SLTDataType x);
//单链表在pos位置删除数据接口
void SListPop(SLNode** pphead, SLNode* pos);
//单链表的销毁函数接口
void SLTDestory(SLNode** pphead);

.c文件

单链表函数实现函数接口

//单链表申请节点函数接口
SLNode* BuySListNode(SLTDataType x) 
{
	SLNode* NewNode = (SLNode*)malloc(sizeof(SLNode));
	if (NewNode == NULL) 
	{
		printf("申请节点失败\n");
		return;
	}
	//
	NewNode->data = x;
	NewNode->next = NULL;
}

//单链表的节点打印操作
void SListPrint(SLNode* phead) 
{
	SLNode* cur = phead;

	while (cur != NULL) 
	{
		printf("%d->", cur->data);
		cur = cur->next;
	}
	if (cur == NULL)//最后打印一个NULL
	{
		printf("NULL");
	}
	
}

//单链表尾插函数接口
void SListPushBack(SLNode** pphead, SLTDataType x) 
{
	assert(pphead);
	SLNode* newnode = BuySListNode(x);//利用申请节点函数申请节点

	SLNode* cur = *pphead; //让cur指向phead所指向空间
	if (cur == NULL) //cur == NULL代表着phead指向NULL, 这时候让phead改变指向。传送phead指针的原因就是
	{                                              //要改变phead的指向。
		*pphead = newnode;//
	}
	else 
	{
		while (cur->next != NULL) //让cur遍历到最后一个节点
		{
			cur = cur->next;
		}
		cur->next = newnode;//最后
	}

}

//单链表头插函数接口
void SListPushFront(SLNode** pphead, SLTDataType x) 
{
	assert(pphead);
	SLNode* newnode = BuySListNode(x);
	//
	SLNode* cur = *pphead;
	newnode->next = cur;
	*pphead = newnode;

}

//单链表尾删函数接口
void SListPopBack(SLNode** pphead) 
{
	assert(pphead);
	if (*pphead == NULL)
		return;
	//
	SLNode* cur = *pphead;
	SLNode* prev = *pphead;
	while (cur->next != NULL) //对链表进行遍历。 cur最终会指向尾节点。 prev用来维护链表
	{
		prev = cur;
		cur = cur->next;
	}
	if (prev == cur) 
	{
		free(cur);
		*pphead = NULL;
	}
	else 
	{
		free(cur);
		prev = NULL;
	}
	
}

//单链表的头删函数接口
void SListPopFront(SLNode** pphead) 
{
	assert(pphead);
	if (*pphead == NULL)
		return;
	//
	SLNode* cur = *pphead;
	*pphead = cur->next;
	free(cur);
}


//单链表查找函数接口
SLNode* SListFind(SLNode* phead, SLTDataType x) 
{
	SLNode* cur = phead;//定义一个指向头节点的指针, 用于遍历
	while (cur != NULL) //向后遍历
	{
		if (cur->data == x) //找到节点后就返回节点的地址。
		{
			return cur;
		}
		cur = cur->next;
	}
	return NULL;
}

//单链表在pos位置之后插入数据接口
void SListInsertAfter(SLNode* pos, SLTDataType x) 
{
	assert(pos);
	SLNode* newnode = BuySListNode(x);
	//
	SLNode* cur = pos->next;
	newnode->next = cur;
	pos->next = newnode;
}


//单链表在pos之后的位置删除数据
void SListPopAfter(SLNode* pos) 
{
	assert(pos);
	//
	SLNode* cur = pos->next;
	pos->next = pos->next->next;
	free(cur);
}

//单链表在pos位置之前插入数据接口
void SListInsert(SLNode** pphead, SLNode* pos, SLTDataType x) 
{
	assert(pphead);

	//
	SLNode* newnode = BuySListNode(x);
	//
	if (*pphead == NULL) 
	{
		*pphead = newnode;
		return;
	}
	//
	if (*pphead == pos) 
	{
		newnode->next = pos;
		*pphead = newnode;
		return;
	}
	SLNode* cur = *pphead;
	while (cur != NULL && cur->next != pos) 
	{
		cur = cur->next;
	}
	newnode->next = pos;
	cur->next = newnode;
}

//单链表在pos位置删除数据接口
void SListPop(SLNode** pphead, SLNode* pos) 
{
	assert(pphead);
	//
	if (*pphead == pos) 
	{
		*pphead = (*pphead)->next;
		free(pos);
	}
	else 
	{
		SLNode* cur = *pphead;
		while (cur->next != pos) 
		{
			cur->next = pos->next;
			free(pos);
		}
	}
}

//单链表的销毁函数接口
void SLTDestory(SLNode** pphead) 
{
	assert(pphead);
	if (*pphead == NULL) 
	{
		return;
	}
	SLNode* prev = (*pphead);
	SLNode* cur = (*pphead)->next;
	if (cur == NULL) 
	{
		*pphead = NULL;
		free(prev);
	}
	else 
	{
		*pphead = NULL;
		while(cur != NULL)
		{
			free(prev);
			prev = cur;
			cur = cur->next;
		}
		free(prev);
	}

}
03-29 04:49