数据结构:单链表

文章目录

        • 链表:
        • 单链表的实现及操作:
          • 1.指针描述的单链表L存储结构
          • 2.查找L的第i个元素,将其值赋值给e
          • 3.在L的第i个位置之前插入元素e
          • 4.在L中,删除第i个元素,并返回其值e
          • 5.输入n个元素,建立带头节点的单链表L
          • 6.归并La和Lb的到新单链表Lc,按值非递减排列
        • 链表操作实例及代码:
          • 代码:
          • 运行结果:

链表:

1.链式存储与顺序存储的不同:

顺序存储:逻辑关系上相邻的两元素,物理位置上也相邻。优点:可随机存取表中任一元素,存储位置可以用简单公式表示。缺点:插入删除需要移动大量元素。

链式存储:不要求逻辑关系上相邻的两元素,物理位置上也相邻。优缺点刚好和顺序存储的相反。

2.线性表的链式存储结构的特点:

用一组任意的存储单元存储线性表的数据元素,这组存储单元可以是连续的也可以是不连续的。

我们用结点存储一个数据元素,结点包含两个域,数据域存储数据元素的值,指针域存储直接后继。

链表每个结点中只包含一个指针域的,称为线性链表或单链表。

使用链表时,只需关心数据元素之间的逻辑顺序,无需关心每个数据元素在存储器中的实际位置。

单链表的实现及操作:

1.指针描述的单链表L存储结构

我们这里单链表是带有头结点的单链表,头结点是单链表第一个元素(首元结点)之前的结点,他的数据域可以不存任何信息,也可存链表长度等信息,他的指针域的指针指向第一个元素的结点。

单链表的头指针指向头结点,单链表可由头指针唯一确定,所以接下来我们都用结构指针描述。

如果线性表是空表,头结点的指针域为空,也就是指针指向null。

线性表最后一个结点的指针域里面的指针指向null。

LNode是一个结点类型,它里面有数据域还有指针域。

LinkList是结点指针类型,它可以通过提取结点的next成员指向我们的结点类型。

调用其结构体里面的成员,这里面就涉及到.->操作符的区别了,A->B则A为指针,->是成员提取,A->B是提取A中的成员B,A只能是指向类、结构、联合的指针。A.B则A为对象或者结构体。

接下来我们参数都是结构体指针LinkList,所以一律用->提取结构体里面的成员。

next指针明显指向下一个LNode类型的结点,那么它就是个结构体指针。

头指针L指向头结点,L->next指向首元结点。

如果说L是头指针,那么L指向的是头结点,L->data是头结点的数据域,L->next是头结点的指针域。L->next指向头结点的下一个LNode类型的结点,也就是首元结点,L->next->data是首元结点的数据域,存的是第一个元素的值。

a指针指向b结点,用->提取a指针的成员,提取的是b这个结点的成员。可以看出我们根本没有考虑a指针所在结构体里面的数据域,也就是与a指针相对应的a的数据域里面的元素。也就是说,头指针仅仅充当了指针的作用,通过它,我们能够访问首元结点的成员。

typedef struct LNode
{LElemType_L data;struct LNode* next;
}LNode;
typedef LNode* LinkList;
2.查找L的第i个元素,将其值赋值给e

L是头指针,也就是指向头结点的指针,我们从第一个元素开始查找,所以要先通过头指针L找到指向第一个元素的指针,也就是L->next。方便起见我们用p表示指向第一个元素的指针。然后用一个j表示当前我们找到了第几个元素。p一开始指向第一个元素,所以j初始值赋为1。然后如果p指向null,意味着我们已经找完了链表里面全部元素,此时退出循环,如果i是不符合条件的,i<=0,那么也要退出循环。

退出循环之后我们判断一下,如果p指向null或者j>i,那么就error。反之,意味着是因为j=i而退出的循环,由于之前我们说p一开始指向第一个元素,所以j初始值赋为1,而且p指向下一个元素的同时j也加1,那么p可以认为始终指的是第j个元素。现在j指的i,也就是说p现在指的是第i个元素,那么把e赋给p->data即可。

