【C数据结构】单链表补充

目录

      • 上章代码
      • 查找结点:
      • 任意结点前面插入结点
      • 任意结点后面插入结点
      • 删除任意结点
      • 删除任意结点的后一个结点
      • 完整代码(包含上章节)

下面是上章的代码:

上章代码

#define _CRT_SECURE_NO_WARNINGS 1
#include
#include
#include
typedef int SLTDateType;
typedef struct SListNode
{
	SLTDateType date;
	struct SListNode* next;
}SLTNode;
void SLNInit(SLTNode* a)
{
	SLTNode* ps = a;
	for (ps;ps != NULL;ps=ps->next) {
		ps->date = 1;
	}
}
void SLPrint(SLTNode* b)
{
	SLTNode* phead = b;
	while (phead != NULL)
	{
		printf("%d ", phead->date);
		phead = phead->next;
	}
	printf("\n");
}
//尾插
void SLPushBack(SLTNode** phead, SLTDateType x)
{
	SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));
	newnode->date = x;
	newnode->next = NULL;
	if (*phead == NULL)
		*phead = newnode;
	else
	{
		SLTNode* crr = *phead;
		while (crr->next != NULL)
		{
			crr = crr->next;
		}
		crr->next = newnode;
	}
}

//头插
void SLPushFront(SLTNode** pphead, SLTDateType x)
{
	SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));
	newnode->date = x;
	newnode->next = NULL;
	if (*pphead == NULL)
		*pphead = newnode;
	else
	{
		newnode->next = *pphead;
		*pphead = newnode;
	}
}

//头删
void SLPopFront(SLTNode** pphead)
{
	//没有结点:
	assert(*pphead);
	//只有一个结点时
	if ((*pphead)->next == NULL)
	{
		free(*pphead);
		*pphead = NULL;
	}
	//多个结点时:
	else
	{
		SLTNode* first = *pphead;
		*pphead = first->next;
		free(first);
		first = NULL;
	}
}
//尾删:
void SLPopBack(SLTNode* phead)
{
	//没有结点时:
	assert(phead);
	//只有一个结点时:
	if (phead->next == NULL)
	{
		free(phead);
		phead = NULL;
	}
	//有多个结点时:
	SLTNode* end = phead;
	SLTNode* pre = NULL;
	//找到尾结点:
	while (end->next != NULL)
	{
		pre = end;
		end = end->next;
	}
	free(end);
	pre->next = NULL;
}

//测试尾插
void TextSListNode()
{
	SListNode* phead = NULL;
	SLPushBack(&phead, 1);
	SLPushBack(&phead, 2);
	SLPushBack(&phead, 3);
	SLPushBack(&phead, 4);
	SLPushBack(&phead, 5);
	SLPrint(phead);

}

//测试尾插和头删
void TextSListNode1()
{
	SListNode* phead = NULL;
	SLPushBack(&phead, 1);
	SLPushBack(&phead, 2);
	SLPushBack(&phead, 3);
	SLPushBack(&phead, 4);
	SLPushBack(&phead, 5);
	SLPrint(phead);
	SLPopFront(&phead);
	SLPrint(phead);
	SLPopFront(&phead);
	SLPrint(phead);
	SLPopFront(&phead);
	SLPrint(phead);
	SLPopFront(&phead);
	SLPrint(phead);
	SLPopFront(&phead);
	SLPrint(phead);
}

//测试头插和尾删
void TextSListNode2()
{
	SListNode* phead = NULL;
	SLPushFront(&phead, 5);
	SLPushFront(&phead, 4);
	SLPushFront(&phead, 3);
	SLPushFront(&phead, 2);
	SLPushFront(&phead, 1);
	SLPrint(phead);
	SLPopBack(phead);
	SLPrint(phead);
	SLPopBack(phead);
	SLPrint(phead);
	SLPopBack(phead);
	SLPrint(phead);
	SLPopBack(phead);
	SLPrint(phead);
}
int main()
{
	
	return 0;
}

接下来实现链表的查找和在任意位置增加和删除结点:

查找结点:

//查找
SLTNode* SListFind(SLTNode* plist,  SLTDateType x)
{
	SLTNode* cur = plist;
	while (cur)
	{
		if (cur->date == x)
			return cur;
		else
			cur = cur->next;
	}
	return NULL;
}

紧接着实现链表的在任意位置增加和删除结点:
首先定义一个动态开辟一个新结点的函数,方便之后代码的实现:

SLTNode* BuySListNode(SLTDateType x)
{
	SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));
	newnode->date = x;
	newnode->next = NULL;
	return newnode;
}

先实现在任意结点前面插入结点:

任意结点前面插入结点

void SListInsert(SLTNode* phead, SLTNode* pos, SLTDateType x)
{
	if (pos == phead)
	{
		SLPushFront(&phead, x);
	}
	else
	{
		SLTNode* prve = phead;
		SLTNode* dst = phead;
		while (dst)
		{
			if (dst == pos)
			{
				SLTNode* newnode = BuySListNode(x);
				newnode->next = prve->next;
				prve->next = newnode;
				break;
			}
			else
			{
				prve = dst;
				dst = dst->next;
			}
		}
	}
}

