利用单链表存储一元多项式_线性表之链式存储结构

169a1992061a646eeaec00fed4a81d92.png

线性表顺序存储结构的特点是,在逻辑关系上相邻的两个元素在物理位置上也是相邻的,因此可以随机存取表中任一元素。但是,当经常需要做插入和删除操作时,则需要移动大量的元素,而采用链式存储结构就可以避免这些移动。由于链式存储结构存储线性表数据元素的存储空间可能是连续的,也可能是不连续的,所以链表的结构是不可以随机存取的。链式存储是最常用的存储方式之一,不仅可以用来表示线性表,也可以用来表示各种非线性的数据结构。

db05f0d890ab9485cc43400ae44b9686.png

1、单链表

在使用链式存储结构表示每个数据元素ai时(i是元素的下角标),除了保存ai信息本身以外,还要 一个存储指示其后继元素a(i+1)存储位置的指针,由这两个部分组成元素ai的存储映像通常称之为结点。它包括两个域:存储数据元素的域称为数据域,存储直接后继存储地址的域称为指针域。 即一个结点的存储结构为(data+next)如图: 7e5b9ffe043f8fb24081036684b332c8.png n个结点链成一个链表,即为线性表的链式存储结构。由于每个结点只包含一个指针域,所以称之为单链表。 如图: 76bfc734e0a5f7efa219757447905e47.png

头指针和头节点

头指针:指链表指向第一个结点的指针,若链表有头结点,则是指向头结点的指针。头节点分为两种:
  • 真实头节点:存储数据
  • 虚拟头节点:不存储数据
10bcffbc636a92b10a3a90b03a617c14.png 2311002f8f9bb2a3a368cfa2a3930f70.png

尾指针

尾指针表示该链表最后一个结点的位置,存储的是最后一个结点的地址。尾指针便于从尾部插入数据的效率,有了尾指针可以直接获取最后一位元素的指针域,然后指向新插入的结点,就完成了数据的插入。 09027db561107244d3eed7d5fecbfc2a.png

线性表链式存储结构(LinkedList)类图

由下面的类图我们可以看出,单链表也是实现了List接口,LinkedList为实现类,并增加了一个Node类。 3fc7562bd42819f69b4a42740a3e9df1.png 链表插入方法 判断指定角标位置,就分为头插,尾插,中间插三种情况。 头插,只需将头指针指向新结点,然后让新结点指向原先的第一个元素。 尾插,先让尾指针元素指向新结点,然后将尾指针向后移一位。 中间插,先通过指定的角标进行遍历,找到插入角标的前一个元素,然后让前一个元素指向新结点,新结点指向当前角标位置的元素。 头插法: e2773bca8c716350cb3753de3e3fbcf8.gif 尾插法: b62e52e9ba36c23455abf477c1ec0d55.gif 一般插入: 89259c0885cfa47c447c77d64e75cc15.gif 链表的删除方法 有三种情况 如果是表头位置,则简单,不需要遍历,让头指针指向第二个元素即可。 如果是表尾位置,则需要通过遍历获取倒数第二个元素,然后让这个元素指向空,并让尾指针向前移一位 如果是中间位置,则需要对链表进行循环遍历找到指向角标的前一个元素,然后让这个元素指向删除元素的下一个元素,并让被删除元素指向为空,值为空。 头删: 34caecdfff435c0089ac1c82fd7d12d8.gif 尾删: 771c8c6e6a2aa6e373a71da22b135b8f.gif 一般删除: e0a39117f1df1d8a308d65fb1fe66130.gif db05f0d890ab9485cc43400ae44b9686.png

2、循环链表

循环链表是链式存储结构的另一种形式。它的特点是单链表最后一个结点(终端结点)的指针域不为空,而是指向链表的头结点,使整个链表构成一个环。 循环链表的结点类型与单链表完全相同,在操作上也基本一致,差别仅在于算法中循环的判断条件不再是p或者p->next为空,而是他们是否等于头指针。 如图: a410f27af81ef7f8df5b5d4f7a4c025c.png

循环链表实现约瑟夫环