Status GetElem_L(LinkList L, int i, LElemType_L &e)
{int j;LinkList p ;j = 1;p = L->next;while(p && j<i)	//满足了才循环				{j++;p = p->next;}if(!p || j>i)					return ERROR;e = p->data;return OK; 
}
3.在L的第i个位置之前插入元素e

在第i个位置插入元素的话我们需要找到第i-1个元素的位置,然后将新结点放到第i-1个元素的位置的下一个位置,并将原来的第i个位置放到新结点的下一个位置。这里面插入可以插入到第一个元素之前,所以我们找的第i-1个元素的位置有可能是头结点的位置,那么我们遍历查找的时候就要从头结点开始,上一个函数我们说,p一开始指向第一个元素,所以j初始值赋为1。这里p指向头结点,所以j初值赋为0。然后继续循环。循环结束后判断退出的原因,是因为没找到还是i的值有问题,还是当j=i-1时退出得,满足j=i-1的话再进行插入。

插入一个结点,首先要给这个结点开一个空间,s指针指向这个新的空间,也就是s指针指向新的结点,这里插入的时候如果先把这个结点放到第i-1个结点的后面,那么我们就找不到原来的第i个结点了,因为原来的第i个结点是通过p->next来找到的,然鹅现在p->next指的是新的结点s。

所以我们就不能先更改p->next,而是先把p->next给连接到s的后面,然后再把p->next更新为s。

Status ListInsert_L(LinkList &L, int i, LElemType_L e)
{LinkList p, s;int j;p = L;j = 0; while(p && j<i-1)					//寻找第i-1个结点 {p = p->next;++j;}if(!p || j>i-1)return ERROR;s = (LinkList)malloc(sizeof(LNode));if(!s)exit(OVERFLOW);s->data = e;s->next = p->next;p->next = s;return OK;
}
4.在L中,删除第i个元素,并返回其值e

删除第i个元素,意味着第i-1个元素连到第i+1个元素,我们知道第i-1个元素的位置,也就知道了后面的元素的位置,因此这里还是找第i-1个元素。

这里可以删除第一个元素,因此还是从头结点开始找。这里我们删除第i个元素的话,第i个元素一定要存在,所以判断里面要先判断第i-1个元素的下一个元素是否存在,本来我们是要找第i-1个元素,但是现在我们先查看了第i个元素,而且我们还存了第i-1个元素的位置,那么我们找第i个元素的话,即使退出循环,我们仍然能找到第i-1个元素的位置,这就转化成了,找第i个元素。当然你也可以找第i-1个元素,只不过你要判断,如果它后面没元素,就退出了,而并不是说只要第i-1个元素不为空,就能删。

最后退出了,但是pre存的是第i-1个元素的位置,那么pre->next=pre->next->next即可,这里删去之后还要把被删的结点的空间给释放了,所以先把pre->next存到p里面,然后释放p即可。

Status ListDelete_L(LinkList &L, int i, LElemType_L *e)
{LinkList pre, p; int j;pre = L;j = 1; while(pre->next && j<i)			{pre = pre->next;++j;}if(!pre->next || j>i)			return ERROR;p = pre->next;pre->next = p->next;*e = p->data;free(p);return OK; 
}
5.输入n个元素,建立带头节点的单链表L

首先看头插法,也就是说先插入的在后面,每次插入是插到链表的第一个元素的位置。如果你输入9 8 7 6 5,链表从表头到表尾依次存放5 6 7 8 9。

头插法先要建立一个头结点,L指针指向头结点,L->next是首元结点,一开始是个空链表,所以L->next指向null。输入一个数,放到一个新结点里面,然后把这个结点插到原来的首元结点前面,也就是L->next前面,让他成为新的首元结点,然后由于L->next指向首元结点,所以我们更新L->next,让他指向这个新结点。

再看尾插法,也就是说先插入的在前面。

先建立头结点L,L->next就是第一个元素的位置,起初为null,我们需要引入一个标记q,让他一开始指向头结点,每当插入一个元素p,q的下一个位置就是p的位置,然后让它指向p的位置。这样每次新结点都放到了p后面,而且q又指向最后的那个元素的位置,那么也就说明我们每次都放到了最后的位置。

