C语言实现单链表的初始化、增删查改基本操作)

C语言实现单链表的初始化、增删查改基本操作

引言

定义

★★★单链表是线性表的链式存取的数据结构,用一组地址任意的存储单元存放线性表中的数据。

原理

<1> 链表中的数据是以结点来表示的,结点的构成:数据域+指针域。
<2> 数据域即是存储数据的存储单元,指针域即是存储后继结点的地址。

优点

<1> 单链表在插入或删除元素时,只需要改变它的前驱元素及插入或删除元素的指向。
<2> 在存储数据数量未知的情况下,单链表是每存储一个数据才开辟一个空间,因此,可以很好的把握空间,浪费不会那么明显。

缺点

<1> 单链表不支持随机访问,故查找效率较慢。
<2> 在存取数据数量已知的情况下,由于单链表的每个数据还包含有指针域,因此空间浪费比较严重。并且,单链表的吗,每个数据地址是随机开辟的,因此,会导致存储空间出现七零八碎的情况,出现很多小的碎片空间。

比较

点击下方链接可以参考上期文章,进行单链表和顺序表的比较。
链接: ★★★ link.

时间上

<1> 顺序表的结构就像是数组一样,可以用下标来访问它的元素,所以顺序表的数据支持随机访问的;相比之下,单链表的数据是链式存储的,它的元素是不支持随机访问的,想要知道某个元素,只能从头结点开始遍历整个链表,知道找到了该元素为止。因此,顺序表访问随机元素的时间复杂度是O(1),而单链表访问随机元素的平均时间复杂度是O(n)。

<2> 顺序表的元素是连续存储的,因此,要在特定位置插入、删除元素需要把它之后的元素全部后移或前移一个元素的位置,时间开销很大;而单链表在插入或删除元素时,只需要改变它的前驱元素及插入或删除元素的指向即可。因此,顺序表在插入随机位置插入、删除元素的平均时间复杂度是O(n),单链表在随机位置插入、删除元素的时间复杂度是O(1)

空间上

<1> 顺序表的空间一般是连续开辟的,而且一次会开辟存储多个元素的空间,所以在使用顺序表时,可以一次把多个数据写入高速缓存,再写入主存,顺序表的CPU高速缓存效率更高,且CPU流水线也不会总是被打断;而单链表是每需要存储一个数据才开辟一次空间,所以每个数据存储时都要单独的写入高速缓存区,再写入主存,这样就造成了单链表CPU高速缓存效率低,且CPU流水线会经常被打断。

<2> 数据数量是否已知也会影响单链表和顺序表的选择使用。根据上述优缺点可以陈述这一观点。

实验过程及结果

代码

//<库函数>
#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
#include<math.h>

//<相关参数的宏定义>
#define Len sizeof(Node)

typedef int Elemtype;

typedef struct Node
{
    
    
	Elemtype data;
	struct Node* next;
}Node;

typedef struct Node Linklist;

//<单链表的初始化、增删查改、输出函数的定义>
Linklist* Creat_L();
void Out_Linklist(Linklist *h);
void Insert_List(Linklist *L,int i,Elemtype x);
void Delete_List(Linklist *L,int i);
void Found_List(Linklist *L,Elemtype x);
void Amend_List(Linklist *L,int i,Elemtype x);

// <主函数>
void main()
{
    
    
	Linklist *L;
	int k ;
	int i ;
	Elemtype x;

	printf("		《 Welcome to use the founction 》\n");
	printf("	    The founction can offer following service\n");
	printf("		*******Please first Initlist*******\n\n");
	printf("		1、Initlist   ->初始化单链表\n");
	printf("		2、Insertlist ->插入操作\n");
	printf("		3、Deletelist ->删除操作\n");
	printf("		4、Foundlist  ->查找操作\n");
	printf("		5、Amendlist  ->更改操作\n");
	printf("		0、Exitlist   ->退出操作\n\n\n");
	printf("        Please choose following digital:1、2、3、4、5、0\n");
	printf("               Finish your idea!!!!!!\n");
	do
	{
    
    
		printf("\n\nPlease Input your choice:");
		scanf("%d",&k);
		switch(k)
		{
    
    
		case 1:
			{
    
    
				L = Creat_L(); 
				Out_Linklist(L);
			}break;
		case 2:
			{
    
    
				printf("Input the position of Insert:");
				scanf("%d",&i);
				printf("Input the data of Insert:");
				scanf("%d",&x);
				Insert_List(L,i,x);
				Out_Linklist(L);
			}break;
		case 3:
			{
    
    
				printf("Input the position of Delete:");
				scanf("%d",&i);
				Delete_List(L,i);
				Out_Linklist(L);
			}break;
		case 4:
			{
    
    
				printf("Input the data of Found:");
				scanf("%d",&x);
				Found_List(L,x);
				//Out_Linklist(L);
			}break;
		case 5:
			{
    
    
				printf("Input the position of Amend:");
				scanf("%d",&i);
				printf("Amend data to:");
				scanf("%d",&x);
				Amend_List(L,i,x);
				Out_Linklist(L);
			}break;
		}
	}while(k!=0);
}

