C语言——单链表

一,链表的定义

链表是一种常见的采用动态存储分配方式的数据结构。在链表中,有一个头指针变量,用这个指针保存一个地址,头指针指向一个变量,这个变量称为元素。链表中,每一个元素包括两部分:数据部分和指针部分。数据部分用来存放元素中包含的数据,指针部分用来指向下一个元素 。(最后一个元素指向NULL)

在链表中,第一个结点前虚假一个头结点,头指针指向头结点,头结点的指针域指向第一个实际有效结点,该节点可以称为首元结点。

确定一个链表需要一个参数:头指针,通过头指针可以推算出链表其他所有的参数

二,单链表

链表中,每个结点只有一个指针,所有指针都是单线联系,除了末尾结点指针为空外,每个结点的指针都指向下一个结点,一环扣一环。

单链表的特点:

1)有一个head指针变量,存放头结点地址,称为头指针。

2)头结点的指针域head->next,存放首元结点(第一个实际有效结点)的地址。

3)数据域存放用户需要的实际数据,指针域存放下一个结点的地址。

4)链表的使用,可以使程序的内存利用率和时间效率大大提高。

5)链表各结点间顺序由指针域next来确定

1.单链表的初始化

由于链表的每个结点都包含数据域和指针域,即每个结点都要包含不同的数据类型,所以结点的数据类型必须选用结构体类型。其中必须有一个成员的类型是指向本结构体的指针类型。

对于这种结构体类型,C语言允许递归递归定义。例如定义一个链表表示一个班级,其中每一个结点表示一位学生,他的结构体类型如下:

typedef struct node{
	char name[20];//姓名 
	int number;//学号 
	struct node *next;//next的类型是指向本结构体数据类型的指针类型 
}Node,*LinkList;

Node是结构体类型,LinkList是结构体指针类型。LinkList head 相当于 Node *head,也相当于struct node *head。在 next 成员定义中,引用了本结构体类型,也就是说类型定义中采用了递归。

单链表的初始化就是创建一个头结点,若头结点的指针域为空,表示空单链表。单链表初始化代码如下:

LinkList InitList()
{
	LinkList head;//定义头指针变量 
	head = (Node*)malloc(sizeof(Node));//头指针指向分配的头结点内存空间 
	head->next=NULL;//头指针指针域为空 
	return head;//返回头结点地址,即头指针 
}

2.单链表的建立

单链表的建立就是在程序运行过程中,从无到有的建立一个链表,即一个一个分配结点的内存空间,然后输入结点中的数据,并建立结点间的相连关系。单链表的建立分为尾插法和头插法。

1)尾插法建立单链表

从第一个空表开始,重复读入数据,生成新结点,将读入的数据存放到新结点的数据域中,然后将新结点插入到当前链表的表尾,直至读入结束标志为止。由于每次插入的新结点都插入到链表表尾,所以增加一个指针 r 来始终指向链表的最后一个结点,以便新结点的插入。尾插法创建单链表代码如下:

void CreatByRear(LinkList head)
{
	Node *r,*s;//s指向新创建的结点 
	char name[20];
	int number;
	r = head;//r指向头结点 ,即当前单链表的尾结点 
	printf ("请输入学生姓名和学号:\n");
	while(1)
	{
		scanf ("%s",name);
		scanf ("%d",&number);
		if (number==0)
		break;
		s = (Node*)malloc(sizeof(Node));//分配结点的内存空间 ,令s指向新分配的内存 
		//分别赋值姓名和学号 
		strcpy(s->name ,name);
		s->number = number;
		r->next = s;//原来的结点指向新结点 
		r = s;//r指向新结点 
	}
	r->next = NULL;//链表的尾结点指针为空 
}

在 while 循环中,用 s 指向新分配的内存,分别赋值姓名和学号,如果学号为 0 ,则结束输入,退出循环,最后将链表的最后一个结点的指针域赋值为NULL,表示链表创建结束。

2)头插法创建单链表

