c语言 链表基本操作

 对于c语言的单链表来说,应该是数据结构中比较简单的一类结构,我们只要认识链表结构,对指针和结构体掌握好,其实编写代码并不算太难。

链表结构:

c语言 链表基本操作_第1张图片

 对于链表中的每一个结点,我们可以定义如下的结构体:

c语言 链表基本操作_第2张图片

 基本操作:

1.创造结点:

c语言 链表基本操作_第3张图片

 为新节点newnode动态开辟一块空间,结点值为x,指针域指向NULL

2.头插结点:

c语言 链表基本操作_第4张图片

 在进行头插元素的时候,第一步和第二步不能进行交换,如果先进pre->next=s,此时pre->next指向了s,在进行s->next=pre->next,就会使s->next指向自己本身,无法达到预期效果

c语言 链表基本操作_第5张图片

3.头删结点:

c语言 链表基本操作_第6张图片 直接将头指针指向原来指向的下一个位置,即pplist->next=cur->next

4.尾插:

c语言 链表基本操作_第7张图片

 当链表为空时,直接将pplist指针指向这个新结点即可;当链表不为空时,则需循环遍历链表,找到链表中最后一个结点,然后将其的next域指向新节点,即cur->next=newnode,此时,不需要将新节点的next域赋值为空,因为在创建结点函数中已将next域赋值为空

5.尾删:
c语言 链表基本操作_第8张图片

 c语言 链表基本操作_第9张图片

当链表中只有一个结点时候,直接将其free掉;当链表中有多个结点时,用俩个指针依次向后遍历,直到快指针的next为空,此时慢指针指向链表中倒数第二个节点,直接将其指向空即可。

5.任意位置后插入元素:

c语言 链表基本操作_第10张图片

 给定一个位置pos,在其后面插入新节点,这种情况与头插法类似,只是在链表中间进行头插,只需要按照头插法的方法即可。

6.任意位置后删除元素:

c语言 链表基本操作_第11张图片

 对于这种情况,同样是给定一个位置,如果此位置为空或者它的next为空,则无法删除,直接返回;如果给定位置正常,则直接将给定位置的next指向,给定位置的next的next。

c语言 链表基本操作_第12张图片

 7.查找元素:

c语言 链表基本操作_第13张图片

在查找元素的时候,只需遍历一遍链表,找到链表当中值与要查找的值相同的结点,并返回(注意,链表中各节点值不相同)。

完整代码: 

SList.h

#pragma once
typedef int DateType;
typedef struct SListNode
{
	DateType data;
	struct SListNode* next;
}SListNode;

// 动态申请一个结点
SListNode* BuySListNode(DateType x);
// 单链表打印
void SListPrint(SListNode* plist);
// 单链表尾插
void SListPushBack(SListNode** pplist, DateType x);
// 单链表的头插
void SListPushFront(SListNode** pplist, DateType x);
// 单链表的尾删
void SListPopBack(SListNode** pplist);
// 单链表头删
void SListPopFront(SListNode** pplist);
// 单链表查找
SListNode* SListFind(SListNode* plist, DateType x); 
// 单链表在pos位置之后插入x
SListNode* SListInsertAfter(SListNode* pos, DateType x);
// 单链表删除pos位置之后的值
SListNode* SListEraseAfter(SListNode* pos);
//销毁单链表
void SListDestory(SListNode** pplist);
//统计链表元素个数
int SListSize(SListNode* plist);

void Test();
SList.c

#include"SList.h"
#include
#include
#include

