单向链表简介

 

一、单向链表的特征

单向链表是利用动态内存分布、使用结构体并配合指针来实现的一种数据结构。相比于数组,单向链表进行数据插入和删除的操作更为简单,但是,调取链表中的元素,只能一个个去访问寻找,不能直接通过位置,一步得到。

二、实现单向链表的基础

struct student
{
	int score;
	char num[100];
	struct student *next;/*通过这个可以指向结构体的指针,可以将多个结构体像是锁链一样连起来
	 					 例如:p1->p2->p3->NULL  注:链表最后一个元素的next是指向空指针的*/ 
};

单向链表通过结构体中,放一个指向本结构体的指针成员,来实现,将每一个元素像锁链一样串起来。

三、创建一个链表

typedef struct student
{
	int score;
	char num[100];
	struct student *next;
}STU;我们可以通过typedef来将struct student用STU来替代,减少代码量

STU *Creatlink(STU a[] , int n)
//定义一个结构体类型的返回指针的函数,链表最后实际上是返回链表的头指针 
{
	STU *head;// 定义一个student结构类型的指针,作为链表的头指针
	
	head = &a[0];//将结构体数组的第一个元素的位置给头指针
	
	// 用循环将链表串连起来 
	for(int i = 0 ; i < n - 1 ; i++)
	{
		a[i].next = &a[i + 1];
	 }
	a[n - 1].next = NULL;//最后一个指向空指针
	
	return head;//最后返回头指针 
}

我们通过上述返回指针的函数,得到了完成了链表的串联,同时,返回了该链表的头指针,我们可以通过操作链表的头指针来操作整个链表。

四、实现在一个链表中查找元素

在单向链表中,要是需要查找某一个元素,我们从链表的第一个元素开始向下遍历,直到找到那个元素为止。

void Find(STU *head , char num[])//根据学号找人
{
	STU *p = head;// 用一个p指针来储存头指针,防止head发生变化
	
	while(p != NULL)
	{
		if(strcmp(p->num,num) == 0) break;
		p = p->next;// 传向下一个指针 
	}
	if(p == NULL) printf("查无此人");
	else //说明找到了
	{
		printf("%d %s", p->score , p->num);
	 } 
}

五、实现删除链表中的一个元素

在单向链表中,删除一个元素,实际操作就是将待删除元素的上一个元素与下一个元素相连,直接跳过这个元素,达到删除的效果。

STU *Dely(STU *head , char num[])
{
	STU *p = head , *front;//用front储存前一个指针;
	while(p != NULL)
	{
		if(strcmp(p->num,num) == 0) break;
	 }
	 front = p;
	 p = p->next;
	 
	 if(p != NULL) // 说明找到了要删除的人 
	 {
	 	front->next = p->next;
	 }
	 return head;//同过返回头指针返回变化后的链表 
}

删除之后得到一个新链表,故返回head。 

六、实现在单向链表中添加一个元素

在单向链表中,添加一个元素又三种情况:

(1)直接添加在链表的最前面,就是将该元素与原链表第一个元素相连,然后,将该元素的位置变为head;

(2)添加在链表的末尾,就是将该元素与原链表的最后一个元素相连,同时,还要将该元素的末尾连上空指针NULL;

(3)添加在链表的中间,将是将该元素与所需要插入位置的前一个,还有后一个元素同时相连;

以上三种情况都会生成一个新的链表,故均会返回head;

下面以向链表中按年龄顺序插入一个元素为例:
 

STU *insert(STU *head , STU *pnewnode)
{
	STU *p , *front;
	p = head;
	while(p != NULL && p->score < (pnewnode->score))//p指向节点的分数比newnode所指向的节点分数小就一直往后移 
	{
		front = p;
		p = p->next;
	}
	
	if(p == head)
	{
		pnewnode->next = head;
		head = pnewnode;//新节点排在head前面,所以newnode成了新head 
	}
	else
	{
		if(p == NULL) //说明插到末尾
		{
			front->next = pnewnode;//把储存的位置给下一个连上新节点
			pnewnode->next = NULL;//新节点的下一个连上NULL 
		 }
		 else//说明是在中间插入; 
		 {
		 	front->next = pnewnode;
		 	pnewnode->next = p;
		  } 
	 }
	 return head;
}

最后,给大家一个实现上述功能的总代码:

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

typedef struct student
{
	int score;
	char num[100];
	struct student *next;
}STU;

//创建一个链表 
STU *Creatlink(STU a[] , int n)
{
	STU *head;
	
	head = &a[0];
	
	
	for(int i = 0 ; i < n - 1 ; i++)
	{
		a[i].next = &a[i + 1];
	 }
	a[n - 1].next = NULL;
	
	return head;
}

//实现一个链表的查找
void Find(STU *head , char num[])
{
	STU *p = head;
	
	while(p != NULL)
	{
		if(strcmp(p->num,num) == 0) break;
		p = p->next;
	}
	if(p == NULL) printf("查无此人");
	else 
	{
		printf("%d %s", p->score , p->num);
	 } 
}

//链表中元素的删除
STU *Dely(STU *head , char num[])
{
	STU *p = head , *front;
	while(p != NULL)
	{
		if(strcmp(p->num,num) == 0) break;
	 }
	 front = p;
	 p = p->next;
	 
	 if(p != NULL) 
	 {
	 	front->next = p->next;
	 }
	 return head;
}

//链表的插入

STU *insert(STU *head , STU *pnewnode)
{
	STU *p , *front;
	p = head;
	while(p != NULL && p->score < (pnewnode->score))
	{
		front = p;
		p = p->next;
	}
	
	if(p == head)
	{
		pnewnode->next = head;
		head = pnewnode; 
	}
	else
	{
		if(p == NULL) 
		{
			front->next = pnewnode;
			pnewnode->next = NULL;
		 }
		 else
		 {
		 	front->next = pnewnode;
		 	pnewnode->next = p;
		  } 
	 }
	 return head;
}

void output(STU *head)
{
	struct student *p = head;
	while(p != NULL)
	{
		printf("%d %s\n", p->score , p->num);
		p = p->next;
	}
}

int main()
{
	int n;
	scanf("%d", &n);

	STU a[100];
	for(int i = 0 ; i < n ; i++)
	{
		scanf("%d %s", &a[i].score , &a[i].num);
	}

	STU *pnewnode , *head , newnode;
	scanf("%d %s", &newnode.score , &newnode.num);

	pnewnode = &newnode;
	char num1[100] , num2[100] , num3[100];
	scanf("%s %s %s", &num1 , &num2 , &num3);

	head = Creatlink(a , n);
	output(head);

	Find(head , num1);

	head = Dely(a ,num2);
	output(head);

	head = insert(a , pnewnode);
	output(head);

	return 0;
}

 

  • 9
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值