从第一个空表开始,重复读入数据,生成新结点,将读入的数据存放到新结点的数据域中,然后将新结点插入到当前链表的表头结点之后,直至读入结束标志为止。尾插法创建单链表代码如下:

void CreatByHead(LinkList head)
{
	Node *s;
	char name[20];
	int number;
	printf ("请输入学生姓名和学号:\n");
	while(1)
	{
		scanf ("%s",name);
		scanf ("%d",&number);
		if (number==0)
		break;
		s = (Node*)malloc(sizeof(Node));
		strcpy(s->name ,name);
		s->number = number;
		s->next = head->next ;//新结点指向原来的首元结点 
		head->next = s;//链表的头结点指向新结点 
	}
	
} 

3.单链表的遍历

void OutPut(LinkList head)
{
	Node *p;//循环所用的临时指针 
	p = head->next ;//p指向链表的首元结点 
	while (p)
	{
		printf ("姓名:%s\n",p->name);//输出姓名 
		printf ("学号:%d\n",p->number);//输出学号 
		p = p->next; //移动临时指针到下一个结点 
	}  	
} 

OutPut函数功能是将链表中的数据进行输出。函数参数中,head表示一个链表的头指针,函数中定义一个临时指针 p 用来进行循环操作,使其指向要输出链表的首元结点。

将链表的初始化,创建和遍历输出操作整合在一起,就编写了一个包含学生信息的链表结构。具体如下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct node{
	char name[20];//姓名 
	int number;//学号 
	struct node *next;//next的类型是指向本结构体数据类型的指针类型 
}Node,*LinkList;

//单链表的初始化:就是创建一个头结点  
LinkList InitList()
{
	LinkList head;//定义头指针变量 
	head = (Node*)malloc(sizeof(Node));//头指针指向分配的头结点内存空间 
	head->next=NULL;//头指针指针域为空 
	return head;//返回头结点地址,即头指针 
}

//尾插法创建单链表 
void CreatByRear(LinkList head)
{
	Node *r,*s;//s指向新创建的结点 
	char name[20];
	int number;
	r = head;//r指向头结点 ,即当前单链表的尾结点 
	printf ("请输入学生姓名和学号:\n");
	while(1)
	{
		scanf ("%s",name);
		scanf ("%d",&number);
		if (number==0)
		break;
		s = (Node*)malloc(sizeof(Node));//分配结点的内存空间 ,令s指向新分配的内存 
		//分别赋值姓名和学号 
		strcpy(s->name ,name);
		s->number = number;
		r->next = s;//原来的结点指向新结点 
		r = s;//r指向新结点 
	}
	r->next = NULL;//链表的尾结点指针为空 
}

//头插法创建单链表
void CreatByHead(LinkList head)
{
	Node *s;
	char name[20];
	int number;
	printf ("请输入学生姓名和学号:\n");
	while(1)
	{
		scanf ("%s",name);
		scanf ("%d",&number);
		if (number==0)
		break;
		s = (Node*)malloc(sizeof(Node));
		strcpy(s->name ,name);
		s->number = number;
		s->next = head->next ;//新结点指向原来的首元结点 
		head->next = s;//链表的头结点指向新结点 
	}
	
} 
//单链表的遍历
void OutPut(LinkList head)
{
	Node *p;//循环所用的临时指针 
	p = head->next ;//p指向链表的首元结点 
	while (p)
	{
		printf ("姓名:%s\n",p->name);//输出姓名 
		printf ("学号:%d\n",p->number);//输出学号 
		p = p->next; //移动临时指针到下一个结点 
	}  	
} 
int main (void)
{
	LinkList ha,hb;//定义单链表头指针 
	ha = InitList();//初始化单链表 
	CreatByRear(ha);//尾插法创建单链表 
	OutPut(ha);//输出单链表 
	hb = InitList();
	CreatByHead(hb);
	OutPut(hb);
		
	return 0;
}

  • 10
    点赞
  • 71
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

๑Aurora.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值