//创造结点
SListNode* BuySListNode(DateType x)
{
	SListNode* newnode = (SListNode*)malloc(sizeof(SListNode));
	if (newnode == NULL)
	{
		exit(0);
	}
	newnode->data = x;
	newnode->next = NULL;
	return newnode;
}
//尾插
void SListPushBack(SListNode** pplist, DateType x)
{
	assert(pplist != NULL);
	if (NULL == *pplist)
	{
		*pplist = BuySListNode(x);
	}
	else
	{
		// pplist的链表不为空
		// 1. 找到原链表中的最后一个节点
		SListNode* cur = *pplist;
		while (cur->next)
		{
			cur = cur->next;
		}

		// 2. 插入新节点
		cur->next = BuySListNode(x);
	}
}
//尾删
void SListPopBack(SListNode** pplist)
{
	assert(pplist != NULL);

	//1.链表中午结点
	if (NULL == *pplist)
		return;
	else if (NULL == (*pplist)->next)
	{
		// 2. 链表中只有一个节点
		free(*pplist);
		*pplist = NULL;
	}
	else
	{
		// 3. 链表中有多个节点(至少是2个)
		// a. 找到最后一个节点并保存其前一个节点
		SListNode* cur = *pplist;
		SListNode* prev = NULL;   // 保存cur的前一个节点
		while (cur->next)
		{
			prev = cur;
			cur = cur->next;
		}

		// cur是最后一个节点   prev刚好是cur的前一个
		free(cur);
		prev->next = NULL;

		/*
		   方法二:
		   1. 找到链表倒数第二个节点
		   while(cur->next->next)
		   {
			   cur = cur->next;
		   }

		   // 2. 删除最后一个节点;cur刚好是最后一个节点的前一个节点
		   free(cur->nexr);
		   cur->next = NULL;
		*/
	}

}
//头插
void SListPushFront(SListNode** pplist, DateType x)
{
	assert(pplist != NULL);

	//创造一个新结点
	SListNode* newnode = BuySListNode(x);
	newnode->next = *pplist;
	*pplist = newnode;

}
//头删
void SListPopFront(SListNode** pplist)
{
	assert(pplist != NULL);
	if (*pplist == NULL)
	{
		printf("链表为空!!!\n");
		return;
	}
	else
	{
		SListNode* cur = *pplist;
		*pplist = cur->next;
		free(cur);
		cur = NULL;
	}
}
SListNode* SListInsertAfter(SListNode* pos, DateType x)
{
	if (pos)
	{
		return;
	}
	SListNode* newnode = BuySListNode(x);
	newnode->next = pos->next;
	pos->next = newnode;
}
SListNode* SListEraseAfter(SListNode* pos)
{
	if (pos||pos->next)
	{
		return;
	}
	SListNode* p = pos->next;
	pos->next = p->next;
	free(p);
	p = NULL;
}
//查找元素
SListNode* SListFind(SListNode* plist, DateType x)
{
	SListNode* cur = plist;
	while (cur)
	{
		if (cur->data == x)
		{
			return cur;
		}
		cur = cur->next;
	}
	return NULL;
}
//统计链表的元素个数
int SListSize(SListNode* plist)
{
	SListNode* cur = plist;
	int count = 0;
	while (cur)
	{
		count++;
		cur = cur->next;
	}
	return count;
}
//销毁链表
void SListDestory(SListNode** pplist)
{
	assert(pplist != NULL);
	SListNode* cur = *pplist;
	while (cur)
	{
		*pplist = cur->next;
		free(cur);
		cur = *pplist;
	}
	*pplist = NULL;
}
//打印单链表
void SListPrint(SListNode* plist)
{
	SListNode* p = plist;
	while (p != NULL)
	{
		printf("%d---->", p->data);
		p = p->next;
	}
	printf("NULL\n");
}

void Test()
{
	SListNode* s =NULL;
	SListPushBack(&s,1);
	SListPushBack(&s, 2);
	SListPushBack(&s, 3);
	SListPushBack(&s, 4);
	SListPushBack(&s, 5);

    SListPopBack(&s);
	SListPushFront(&s, 4);
	SListPushFront(&s, 3);
	SListPushFront(&s, 2);
	SListPushFront(&s, 1);

	SListPrint(s);
	int num=SListSize(s);
	printf("\nnum=%d\n", num);
	SListDestory(&s);
}
SList_Main.c

#include"SList.h"

int main()
{
	Test();
	return 0;
}

 

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