单链表的建立



一.准备工作

  1. 我们建立单链表准备采用头插法尾插法两种方法来建立单链表。

  2. 单链表的准备工作和顺序表的准备工作基本相同,点击—>顺序表的准备工作+建立工作即可查看。

  3. 头部函数:
    [] 两个头文件stdio.hstdlib.h
    [] 定义状态函数
    [] 定义结点数据域的数据类型

#include<stdio.h>
#include<stdlib.h>
typedef int Status;//状态函数
typedef int ElemType;//结点数据域的数据类型

1.通过结构类型来定义单链表存储类型与定义

typedef struct Node
{
	ElemType data;//数据域
	struct Node* next;//指针域
}Node;

通过以上结构类型我们定义了一个数据域data数组和指针域Node* next
我们知道单链表的结构如图:
在这里插入图片描述
由单链表的结构组成可知:

  1. 单链表的每个结点是由两部分组成的,分别是数据域指针域
  2. 我们通常将数据域里的数据用数组data来存储
  3. 我们通常将指针域里的数据用数组next来存储

所以单链表可以表示成如下图:
在这里插入图片描述
我们需要知道图中的信息:

  1. 每个data数组是用来存放结点的值

  2. 每个next指针都是用来存放下一个结点的地址

  3. 定义指向指针的结点类型

typedef struct Node* LinkList;

这条语句通常都会加到typedef定义的结构类型后面,它的含义是:
struct Node*定义成了一个新的类型LinkList,这个类型是一个结构体指针。
换句话说就是:
LinkListstruct Node*等价,他有两个名字。


二.操作函数的声明

1.单链表的初始化
2.尾插法建立单链表
3.头插法建立单链表
4.输出链表的数据域

LinkList InitList_List(void);
LinkList CreateListTail(ElemType a[],int n);
LinkList CreateListHead(ElemType a[],int n);
void PrintList_List(LinkList head);

三.主函数的编写

1.主函数的编写

int main()
{
	ElemType d[4]={17,24,39,45};
	/*===================================*/
	LinkList Tail_Head;//尾插法
	Tail_Head=CreateListTail(d,4);//尾插法
	/*===================================*/
	LinkList H_Head;//头插法
	H_Head=CreateListHead(d,4);//头插法
	/*=====================================*/
	printf("单链表是:\n");
	PrintList_List(Tail_Head);//尾插法调用功能函数
	PrintList_List(H_Head);//头插法调用功能函数
	/*=====================================*/
	printf("\n");
	return 0;

四.功能函数的编写

1.尾插法

LinkList CreateListTail(ElemType a[],int n)
{
	LinkList head,p,q;
	int i;
	head=Initlist_List();
	q=head;

	for(i=0;i<n;i++)
	{
		p=(Node*)malloc(sizeof(Node));
		p->data=a[i];
		q->next=p;
		q=p;
	}
	p->next=NULL;
	return head;
}

2.头插法

LinkList CreateHead(ElemType a[],int n)
{
	LinkList head,p;
	int i;
	head=InitList_List();
	for(i=n-1;i>=0;i--)
		{
			p=(Node*)malloc(sizeof(Node));
			p->data=a[i];
			p->next=head->next;
			head->next=p;
		}
		return head;
}

3.线性表输出函数

void PrintList_List(LinkList head)
{
	LinkList p;
	p=head;
	while(p->next!=NULL)
	{
		p=p->next;
		printf("%d",p->data);
	}
}

4.线性表的初始化

LinkList InitList_List(void)
{
	LinkList head;//定义头指针
	/*动态内存分配空间给head指针*/
	head=(Node *)malloc(sizeof(Node));//申请一个结点给head指针
	if(head==NULL)//动态内存分配失败
	exit(1);
	
	head->next=NULL;//只有一个结点
	return head;//返回头指针
}

五.函数接口的说明

1.链表的初始化

LinkList InitList_List(void);

接口:
[注意点]:为什么初始化函数的形参为void空类型呢?

  • 我们知道了链表的存储结构,还需要了解单链表的两种形式。
  • 单链表的两种形式为:
    (1).不带头结点的单链表
    在这里插入图片描述
    (2).带头结点的单链表
    在这里插入图片描述
    以上多出来的头结点是指:位于单链表最前面的一个摆设,哈哈,之所以理解成摆设是因为它的数据域里不存放东西,也就是NULL了,而且头结点不计入单链表表长,说到底它就是没有存在感般的存在。所以我们以上形参直接定义成void,其实还有个等价的方法写出来,便于你理解。
void InitList_List(LinkList *L)//初始化单链表
{
   L=(LinkList_List *)malloc(sizeof(LinkList_List));
   L->next=NULL;
}

我们用一个指针L来代表形参,在动态内存开辟空间申请新结点给LL指向的头结点为NULL,其实这个指针L就是头指针了。

2.尾插法建立单链表函数

LinkList CreateListTail(ElemType a[],int n);

函数接口1:ElemType a[]表示结点的值
函数接口2:int n表示结点的个数

3.头插法建立单链表函数

LinkList CreateListHead(ElemType a[],int n);

函数接口1:ElemType a[]表示结点的值
函数接口2:int n表示结点的个数

4.单链表输出函数

void PrintList_List(LinkList head);

函数接口:链表头指针LinkList
别问为什么形参是头指针啊,单链表执行逻辑就是从头指针开始的呀,不像顺序表那样支持随机访问,单链表这里还是得好好老老实实从头开始。


六.头插法和尾插法的算法分析

为什么我们要在后边来讨论头插法尾插法的算法分析呢?
因为我们前面已经提到了单链表的两种形式,知道了有无头结点的单链表。
<1>.在带有头结点的单链表中进行头插法
在这里插入图片描述
我们通过改变结点指针域指向的方式就可以将新结点a1插入其中。

<2>.在带无头结点的单链表中进行头插法
在这里插入图片描述
在这里插入图片描述
尾插法算法分析也是如此,可以试着自己分析一下。


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

CodeLinghu

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

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

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

打赏作者

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

抵扣说明:

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

余额充值