最终还需让q->next指向null,因为已经插入完了,它没有下一个元素了。

Status CreateList_HL(LinkList &L, int n)
{int i;LinkList p;LElemType_L tmp;L = (LinkList)malloc(sizeof(LNode));if(!L)exit(OVERFLOW);L->next = NULL;							 printf("请输入%d个数:",n);for(i=1; i<=n; ++i){if(scanf("%d", &tmp)==1){p = (LinkList)malloc(sizeof(LNode));if(!p)exit(OVERFLOW);p->data = tmp;						 p->next = L->next;L->next = p;		}elsereturn ERROR;}return OK;
}  Status CreateList_TL(LinkList &L, int n)
{int i;LinkList p, q;LElemType_L tmp;	L = (LinkList)malloc(sizeof(LNode));if(!L)exit(OVERFLOW);L->next = NULL;printf("请输入%d个数:",n);for(i=1,q=L; i<=n; ++i){if(scanf("%d", &tmp)==1){p = (LinkList)malloc(sizeof(LNode));if(!p)exit(OVERFLOW);p->data = tmp;						q->next = p;q = q->next;		}elsereturn ERROR;		}q->next = NULL;return OK;
}
6.归并La和Lb的到新单链表Lc,按值非递减排列

这个就是把La也当成Lc的头结点,然后从第一个元素开始,依次比较La,Lb的当前元素大小。如果小的,那么放到Lc的后面,然后把放过的那个元素所在的链表的指针后移一位。最后如果有一个列表已经遍历完了,那么就把那没被遍历完的列表放到Lc的后面,我们可以看出,Lb的元素全放到了La里面,最后只剩了一个Lb的头结点,所以我们把头结点free掉即可。

void MergeList_L(LinkList &La, LinkList &Lb, LinkList &Lc)
{										LinkList pa, pb, pc;pa = La->next;pb = Lb->next;pc = Lc = La;												while(pa && pb){if(pa->data <= pb->data){pc->next = pa;pc = pa;pa = pa->next;}else{pc->next = pb;pc = pb;pb = pb->next;}	}pc->next = pa ? pa : pb;			free(*Lb);							*Lb = NULL; 
}

链表操作实例及代码:

代码:
#include<cstdio>
#include<cstdlib>#define	OK			1			
#define	ERROR		0	
#define	OVERFLOW	-2			
#define UNDERFLOW	-3	
#define	TRUE		1			
#define	FALSE		0typedef int LElemType_L;
typedef int Status;typedef struct LNode
{LElemType_L data;struct LNode* next;
}LNode;
typedef LNode* LinkList;Status GetElem_L(LinkList L, int i, LElemType_L &e)
{int j;LinkList p = L->next;j = 1;p = L->next;while(p && j<i)					{j++;p = p->next;}if(!p || j>i)					return ERROR;e = p->data;return OK; 
}
Status ListInsert_L(LinkList &L, int i, LElemType_L e)
{LinkList p, s;int j;p = L;j = 0; while(p && j<i-1)					//寻找第i-1个结点 {p = p->next;++j;}if(!p || j>i-1)return ERROR;s = (LinkList)malloc(sizeof(LNode));if(!s)exit(OVERFLOW);s->data = e;s->next = p->next;p->next = s;return OK;
}
Status ListDelete_L(LinkList &L, int i, LElemType_L &e)
{LinkList pre, p; int j;pre = L;j = 1; while(pre->next && j<i)			{pre = pre->next;++j;}if(!pre->next || j>i)			return ERROR;p = pre->next;pre->next = p->next;e = p->data;free(p);return OK; 
}Status CreateList_HL(LinkList &L, int n)
{int i;LinkList p;LElemType_L tmp;L = (LinkList)malloc(sizeof(LNode));if(!L)exit(OVERFLOW);L->next = NULL;						printf("(头插法)请输入%d个数:",n);for(i=1; i<=n; ++i){if(scanf("%d", &tmp)==1){p = (LinkList)malloc(sizeof(LNode));if(!p)exit(OVERFLOW);p->data = tmp;				 p->next = L->next;L->next = p;		}elsereturn ERROR;}return OK;
}  Status CreateList_TL(LinkList &L, int n)
{int i;LinkList p, q;LElemType_L tmp;	L = (LinkList)malloc(sizeof(LNode));if(!L)exit(OVERFLOW);L->next = NULL;printf("(尾插法)请输入%d个数:",n);for(i=1,q=L; i<=n; ++i){if(scanf("%d", &tmp)==1){p = (LinkList)malloc(sizeof(LNode));if(!p)exit(OVERFLOW);p->data = tmp;						q->next = p;q = q->next;		}elsereturn ERROR;		}q->next = NULL;return OK;
}
Status ListTraverse_L(LinkList L, void(Visit)(LElemType_L))
{LinkList p;if(!L)return ERROR;elsep = L->next;	while(p){Visit(p->data);p = p->next;}printf("\n");return OK;
}
void PrintElem(LElemType_L e)
{printf("%d ", e);
}
void MergeList_L(LinkList &La, LinkList &Lb, LinkList &Lc)
{										LinkList pa, pb, pc;pa = La->next;pb = Lb->next;pc = Lc = La;											while(pa && pb){if(pa->data <= pb->data){pc->next = pa;pc = pa;pa = pa->next;}else{pc->next = pb;pc = pb;pb = pb->next;}	}pc->next = pa ? pa : pb;			 free(Lb);							Lb = NULL; 
}
int main()
{LinkList La, Lb, Lc ;int m,i;									LElemType_L e;m = 5;printf("作为示例,La长度设定为 %d ,Lb设定为 %d ,创建La和Lb...\n", m, m);CreateList_HL(La, m);CreateList_TL(Lb, m);	printf("La = ");ListTraverse_L(La, PrintElem);printf("Lb = ");ListTraverse_L(Lb, PrintElem);printf("\n");MergeList_L(La, Lb, Lc);printf("合并La和Lb为Lc = ");ListTraverse_L(Lc, PrintElem);printf("\n");ListDelete_L(Lc, 6, e);printf("删除 Lc 中第 6 个元素 \"%d\" ...\n", e);printf(" Lc 中的元素为:Lc = ");						 ListTraverse_L(Lc, PrintElem);printf("\n");GetElem_L(Lc, 4, e);printf(" Lc 中第 4 个位置的元素为 \"%d\" \n", e);printf("\n");for(i=1; i<=6; i++)									{printf("在 Lc 第 %d 个位置插入 \"%d\" ...\n", i, 2*i);ListInsert_L(Lc, i, 2*i);}printf(" Lc 中的元素为:Lc = ");						 ListTraverse_L(Lc, PrintElem);printf("\n");return 0;
}
运行结果:

输入:

9 7 5 3 1

2 4 6 8 10

输出:

作为示例,La长度设定为 5 ,Lb设定为 5 ,创建La和Lb…
(头插法)请输入5个数:9 7 5 3 1
(尾插法)请输入5个数:2 4 6 8 10
La = 1 3 5 7 9
Lb = 2 4 6 8 10

合并La和Lb为Lc = 1 2 3 4 5 6 7 8 9 10

删除 Lc 中第 6 个元素 “6” …
Lc 中的元素为:Lc = 1 2 3 4 5 7 8 9 10

Lc 中第 4 个位置的元素为 “4”

在 Lc 第 1 个位置插入 “2” …
在 Lc 第 2 个位置插入 “4” …
在 Lc 第 3 个位置插入 “6” …
在 Lc 第 4 个位置插入 “8” …
在 Lc 第 5 个位置插入 “10” …
在 Lc 第 6 个位置插入 “12” …
Lc 中的元素为:Lc = 2 4 6 8 10 12 1 2 3 4 5 7 8 9 10

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/560551.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

mysql离散查询_如何写出高性能的MySQL查询

作者&#xff1a;会写代码的猪 发布时间&#xff1a;December 25, 2009 分类&#xff1a;猪在写代码想写这样一篇文章很久了&#xff0c;但始终没有下手。最近帮同事看了几个查询&#xff0c;而且自己也在考虑一个索引系统的问题&#xff0c;所以今天就把这个写了。介绍一下MyS…

计算机中丢失msc,mscvr120.dll32位/64位版_修复计算机中丢失msvcr120.dll