在任意结点后面插入结点

任意结点后面插入结点

void SListInsertAfter(SLTNode* pos, SLTDateType x)
{
	SLTNode* newnode = BuySListNode(x);
	newnode->next = pos->next;
	pos->next = newnode;
}

删除任意结点

void SLTErase(SLTNode* phead, SLTNode* pos)
{
	if (pos == phead)
	{
		SLPopFront(&phead);
	}
	else
	{
		SLTNode* prve = phead;
		while (prve)
		{
			if (prve->next == pos)
			{
				prve->next = pos->next;
				free(pos);
				break;
			}
			else
			{
				prve = prve->next;
			}
		}
	}
}

删除任意结点的后一个结点

void SLTEraseAfter( SLTNode* pos)
{
	SLTNode* cur = pos->next;
	pos->next = pos->next->next;
	free(cur);
}

可以看到,在链表结点的后面插入和删除结点是比较容易的。
我们也可以像上章一样对所写代码进行测试,下面是整个的完整代码:

完整代码(包含上章节)

#define _CRT_SECURE_NO_WARNINGS 1
#include
#include
#include
typedef int SLTDateType;
typedef struct SListNode
{
	SLTDateType date;
	struct SListNode* next;
}SLTNode;
void SLNInit(SLTNode* a)
{
	SLTNode* ps = a;
	for (ps;ps != NULL;ps=ps->next) {
		ps->date = 1;
	}
}
void SLPrint(SLTNode* b)
{
	SLTNode* phead = b;
	while (phead != NULL)
	{
		printf("%d ", phead->date);
		phead = phead->next;
	}
	printf("\n");
}
//尾插
void SLPushBack(SLTNode** phead, SLTDateType x)
{
	SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));
	newnode->date = x;
	newnode->next = NULL;
	if (*phead == NULL)
		*phead = newnode;
	else
	{
		SLTNode* crr = *phead;
		while (crr->next != NULL)
		{
			crr = crr->next;
		}
		crr->next = newnode;
	}
}

//头插
void SLPushFront(SLTNode** pphead, SLTDateType x)
{
	SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));
	newnode->date = x;
	newnode->next = NULL;
	if (*pphead == NULL)
		*pphead = newnode;
	else
	{
		newnode->next = *pphead;
		*pphead = newnode;
	}
}

//头删
void SLPopFront(SLTNode** pphead)
{
	//没有结点:
	assert(*pphead);
	//只有一个结点时
	if ((*pphead)->next == NULL)
	{
		free(*pphead);
		*pphead = NULL;
	}
	//多个结点时:
	else
	{
		SLTNode* first = *pphead;
		*pphead = first->next;
		free(first);
		first = NULL;
	}
}
//尾删:
void SLPopBack(SLTNode* phead)
{
	//没有结点时:
	assert(phead);
	//只有一个结点时:
	if (phead->next == NULL)
	{
		free(phead);
		phead = NULL;
	}
	//有多个结点时:
	SLTNode* end = phead;
	SLTNode* pre = NULL;
	//找到尾结点:
	while (end->next != NULL)
	{
		pre = end;
		end = end->next;
	}
	free(end);
	pre->next = NULL;
}

SLTNode* BuySListNode(SLTDateType x)
{
	SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));
	newnode->date = x;
	newnode->next = NULL;
	return newnode;
}
//查找
SLTNode* SListFind(SLTNode* plist,  SLTDateType x)
{
	SLTNode* cur = plist;
	while (cur)
	{
		if (cur->date == x)
			return cur;
		else
			cur = cur->next;
	}
	return NULL;
}

//在任意结点前面插入结点
void SListInsert(SLTNode* phead, SLTNode* pos, SLTDateType x)
{
	if (pos == phead)
	{
		SLPushFront(&phead, x);
	}
	else
	{
		SLTNode* prve = phead;
		SLTNode* dst = phead;
		while (dst)
		{
			if (dst == pos)
			{
				SLTNode* newnode = BuySListNode(x);
				newnode->next = prve->next;
				prve->next = newnode;
				break;
			}
			else
			{
				prve = dst;
				dst = dst->next;
			}
		}
	}
}

//在任意结点后面插入结点
void SListInsertAfter(SLTNode* pos, SLTDateType x)
{
	SLTNode* newnode = BuySListNode(x);
	newnode->next = pos->next;
	pos->next = newnode;
}

//删除任意结点
void SLTErase(SLTNode* phead, SLTNode* pos)
{
	if (pos == phead)
	{
		SLPopFront(&phead);
	}
	else
	{
		SLTNode* prve = phead;
		while (prve)
		{
			if (prve->next == pos)
			{
				prve->next = pos->next;
				free(pos);
				break;
			}
			else
			{
				prve = prve->next;
			}
		}
	}
}

//删除任意结点的后一个结点
void SLTEraseAfter( SLTNode* pos)
{
	SLTNode* cur = pos->next;
	pos->next = pos->next->next;
	free(cur);
}


