四种创建单链表的方法

这篇具有很好参考价值的文章主要介绍了四种创建单链表的方法。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

学习了这么久的数据结构,终于把链表吃透啦,下面是我整理的四种创建单链表的的方法

以及一些非常容易犯的错误,让我们一起来看看吧~

目录

一、单链表的分类

二、单链表的初始化

2.1 初始化不带头结点的单链表

2.2 初始化带头结点的单链表

三、单链表的创建

3.1 创建不带头结点的单链表

3.1.1 头插法

3.1.2 尾插法

3.2 创建带头结点的单链表

3.2.1 头插法

3.2.2 尾插法

四、单链表的打印

4.1 打印不带头结点的单链表

4.2 打印带头结点的单链表

五、代码实现

5.1 完整代码

5.2 运行结果

六、总结

附:系列文章


一、单链表的分类

  单链表一共有两种,一个是带头结点的单链表,还有一个是不带头结点的单链表

  总的来说,带头结点的单链表相对于不带头结点的单链表来说,更加方便对链表基本操作的实现  

(带头结点的单链表操作起来更方便,所以很多时候我们都是用带头结点的单链表)

二、单链表的初始化

  单链表的初始化,我们分不带头结点和带头结点两种情况

2.1 初始化不带头结点的单链表

  不带头结点的单链表,说明头指针指向了第一个有效的结点

PNode Init_1_Node(){
	PNode head;          
	head=NULL;      //因为不带头结点,所以我们只要让头结点为空
	return head;
}

2.2 初始化带头结点的单链表

  带头结点的单链表,头指针要指向头结点(头结点不存放数值,可将头结点理解为无效结点)

PNode Init_2_Node(){
	PNode head;
	head=(PNode)malloc(sizeof(Node));     //申请一个头结点
	head->next=NULL;                      //头结点指针域指向空
	return head;
}

三、单链表的创建

  单链表的创建,我们分不带头结点和带头结点来介绍,具体再分为头插法和尾插法两种方法

3.1 创建不带头结点的单链表

3.1.1 头插法

  头插法嘛,顾名思义,每次都在链表的前面插入,这样最先输入的结点最后输出,最后输入的结点最先输出。例如你输入的是1,2,3。那么打印出来的将是3,2,1。

void Creat_1_Node(PNode *head){       //不带头结点我们用头指针的地址来保存单链表
	int i,n;
	printf("(头插法)请输入不带头结点的链表结点个数:"); 
	scanf("%d",&n);                   //输入不带头结点单链表的结点个数
	for(i=1;i<=n;i++){      
		PNode Pnew=(PNode)malloc(sizeof(Node));    //创建一个新的结点 
		Pnew->next=NULL;                         //指针域指向空
		printf("第%d个结点的元素为:",n+1-i); 
	    scanf("%d",&Pnew->data);
		if(*head==NULL){              //判断头指针是否指向空
			*head=Pnew;               //如果是则让头指针指向第一个有效结点
		}else{                        //当头指针指向非空时
			Pnew->next=*head;         //将新的结点插入到头指针所指结点的前面
			*head=Pnew;               //头指针指向新插入的结点
		}                             
	}                     //例如你输入  1 2 3 
}                        //实际上链表是 3 2 1  这是因为你是在前面插入了新的结点

3.1.2 尾插法

  尾插法呢就比较好理解了,每次都在链表的最后插入一个新的结点就好了,这个是按顺序的,输入什么最后就输出什么。例如输入1,2,3。输出将是1,2,3。

void Creat_2_Node(PNode *head){
	PNode Last;           //尾插法的话,我们要有一个时刻指向尾结点的指针
	int i,n;
	printf("(尾插法)请输入不带头节点的链表结点个数:");
	scanf("%d",&n);
	for(i=1;i<=n;i++){
		PNode Pnew=(PNode)malloc(sizeof(Node));
		Pnew->next=NULL;
		printf("第%d个结点的元素为:",i); 
		scanf("%d",&Pnew->data);
		if(*head==NULL){        //判断头指针是否指向空,这是必要的
			*head=Pnew;         //头指针指向第一个有效结点
			Last=Pnew;          //因为此时只有一个结点,所以Last指向这个结点就好
		}else{                  //当头指针指向不是空的时候
			Last->next=Pnew;    //尾结点指针域指向新插入的结点
			Last=Pnew;          //将新结点赋给尾结点(插入的结点变成新的尾结点)
		}
	}
}