mscvr120.dll32位/64位版_修复计算机中丢失msvcr120.dllmscvr120.dll是系统的非常重要的一个文件&#xff0c;相信很多的人都是遇到文件丢失的情况&#xff0c;这个时候就需要你在下载一个dll文件使用了&#xff01;现在就为大家提供最新的dll文件下载&#xff0c;需要的可以看…

mysql解压缩版配置_MySQL 5.6 for Windows 解压缩版配置安装

1、MySQL安装文件分为两种&#xff0c;一种是msi格式的&#xff0c;一种是zip格式的。如果是msi格式的可以直接点击安装&#xff0c;按照它给出的安装提示进行安装(相信大家的英文可以看懂英文提示)&#xff0c;一般MySQL将会安装在C:\Program Files\MySQL\MySQL Server 5.6 该…

数据结构:顺序栈

文章目录栈&#xff1a;顺序栈的实现及操作&#xff1a;1.定义一个栈2.构造一个空栈3.取栈顶元素4.插入元素e5.删除栈顶元素&#xff0c;返回其值6.清空栈&#xff0c;销毁栈栈的操作实例及代码&#xff1a;栈&#xff1a; 从数据结构上来看&#xff0c;栈也是线性表&#xff…

计算机二级考试开考多久能出来,【计算机二级】明天就要开考了,你们准备好了吗?...

原标题&#xff1a;【计算机二级】明天就要开考了&#xff0c;你们准备好了吗&#xff1f;计算机二级考试马上要来了现在距离考试只有不到几个小时的时间了不知道各位同学准备的怎么样了呢&#xff1f;人有多大胆&#xff0c;复习拖多晚但这可不是什么好习惯奔赴“战场”之前先…

mysql面试题 高级_高级MySQL数据库面试问题 附答案

mysql -u USER_NAME -xml -e SELECT * FROM table_name > table_name.xml上面的例子中USER_NAME是数据库的用户名&#xff0c;table_name是待导出为xml文件的表名&#xff0c;table_name.xml是存放数据的xml文件9. MySQL_pconnect是什么? 它和MySQL_connect有什么区别?答&…

办公室中有一台计算机连接打印机,办公室就一个打印机,怎么让多个电脑一起用...

中小型企业的办公室一般只配一台打印机&#xff0c;每次打印东西都要把文件拷在U盘再转到连接打印机的那台电脑&#xff0c;很麻烦。那么怎么才能实现打印机多台电脑共享呢&#xff1f;以下把连接打印机的电脑成为“主电脑”&#xff0c;把需要的共享的电脑叫“客电脑”。1.设置…

数据结构:单链队列

文章目录队列&#xff1a;单链队列的实现及操作&#xff1a;1.定义一个队列2.构造一个空队列3.销毁队列4.插入元素e到队尾5.删除队头元素&#xff0c;用e返回其值单链队列操作实例及代码&#xff1a;队列&#xff1a; 队列是先进先出的线性表。 队列只允许在表的一端插入元素…

php修改mysql数据找不到_php 如何修改mysql数据

PHP MYSQL 修改删除数据创建userinfo_update.php&#xff0c;用于查询用户信息&#xff0c;先显示信息&#xff0c;在修改&#xff1a;先通过GET获取用户编号查询用户信息&#xff1a;$sql "select * from user_info where user_id".$_GET[userId]."";$re…

人工智能训练机器人的服务器,人工智能系统教会机器人如何在荒野中行走

对救援人员和户外运动爱好者来说&#xff0c;穿越荒野小径是一项有用的技能&#xff0c;但对机器人来说却很难。这并不是说这些机械动物没有能力在爬上山坡的同时避开倒下的树枝——最先进的机器学习算法可以做到这一点。问题在于它们缺乏通用性&#xff1a;人工智能驱动的机器…

(递归)猴子吃桃

题目&#xff1a; 猴子买一堆桃不知个数&#xff0c;每天吃桃子一半多一个&#xff0c;第n天只剩一个桃&#xff0c;问一开始买了几个桃。输入整数n(2<n<30)。输出买的桃的数量。 样例输入2&#xff0c;输出4。 样例输入3&#xff0c;输出10。 分析与解答&#xff1a; …

