线性表的链式存储结构 ( 链表 )

线性表的链式存储结构

1.相比于线性表的顺序存储结构的优缺点

相比于线性表的顺序存储结构的优点

(1)链式存储时,相邻数据元素可随意存放,但所占存储空间分两部分,一部分存放结点值,另一部分存放表示结点间关系的指针

优点:插入或删除元素时很方便,使用灵活,存储空间利用率高。

缺点:存储密度小(<1),查找和修改需要遍历整个链表。

(2)顺序存储时,相邻数据元素的存放地址也相邻(逻辑与物理统一);要求内存中可用存储单元的地址必须是连续的。

优点:存储密度大(=1),易于查找和修改。

缺点:插入或删除元素时不方便;存储空间利用率低,预先分配内存可能造成存储空间浪费。

2.线性表的单链表储存结构

//线性表的单链表储存结构
typedef struct node
{
    
    
	Elemtype date;
	
	struct node *next;
 } node;
 typedef struct node *list;

3.单链表的整表创建 (尾插法)

//单链表的整表创建 (尾插法)
void creatlist(list*L,int a[],int n)
{
    
    
	list p,r;//r指向链表的尾结点, 
	
	int i;
	*L=(list)malloc(sizeof(node));//L为线性表 
	
	r=*L;//定义r指向尾部的结点 
	
	for(i=0;i<n;i++)
	{
    
    
		p=(list)malloc(sizeof(node));//生成新结点 
		
		p->date=a[i];
		
		r->next=p;//表尾终端结点的指针指向新节点,就是将将新生成的节点p插入链表尾部 
		
		r=p;//r重新指向尾结点 
	}
	r->next=NULL;
 } 

4.单链表的整表输出

void showlist(list L,int n)
 {
    
    
 	list p=L->next;
 	while(p)
 	{
    
    
 		printf("%3d",p->date);
 		p=p->next;
	 }
	 printf("\n");
  } 

3.单链表元素的获取

int getElem(list L,int i,Elemtype *x)
 {
    
    
 	int j=1;//从链表第一个结点开始一一检索 
 	
	list p;//定义一个头指针 
	
 	p=L->next;
	 	
	for(j=1;j<i;j++)
 	{
    
    
 		p=p->next;
	 }
	  if(p==NULL||j>i)//判断指针p和j是否合法 ,若不合法返回0 
	 
	 	return 0;
	*x=p->date;//将第i个元素的数据赋给*e; 
	
	return 1;//获取成功返回1 
  } 

4.单链表的插入

//在原链表第i个元素之前插入数据元素X,L的长度++

//单链表的插入,在原链表第i个元素之前插入数据元素X,L的长度++ 
 int listinsert(list*L,int i,Elemtype x) 
 {
    
    
 	int j=1;
	list p=*L;
	list s;//定义一个空结点s;
	for(j=1;j<i;j++)
	{
    
    
		p=p->next;
	 } 
	 if(p==NULL||j>i)//判断指针p和j是否合法 ,若不合法返回0 
		return 0;
	 s=(list)malloc(sizeof(node));//生成新节点 
	 s->date=x;
	 s->next=p->next;//顺序不可改变,若更换就会造成s->next=s; 
	 p->next=s;
	 return 1;
 }

5.//单链表的删除

//单链表的删除
 int listdelete(list L,int i,Elemtype*x) 
 {
    
    
 	int j=1;
 	list q;
 	list p=L->next;
 	for(j=1;j<i;j++)//遍历寻找第i个元素 
 	{
    
    
 		p=p->next;
	 }
	 if(p->next==NULL||j>i) //若第i个元素不存在,返回零 
 		return 0;
	 q=p->next;//借用q删除第i个结点 
	 p->next=q->next;
	 free(q);//回收删除的结点 
	 return 1;
} 

完整代码详解

#include<stdio.h>

#include<stdlib.h>

#include<typeinfo> 