3.2 创建带头结点的单链表

3.2.1 头插法

  带头结点的单链表使用头插法创建时,一定要注意 Pnew->next=p->next 和 p->next=Pnew 两行代码不能颠倒!Pnew->next=p->next 的意思是将p后面的所有结点都接到了要插入的新结点的后面,p->next=Pnew 的意思是将新结点接到p(头结点)的后面。如果将两行代码颠倒了,那么头结点后面的所有结点将丢失,这样无论你创建多大的链表,其实最后都只有两个结点(一个是头结点,没什么用,还有一个就是你输入的最后一个数据),其他的结点都丢失了

void Creat_3_Node(PNode head){
	PNode p=head;          //将head赋给p,p是头结点,不保存数据,为无效结点
	int i,n;
	printf("(头插法)请输入带头节点的链表结点个数:");
	scanf("%d",&n);
	for(i=1;i<=n;i++){
		PNode Pnew=(PNode)malloc(sizeof(Node));  //创建新的结点
		Pnew->next=NULL;                         //指针域指向空
		printf("第%d个结点的元素为:",n+1-i); 
		scanf("%d",&Pnew->data);                
		Pnew->next=p->next;       //这里注意一定要先把p后面的所有结点接到Pnew后面
		p->next=Pnew;             //再执行把Pnew连接到p后面
	}
}

3.2.2 尾插法

  尾插法就不需要担心数据丢失的问题了,因为是在尾结点后面插入(尾结点后面没有其他结点)

void Creat_4_Node(PNode head){
	PNode p=head;
	PNode Last;          //需要一个时刻指向尾结点的指针
	Last=p;
	int i,n;
	printf("(尾插法)请输入带头节点的链表结点个数:");
	scanf("%d",&n);
	for(i=1;i<=n;i++){
		PNode Pnew=(PNode)malloc(sizeof(Node));
		Pnew->next=NULL;
		printf("第%d个结点的元素为:",i); 
		scanf("%d",&Pnew->data);
		Last->next=Pnew;      //尾结点指针域指向要插入的结点
		Last=Pnew;            //新插入的结点成为新的尾结点
	}	
}

四、单链表的打印

  这里分为不带头结点和带头结点两种情况,需要分别打印

4.1 打印不带头结点的单链表

void Print_1_Node(PNode head){
	PNode p=head;            //不带头结点,p就是第一个有效元素
	printf("新的链表为:");
	while(p!=NULL){           //采用循环挨个打印
		printf("%d ",p->data);
		p=p->next;
	}
	printf("\n");
}

4.2 打印带头结点的单链表

void Print_2_Node(PNode head){
	PNode p=head->next;       //带头结点,p应该为第一个有效结点
	printf("新的链表为:");
	while(p!=NULL){
		printf("%d ",p->data);    //打印
		p=p->next;
	}
	printf("\n");
}

五、代码实现

5.1 完整代码