约瑟夫环问题,是一个经典的循环链表问题,题意是:已知 n 个人(分别用编号 1,2,3,…,n 表示)围坐在一张圆桌周围,从编号为 k 的人开始顺时针报数,数到 m 的那个人出列;他的下一个人又从 1 开始,还是顺时针开始报数,数到 m 的那个人又出列;依次重复下去,直到圆桌上剩余一个人。 如图 所示,假设此时圆周周围有 5 个人,要求从编号为 3 的人开始顺时针数数,数到 2 的那个人出列: c92486da1e046679ce858482b66a9ef8.png

出列顺序依次为:

  • 编号为 3 的人开始数 1,然后 4 数 2,所以 4 先出列;

  • 4 出列后,从 5 开始数 1,1 数 2,所以 1 出列;

  • 1 出列后,从 2 开始数 1,3 数 2,所以 3 出列;

  • 3 出列后,从 5 开始数 1,2 数 2,所以 2 出列;

  • 最后只剩下 5 自己,所以 5 胜出。

    约瑟夫环问题有多种变形,比如顺时针转改为逆时针等,虽然问题的细节有多种变数,但解决问题的中心思想是一样的,即使用循环链表。

db05f0d890ab9485cc43400ae44b9686.png

3、双向链表

若是希望从表中快速确定一个结点的直接前驱,只需要在单链表的结点类型中增加一个指向其直接前趋的指针域prior即可,这样就形成链表中有两条不同方向的链,因此成为双向链表。

双向链表的结点表示:

cb112727eb624cafd9d29f2d9e96aaec.png 双向链表: fd2c38b2b46e4245b0974238c129da71.png 双向链表中插入结点: 9326e8cade36839d023ad7c478d950a5.png双向链表删除结点:与删除结点反之。 遍历链表,找到要删除的结点,然后利用该结点的两个指针域完成删除操作。 db05f0d890ab9485cc43400ae44b9686.png

4、双向循环链表

其实就是双向链表和循环链表的结合体,对于新的约瑟夫环问题,需要将循环链表和双向链表结合使用,组成:双向循环链表。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
符号多项式的操作,已经成为表处理的典型用例。在数学上,一个一元多项式Pn(x)可按升幂写 成: Pn(x) = p0+ p1x+ p2x2+….+ pnxn 它由n+1个系数唯一确定,因此,在计算机里,它可用一个线 性表P来表示: P = (p0 ,p1 ,p2 ,… pn)每一项的指数i隐含在其系数pi的序号里。 假设Qm(x)是一元m次多项式,同样可用线性表Q来表示:Q = (q0 ,q1 ,q2 ,… qm)。 不失一般性,设m<n,则两个多项式相加的结果 Rn(x) = Pn(x)+Qm(x)可用线性表R表示:R = (p0+q0 , p1+q1 , p2 +q2 , … , pm +qm , pm+1 ,… pn)。显然,我们可以对P、Q和R采用顺序存储结构, 使得多项式相加的算法定义十分简洁。至此,一元多项式的表示及相加问题似乎已经解决了。 然而在通常的应用中,多项式的次数可能很高且变化很大,使得顺序存储结构的最大长度很难 决定。特别是在处理形如:S(x) = 1+3x10000+2x20000的多项式时,就要用一长度为20001的线性表来 表示,表中仅有三个非零元素,这种对内存间的浪费是应当避免的,但是如果只存储非零系数项 则显然必须同时存储相应的指数。 一般情况下的一元n次多项式可写成: Pn(x) = p1x e1 + p2x e2 + … + pmx em 其中 pi,是指数为 ei 的项的非零系数,且满足 0 ≤ e1 < e2 < …< em = n,若用一个长度为 m 且 每个元素有两个数据项(系数项和指数项)的线性表便可唯一确定多项式 Pn(x)。 ((p1 ,e1) , (p2 ,e2) , … ,(pm,em)) 在最坏情况下,n+1(=m)个系数都不为零,则比只存储每项系数的方案要多存储一倍的数据。但 是,对于 S(x)类的多项式,这种表示将大大节省间。 本题要求选用线性表的一种合适的存储结构来表示一个一元多项式,并在此结构实现一元多 项式的加法,减法和乘法操作

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值