C语言链表基础知识

11.7链表

链表是一种最常见的数据结构,它动态地进行存储分配。

用指针处理链表

链表有单向链表、双向链表、环形链表等形式。

11.7.1链表概述

链表是将若干个数据项按一定的原则连接起来的表。
连接原则:

(1)前一个结点指向下一个结点
(2)只有通过前一个结点オ能找到下一个结点。
链表组成:
(1)头指针变量head一存放首元素地址,指向链表的首结点。
(2)每个结点由两个域组成:
数据域一一存储结点本身的信息。(用户有用信息)
指针域一一存放下一个结点的地址
(3)尾结点的指针域置为“NULL”,作为链表结束的标志。

链表结点数据可以用结构体来描述,例如

其中成员num和 score用来存放结点中的有用数据(用户
需要用到的数据),next是指针类型的成员,它指向 struct
student类型数据(这就是next所在的结构体类型)

 struct student
 {
 	long num;
 	float score;
 	struct student*next;/*指向下一结点*/
 };

其中成员num和 score用来存放结点中的有用数据(用户
需要用到的数据),next是指针类型的成员,它指向 struct
student类型数据(这就是next所在的结构体类型)

11.7.2简单链表

静态链表:所有结点在程序中定义,没有动态申请空间,用完后也不能够释放空间

void main()
{
	struct student a,b, c, head, *p;  	//对三个结点赋值
		a.num=89101;a. score=89.5;
		b. num=89103: 5. score=90
		C num=89107: c score=85;
		//建立彼此的链接,形成链表
	head=&a;
	a next=&b;
	b. next=&c;
	C next=NULL;
	p=head;
		//输出链表的数据信息
	do
	{
		printf("1d5. 1f\n", p->num, p->score);
    	p=p->next;
	}while(p!=NULL);
   
}

库函数< stdlib. h>和< alloc. h>提供动态地开辟和释放存储单元的有关函数

(1) malloc函数

函数原型:

void* malloc(unsigned int size)

功能:在内存的动态存储区分配size个字节的连续存储空间

返回值:

​ 成功,返回一个指针,该指针指向存储空间首地址,基类型为void

​ 失败,返回空指针(NULL)。原因:内存空间不够。
由于返回值是空类型指针,所以在调用时必须进行强制类型转换,将其转换成所需的类型。
如:

int *p=NULL;
p=(int*) malloc(sizeof(int));

(2)free函数

函数原型:

void free( void *p)

功能:

释放由p指向的空间。该地址p必须是最近一次由mllc、 calloc、 realloc函数申请成功返回的指针。
free函数无返回值,使用free前应检查该指针是否为空。
如:

int*p=NULL;
p=(int*)malloc(10* sizeof(int));
if(p!= NULL)
{
	free(p);
	p=NULL;
}					//free和NULL配对使用,防止产生野指针

11.7.3线性链表

1.线性链表概述及其结构

​ 线性表:当一组数据元素形成了“前后”关系时,我们称之为线性表

2.线性表在内存中的两种形式

​ 顺序表:以数组形式存放,连续存放,插入或删除需要移动其他数据元素

​ 线性链表:以指针形式链接数据单元,插入或删除不需要移动其他数据元素

struct 节点结构体类型名
{
	数据成员定义;
	struct 节点结构体类型名 *指针变量名;
};

2、线性链表的基本操作有:创建、插入、删除、输岀和销毁等。

链表的创建操作

含义:从无到有地建立起一个链表,即往空链表中依次插入若干结点,并保持结点之间的前驱和后继关系。

NODE *Create_LinkList()//创建链表
{
	NODE *head,*tail,*pnew;
	int scor;
	head=(NODE*)malloc(sizeof(NODE));//创建头节点
	if(head==NULL)//创建失败,则返回
	{
		printf("no enough memory!\n");
		return(	NULL);
	}
    
	head->next=NULL;//头节点的指针域置NULL
    
	printf("input the score of students:\n");
	while(1)//创建学生成绩线性链表
	{
    	scanf("%d",&score);//输入成绩
    	if(score<0)//成绩为负,循环退出
        	break;
   		 //创建一新节点
   		pnew=(NODE*)malloc(sizeof(NODE));
    	if(pnew==NULL)//创建新节点失败,则返回
    	{
        	printf("no enough memory!\n");
       		return(NULL);
    	}
    	pnew->score=score;
    	pnew->next=NULL;
    	tail->next=pnew;
    	tail=pnew;
	}
	return(head);
}
链表的插入操作

插入前,Ni是Ni+1的前驱,Ni+1是Ni的后继;插入后,新插入的结点N成为Ni的后继、Ni+1的前驱

void Insert_LinkList(NODE*head,NODE*pnew,int i)
{
	NODE *p;
	int j;
	p=head;
	for(j=0;j<i&&p!=NULL;j++)//将p指向要插入的第i个节点
		p=p->next;
	if(p==NULL)//表明链表中第i个节点不存在
	{
		printf("the %d node not foundt!\n",i);
		return;
	}
	pnew->next=p->next;//将插入节点的指针域指向第i个节点的后继节点
	p->next=pnew;//将第i个节点的指针域指向插入节点
}
链表的删除操作

删除前,节点Ni-1是Ni的前驱,Ni+1是Ni的后继;删除后,结点Ni+1成为Ni-1的后继。

记得释放删除节点的内存

void Delete_LinkList(NODE *head,int i)
{
	NODE *p,*q;
	int j;
	if(i==0) return;//删除的是头指针
	p=head;
	//将p指向要删除的第i个节点的前驱节点
	for(j=1;j<i&&p->next!=NULL;j++)
		p=p->next;
	if(p->next==NULL)//表明链表中第i个节点不存在
	{
		printf("the %d node not foundt!\n",i);
		return;
	}
    q=p->next;//q指向待删除的节点i
    p->next=q->next;//删除节点i
    free(q);//释放节点i的内存单元
}
链表的输出操作
void Display_LinkList(NODE *head)
{
	NODE *p;
	for(p=head->next;p!=NULL;p=p->next)
		printf("%d",p->score);
	printf("\n");
}
链表的销毁操作

一个节点一个节点从后往前删除

void Free_LinkList(NODE *head)
{
	NODE *p,*q;
	p=head;
	while(p->next!=NULL)
	{
		q=p->next;
		p->next=q->next;
		free(q);
	}
}
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值