#include<stdio.h>
#include<malloc.h>
typedef struct Node{
	int data;
	struct Node * next;
}Node,*PNode;
PNode Init_1_Node(){
	PNode head;
	head=NULL;
	return head;
}
PNode Init_2_Node(){
	PNode head;
	head=(PNode)malloc(sizeof(Node));
	head->next=NULL;
	return head;
}
void Creat_1_Node(PNode *head){
	int i,n;
	printf("(头插法)请输入不带头节点的链表结点个数:");
	scanf("%d",&n);
	for(i=1;i<=n;i++){
		PNode Pnew=(PNode)malloc(sizeof(Node));
		Pnew->next=NULL;
		printf("第%d个结点的元素为:",n+1-i); 
	    scanf("%d",&Pnew->data);
		if(*head==NULL){
			*head=Pnew;
		}else{
			Pnew->next=*head;
			*head=Pnew;
		}
	}
}
void Creat_2_Node(PNode *head){
	PNode Last;
	int i,n;
	printf("(尾插法)请输入不带头节点的链表结点个数:");
	scanf("%d",&n);
	for(i=1;i<=n;i++){
		PNode Pnew=(PNode)malloc(sizeof(Node));
		Pnew->next=NULL;
		printf("第%d个结点的元素为:",i); 
		scanf("%d",&Pnew->data);
		if(*head==NULL){
			*head=Pnew;
			Last=Pnew;
		}else{
			Last->next=Pnew;
			Last=Pnew;
		}
	}
}
void Creat_3_Node(PNode head){
	PNode p=head;
	int i,n;
	printf("(头插法)请输入带头节点的链表结点个数:");
	scanf("%d",&n);
	for(i=1;i<=n;i++){
		PNode Pnew=(PNode)malloc(sizeof(Node));
		Pnew->next=NULL;
		printf("第%d个结点的元素为:",n+1-i); 
		scanf("%d",&Pnew->data);
		Pnew->next=p->next;
		p->next=Pnew;
	}
}
void Creat_4_Node(PNode head){
	PNode p=head;
	PNode Last;
	Last=p;
	int i,n;
	printf("(尾插法)请输入带头节点的链表结点个数:");
	scanf("%d",&n);
	for(i=1;i<=n;i++){
		PNode Pnew=(PNode)malloc(sizeof(Node));
		Pnew->next=NULL;
		printf("第%d个结点的元素为:",i); 
		scanf("%d",&Pnew->data);
		Last->next=Pnew;
		Last=Pnew;
	}	
}
void Print_1_Node(PNode head){
	PNode p=head;
	printf("新的链表为:");
	while(p!=NULL){
		printf("%d ",p->data);
		p=p->next;
	}
	printf("\n");
}
void Print_2_Node(PNode head){
	PNode p=head->next;
	printf("新的链表为:");
	while(p!=NULL){
		printf("%d ",p->data);
		p=p->next;
	}
	printf("\n");
}
int main(){
	PNode H1,H2,H3,H4;
	H1=Init_1_Node();
	Creat_1_Node(&H1);
	Print_1_Node(H1);
	H2=Init_1_Node();
	Creat_2_Node(&H2);
	Print_1_Node(H2);
	H3=Init_2_Node();
	Creat_3_Node(H3);
	Print_2_Node(H3);
	H4=Init_2_Node();
	Creat_4_Node(H4);
	Print_2_Node(H4);
    return 0;
}

5.2 运行结果

单链表的创建,# 《 数据结构与算法 》,数据结构,算法,c语言

六、总结

  综上所述,我们一共有四种创建单链表的方法,其实头插法基本不用,我们用的最多的是尾插法创建带头结点的单链表。

  在创建单链表的时候,要注意几个问题:

1.一定要初始化单链表,不管是带头结点还是不带头结点的单链表,不然会出现输入一半程序终结的情况(暂时不知道是什么情况)

2.创建不带头结点的单链表,要用到指针的指针,否则没法保存地址。

3.创建不带头结点的单链表,一定要先判断头指针是否指向空文章来源地址https://www.toymoban.com/news/detail-717665.html

附:系列文章

序号 文章目录 直达链接
1 顺序表的十个基本操作(全) https://want595.blog.csdn.net/article/details/127139051
2 单链表的十三个基本操作(全) https://want595.blog.csdn.net/article/details/127139598
3 四种创建单链表的方法 https://want595.blog.csdn.net/article/details/127017405
4 删除重复元素(顺序表、单链表) https://want595.blog.csdn.net/article/details/127023468
5 两个有序表的合并(三种方法) https://want595.blog.csdn.net/article/details/127104602
6 一元多项式相加问题(两种方法) https://want595.blog.csdn.net/article/details/127131351
7 约瑟夫环问题(三种方法) https://want595.blog.csdn.net/article/details/127019472
8 顺序栈与链栈 https://want595.blog.csdn.net/article/details/127035609
9 顺序循环队列与链队列 https://want595.blog.csdn.net/article/details/127040115
10 后缀表达式的转换(栈的运用) https://want595.blog.csdn.net/article/details/127088466
11 简单表达式的计算(两种方法) https://want595.blog.csdn.net/article/details/127121720
12 next数组(详细求法) https://want595.blog.csdn.net/article/details/127217629
13 BF算法(具体应用) https://want595.blog.csdn.net/article/details/127138894
14 串的模式匹配相关问题(BF算法、KMP算法) https://want595.blog.csdn.net/article/details/127182721
15 二叉树的遍历(七种方法) https://want595.blog.csdn.net/article/details/127472445