//测试尾插
void TextSListNode()
{
	SListNode* phead = NULL;
	SLPushBack(&phead, 1);
	SLPushBack(&phead, 2);
	SLPushBack(&phead, 3);
	SLPushBack(&phead, 4);
	SLPushBack(&phead, 5);
	SLPrint(phead);

}

//测试尾插和头删
void TextSListNode1()
{
	SListNode* phead = NULL;
	SLPushBack(&phead, 1);
	SLPushBack(&phead, 2);
	SLPushBack(&phead, 3);
	SLPushBack(&phead, 4);
	SLPushBack(&phead, 5);
	SLPrint(phead);
	SLPopFront(&phead);
	SLPrint(phead);
	SLPopFront(&phead);
	SLPrint(phead);
	SLPopFront(&phead);
	SLPrint(phead);
	SLPopFront(&phead);
	SLPrint(phead);
	SLPopFront(&phead);
	SLPrint(phead);
}

//测试头插和尾删
void TextSListNode2()
{
	SListNode* phead = NULL;
	SLPushFront(&phead, 5);
	SLPushFront(&phead, 4);
	SLPushFront(&phead, 3);
	SLPushFront(&phead, 2);
	SLPushFront(&phead, 1);
	SLPrint(phead);
	SLPopBack(phead);
	SLPrint(phead);
	SLPopBack(phead);
	SLPrint(phead);
	SLPopBack(phead);
	SLPrint(phead);
	SLPopBack(phead);
	SLPrint(phead);
}


//测试查找:
void TextSListNode3()
{
	SListNode* phead = NULL;
	SLPushBack(&phead, 1);
	SLPushBack(&phead, 2);
	SLPushBack(&phead, 3);
	SLPushBack(&phead, 4);
	SLPushBack(&phead, 5);
	SLPrint(phead);
	//找到值为3的结点并修改值为6
	SLTNode* dst = SListFind(phead, 2);
	dst->date = 6;
	SLPrint(phead);
}
//测试在任意结点前面增加结点
void TextSListNode4()
{
	SListNode* phead = NULL;
	SLPushBack(&phead, 1);
	SLPushBack(&phead, 2);
	SLPushBack(&phead, 3);
	SLPushBack(&phead, 4);
	SLPushBack(&phead, 5);
	SLPrint(phead);
	//找到值为3的结点并修改值为6
	SLTNode* dst = SListFind(phead, 2);
	//在值为2的结点前面添加一个值为6的结点:
	SListInsert(phead, dst, 6);
	SLPrint(phead);
}
//测试删除任意结点:
void TextSListNode5()
{
	SListNode* phead = NULL;
	SLPushBack(&phead, 1);
	SLPushBack(&phead, 2);
	SLPushBack(&phead, 3);
	SLPushBack(&phead, 4);
	SLPushBack(&phead, 5);
	SLPrint(phead);
	//找到值为3的结点并修改值为6
	SLTNode* dst = SListFind(phead, 2);
	//在值为2的结点前面添加一个值为6的结点:
	SListInsert(phead, dst, 6);
	SLPrint(phead);
	SLTNode* dst1 = SListFind(phead, 4);
	SLTErase(phead, dst1);
	SLPrint(phead);
}
//测试在任意结点后面插入结点
void TextSListNode6()
{
	SListNode* phead = NULL;
	SLPushBack(&phead, 1);
	SLPushBack(&phead, 2);
	SLPushBack(&phead, 3);
	SLPushBack(&phead, 4);
	SLPushBack(&phead, 5);
	SLPrint(phead);
	//找到值为3的结点并修改值为6
	SLTNode* dst = SListFind(phead, 2);
	//在值为2的结点前面添加一个值为6的结点:
	SListInsert(phead, dst, 6);
	SLPrint(phead);
	SLTNode* dst1 = SListFind(phead, 4);
	SLPrint(phead);
	SListInsertAfter(dst, 20);
	SLPrint(phead);
	SListInsertAfter(dst1, 40);
	SLPrint(phead);
}


//测试删除任意结点后面的结点
void TextSListNode7()
{
	SListNode* phead = NULL;
	SLPushBack(&phead, 1);
	SLPushBack(&phead, 2);
	SLPushBack(&phead, 3);
	SLPushBack(&phead, 4);
	SLPushBack(&phead, 5);
	SLPrint(phead);
	//找到值为3的结点并修改值为6
	SLTNode* dst = SListFind(phead, 2);
	//在值为2的结点前面添加一个值为6的结点:
	SListInsert(phead, dst, 6);
	SLPrint(phead);
	SLTNode* dst1 = SListFind(phead, 4);
	SLPrint(phead);
	SListInsertAfter(dst, 20);
	SLPrint(phead);
	SListInsertAfter(dst1, 40);
	SLPrint(phead);
	SLTEraseAfter(dst);
	SLPrint(phead);
	SLTEraseAfter(dst1);
	SLPrint(phead);
}
int main()
{
	TextSListNode7();
	return 0;
}

小小三百行不成敬意,有错误的地方还请大佬指正:


你可能感兴趣的:(c语言,数据结构,链表,算法)