// <初始化函数>
Linklist* Creat_L()
{
    
    
	//int i;
	Linklist *h,*p,*s;
	Elemtype x;
	h = (Node*)malloc(Len);
	h->next = NULL;	
	p = h;
	printf("Please Enter the FIRST Node data: ");
	scanf("%d",&x);
	while(x!=99)                              //假设终止条件
	{
    
    
		s = (Node*)malloc(Len);	
		s->data = x;                          //赋值		
		s->next = NULL;
		p->next = s;
		p = s;	
		printf("Please Enter the NEXT  Node data: ");
		scanf("%d",&x);
	}
	return h;
}

//<输出函数>
void Out_Linklist(Linklist *h)
{
    
    
	Linklist *p;
	p  = h->next;
	printf("Output Linklist:");
	while(p)
	{
    
    
		if(p->next!=NULL)
		{
    
    
			printf("%d -> ",p->data);
			p = p->next;
		}
		else
		{
    
    
			printf("%d",p->data);
			p = p->next;
		}
	}
}

//<插入函数>
void Insert_List(Linklist *L,int i,Elemtype x)
{
    
    
	int j;
	Linklist *p,*s;
	p = L;

	if(i<0)
	{
    
    
		printf("The position is unreasonable!!!!!!!!!\n");
		printf("Please Input Again!!!!!!!\n");
		exit(0);
	}

	for(j=0;j<=i;j++)
	{
    
    
		if(j == i)
		{
    
    
			s = (Node*)malloc(Len);      //声明一个新节点 s ,并填充相关数据,插入链表
			s->data = x;
			s->next = p->next;
			p->next = s;
			break;
		}
		p = p->next;
	}
}

// <删除函数>
void Delete_List(Linklist *L,int i)
{
    
    
	Linklist *p,*s;
	int j;
	Elemtype x;

	p = L;

	if(i<0||p->next == NULL)
	{
    
    
		printf("The position is unreasonable!!!!!!!!!\n");
		printf("Please Input Again!!!!!!!\n");
		exit(0);
	}
	for(j=0;j<=i;j++)
	{
    
    
		if(j==i)
		{
    
    
			s = p->next;             //定义变量 s  指向牺牲节点,并释放
			x = s->data;
			p->next = s->next;			
			free(s);
		}
		p = p->next;
	}
}

// <查找函数>
void Found_List(Linklist *L,Elemtype x)
{
    
    
	Linklist *p;
	int i = 0;
	p = L;
	while(p)
	{
    
    		
		if(p->data == x)
		{
    
    
			printf("Found data in %d position\n",i);
			break;
		}
		else
		{
    
    
			i++;
			p = p->next;
		}		
	}
	if(p==NULL)
		printf("Sorry , The data is not in the Linklist!!!!!!\n");
}

//<修改函数>
void Amend_List(Linklist *L,int i,Elemtype x)
{
    
    
	Linklist *p;
	int j = 0;
	p = L;
	while(p)
	{
    
    
		if(j == i)
		{
    
    
			p->data = x;
			break;
		}
		else
		{
    
    
			j++;
			p = p->next;
		}	
	}
	if(p==NULL)
		printf("The position of inputting is incorrect!!!!!!\n");
}

运行结果

★★★依次完成初始化、增删查改基本操作★★★

在这里插入图片描述

总结

综合上述,顺序表和单链表各有各的优缺点,使用哪一种会好一些要结合具体的问题而言,不能一概而论。

猜你喜欢

转载自blog.csdn.net/MZYYZT/article/details/113275710