到了这里,关于四种创建单链表的方法的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 数据结构--单链表的定义

    单链表的定义(如何用代码实现) 优点:不要求大片连续空间,改变容量方便 缺点:不可随机存取,要耗费一定空间存放指针 为了方便 我们经常使用 typedef t y p e d e f 数据类型 别名 color{purple}typedef 数据类型 别名 t y p e d e f 数据类型 别名 代码一: 代码二: 代码一与代码二是

    2024年02月11日
    浏览(43)
  • 【数据结构】-- 单链表的实现

    在前面我们学习了顺序表,顺序表在数组的基础上提供了很多现成的方法,方便了我们对数据的管理,但是我们也发现顺序表有着许多不足: 在处理大型的数据时,需要频繁的增容且在中间删除或插入数据时需要遍历顺序表,这些性质导致了顺序表的 效率较低 。这时我们就

    2024年04月27日
    浏览(30)
  • 【数据结构】单链表的层层实现!! !

    关注小庄 顿顿解馋(●’◡’●) 上篇回顾 我们上篇学习了本质为数组的数据结构—顺序表,顺序表支持下标随机访问而且高速缓存命中率高,然而可能造成空间的浪费,同时增加数据时多次移动会造成效率低下,那有什么解决之法呢?这就得引入我们链表这种数据结构 概念

    2024年03月12日
    浏览(35)
  • 【数据结构】单链表的简单实现

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 单链表是一种链式存取的数据结构,用一组地址任意的存储单元存放线性表中的数据元素。链表中的数据是以结点来表示的,每个结点的构成:元素(数据元素的映象) + 指针(指示后继元素存储位置),元

    2024年02月04日
    浏览(41)
  • 数据结构--单链表的插入&删除

    目标 单链表的插入(位插、前插、后插) 单链表的删除 按为序插入(带头结点) ListInsert(L,i,e):插入操作。在表L中的第i个位置上插入指定元素e。 思路:找到第i-1个结点,将新结点插入其后 代码实现 时间复杂度 最好时间复杂度 O(1) 最坏时间复杂度 O(1) 平均时间复杂度 O(1) 按位

    2024年02月07日
    浏览(34)
  • 【数据结构】—— 单链表的增删改查

    ❤️一名热爱Java的大一学生,希望与各位大佬共同学习进步❤️ 🧑个人主页:@周小末天天开心 各位大佬的点赞👍 收藏⭐ 关注✅,是本人学习的最大动力 感谢! 📕该篇文章收录专栏—数据结构 目录 方法重写 重写条件 重写好处 重写演示 单链表 介绍 单链表的增删改查

    2024年02月02日
    浏览(35)
  • 【数据结构】实现单链表的增删查

    链表类和节点类的定义: 图解: 从中间位置插入: 图解:假定index=2 尾插: 删除当前线性表中索引为index的元素,返回删除的元素值: 图解: 删除当前线性表中第一个值为element的元素: 删除当前线性表中所有值为element的元素: 将当前线性表中index位置的元素替换为eleme

    2024年02月14日
    浏览(39)
  • 探索数据结构:单链表的实战指南

    ✨✨ 欢迎大家来到贝蒂大讲堂✨✨ 🎈🎈养成好习惯,先赞后看哦~🎈🎈 所属专栏:数据结构与算法 贝蒂的主页:Betty‘s blog 在上一章节中我们讲解了数据结构中的顺序表,知道了顺序表的空间是连续存储的,这与数组非常类似,为我们随机访问数据提供了便利的条件。但

    2024年03月09日
    浏览(57)
  • 【数据结构】单链表的定义和操作

    目录 1.单链表的定义 2.单链表的创建和初始化 3.单链表的插入节点操作 4.单链表的删除节点操作 5.单链表的查找节点操作 6.单链表的更新节点操作 7.完整代码 🌈嗨!我是Filotimo__🌈。很高兴与大家相识,希望我的博客能对你有所帮助。 💡本文由Filotimo__✍️原创,首发于CS

    2024年02月02日
    浏览(38)
  • 数据结构:单链表的实现(C语言)

    个人主页 : 水月梦镜花 个人专栏 : 《C语言》 《数据结构》 本博客将要实现的无头单向不循环链表。 我们将节点定义为如下结构: 其成员变量有data,next。 将int重命名为STLDataType,方便我们以后修改数据域的内容。 动态申明一个空间,来放置数据。如下: 将data的内容置

    2024年02月14日
    浏览(36)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包