世界手机号码格式_脑炎康复之旅——世界脑炎日病友征文

○○脑炎康复之旅世界脑炎日病友征文2月22日是世界脑炎日(World Encephalitis Day)。2014年发起的世界脑炎日旨在致敬和鼓励全世界经历过脑炎的患者和脑炎医疗工作者。几年来&#xff0c;全球已有1.87亿人次参与世界脑炎日活动。2021年的世界脑炎日即将到来&#xff0c;今年世界…

pythoni手机版下载_Python进度栏和下载

已更新您的示例网址&#xff1a;我刚刚为此编写了一种超级简单的方法(将其略微修改)&#xff0c;以将pdfs刮出某个站点。 请注意&#xff0c;由于Powershell无法处理“ \ r”&#xff0c;因此只能在基于UNIX的系统(Linux&#xff0c;Mac OS)上正常运行import requestslink &qu…

(递归)斐波那契数列

题目 f1f21,fnafn−1bfn−2(n>2)f1f21,f_naf_{n-1}bf_{n-2}(n>2)f1f21,fn​afn−1​bfn−2​(n>2) 输入包含四个整数n(1≤n≤100),a(1≤a≤10),b(1≤a≤10),p((1≤a≤2000)。n(1\leq n \leq 100),a(1\leq a \leq 10),b(1\leq a \leq 10),p((1\leq a \leq 2000)。n(1≤…

树莓派和微信和服务器,用树莓派搭建微信公共平台

1、首先你需要一个公网ip&#xff0c; 需要做好映射&#xff0c; 把80端口映射到你的树莓派ip。2、打开你的树莓派终端&#xff0c; 创建文件夹“templates ” 和文件“weixind.py”。3、文件“weixind.py”中写入以下代码。安装“sudo apt-get install python-lxml”。5、申请…

mysql数据异常增长_mysql表到一定数据量后会异常的增长

如题InnoDB的table&#xff0c;里面的字段非常简单&#xff0c;如图中的类型才100多W的数据量&#xff0c;数据是慢慢积累起来的&#xff0c;到了最近发现涨到12G后&#xff0c;会每天成倍的增长&#xff0c;最高到达过50G&#xff0c;而数据量还是那些&#xff0c;longtext的字…

(递归)快速幂

题目 xyx^yxy当y很大&#xff0c;采用如下方式 {f(x,y2)f(x,y2),(y%20,y>0)1,y0f(x,y2)f(x,y2)x,(y%21,y>0)\left\{\begin{matrix} &amp; f(x,\frac{y}{2})\times f(x,\frac{y}{2}),(y\%20,y>0)\\ &amp; 1,y0\\ &amp; f(x,\frac{y}{2})\times f(x,\frac{y…

舰r4月28服务器维护,崩坏3 11月28日版本更新维护通知

亲爱的舰长&#xff1a;为了给舰长更好的游戏体验&#xff0c;休伯利安号将在11月28日进行版本更新维护&#xff0c;维护完成后战舰将更新为3.6版本——「绯夜霞隐」。维护时间安卓国服、iOS服和各渠道服&#xff1a;11月28日07:00~12:00全平台服(桌面服)&#xff1a;11月28日0…

ec200s 方案 移远_移远 4G Cat 1 无线通信模块EC200S

EC200S 是移远通信最近推出的LTE Cat 1 无线通信模块&#xff0c;支持最大下行速率10Mbps 和最大上行速率5Mbps&#xff0c;具有超高的性价比&#xff1b;同时在封装上兼容移远通信多网络制式LTE Standard EC2x(EC25、EC21、EC20 R2.0、EC20 R2.1)和EC200T/EG25-G/EG21-G 模块以…

(递归)弹簧板

题目 现在n个弹簧板&#xff0c;小球从第i个弹簧板落下&#xff0c;可以向前弹a[i-1]个距离或者b[i-1]个距离&#xff0c;现在从第一个弹簧板落下&#xff0c;计算弹多少次&#xff0c;弹出弹簧板。(1≤n≤200),(0<a[i],b[i]≤30)(1 \leq n \leq 200),(0 < a[i],b[i]\le…