typedef int Elemtype;
//线性表的单链表储存结构
typedef struct node
{
    
    
	Elemtype date;
	
	struct node *next;
 } node;
 typedef struct node *list;
 
 //单链表的整表创建 (尾插法) 
 void creatlist(list*L,int a[],int n)
{
    
    
	list p,r;//r指向链表的尾结点, 
	
	int i;
	*L=(list)malloc(sizeof(node));//L为线性表 
	
	r=*L;//定义r指向尾部的结点 
	
	for(i=0;i<n;i++)
	{
    
    
		p=(list)malloc(sizeof(node));//生成新结点 
		
		p->date=a[i];
		
		r->next=p;//表尾终端结点的指针指向新节点,就是将将新生成的节点p插入链表尾部 
		
		r=p;//r重新指向尾结点 
	}
	r->next=NULL;
 } 
 //单链表的整表输出
void showlist(list L,int n)
 {
    
    
 	list p=L->next;
 	while(p)
 	{
    
    
 		printf("%3d",p->date);
 		p=p->next;
	 }
	 printf("\n");
  } 
 //单链表元素的获取
 int getElem(list L,int i,Elemtype *x)
 {
    
    
 	int j=1;//从链表第一个结点开始一一检索 
 	
	list p;//定义一个头指针 
	
 	p=L->next;
	 	
	for(j=1;j<i;j++)
 	{
    
    
 		p=p->next;
	 }
	  if(p==NULL||j>i)//判断指针p和j是否合法 ,若不合法返回0 
	 
	 	return 0;
	*x=p->date;//将第i个元素的数据赋给*x; 
	
	return 1;//获取成功返回1 
  } 
 //单链表的插入,在原链表第i个元素之前插入数据元素X,L的长度++ 
 int listinsert(list*L,int i,Elemtype x) 
 {
    
    
 	int j=1;
 	
	list p=*L;
	
	list s;//定义一个空结点s;
	
	for(j=1;j<i;j++)
	{
    
    
		p=p->next;
	 } 
	 if(p==NULL||j>i)//判断指针p和j是否合法 ,若不合法返回0 
	 
		return 0;
		
	 s=(list)malloc(sizeof(node));//生成新节点 
	 
	 s->date=x;
	 
	 s->next=p->next;//顺序不可改变,若更换就会造成s->next=s; 
	 
	 p->next=s;
	 
	 return 1;
 }
 //单链表的删除
 int listdelete(list L,int i,Elemtype *x) 
 {
    
    
 	int j=1;
 	
 	list q;
 	
 	list p=L->next;
 	
 	for(j=1;j<i;j++)//遍历寻找第i个元素 
 	{
    
    
 		p=p->next;
	 }
	 if(p->next==NULL||j>i) //若第i个元素不存在,返回零 
	 
 		return 0;
 		
	 q=p->next;//借用q删除第i个结点 
	 
	 p->next=q->next;
	 
	 free(q);//回收删除的结点 
	 
	 return 1;
} 

int main()
{
    
    
	list L;
	
	int n=5;
	
	printf("请输入链表长度\n");
	
	scanf("%d",&n);
	
	int x,i;
	
	int a[100];
	
	printf("请输入%d位链表的值\n",n);
	
	for(i=0;i<n;i++)
	{
    
    
		scanf("%d",&a[i]);
	}
	creatlist(&L,a,n);
	
	printf("请输入你要查询的链表中的第i个值\n"); 
	
	scanf("%d",&i);
	
	getElem(L,i,&x);
	
	printf("第%d个值为%d\n",i,x);
	
	printf("请输入要插入节点的位置z和插入的值x0\n");
	
	int z,x0;
	
	scanf("%d %d",&z,&x0); 
	
	listinsert(&L,z,x0);
	
	printf("此时链表的各元素如下\n"); 
	
	showlist( L, n);
	
	printf("请输入要删除的位置o\n"); 
	
	int o;
	
	scanf("%d",&o);
	 
	listdelete( L,o,&x);
	
	showlist( L, n);
 } 

运行结果
注:我本人是在vs上编写代码的,上传代码将所有scanf_s改为了scanf;
以便使用其他编译器运行
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_59708493/article/details/121198447