码迷,mamicode.com
首页 > 其他好文 > 详细

数据结构(一)线性表

时间:2019-01-16 23:57:38      阅读:362      评论:0      收藏:0      [点我收藏+]

标签:get   除了   链式   从后往前   alt   引用   src   link   简单   

线性表

基本概念

  线性表是一种线性结构,在一个线性表中数据元素的类型是相同的,或者说线性表是由 同一类型的数据元素构成的线性结构。

  定义:线性表是具有相同数据类型的n(n≥0)个数据元素的有限序列,通常记为: (a1,a2,… ai-1,ai,ai+1,…an) 其中n为表长, n=0 时称为空表。 需要说明的是:ai为序号为 i 的数据元素(i=1,2,…,n),通常将它的数据类型抽象为 ElemType,ElemType根据具体问题而定。

线性表的实现

1、线性表的顺序存储结构

(1)顺序表

  线性表的顺序存储是指在内存中用地址连续的一块存储空间顺序存放线性表的各元素, 用这种存储形式存储的线性表称其为顺序表。

  设a1的存储地址为Loc(a1),每个数据元素占d个存储地址,则第i个数据元素的地址为: Loc(a i)=Loc(a1)+(i-1)*d 1≤i≤n 这就是说只要知道顺序表首地址和每个数据元素所占地址单元的个数就可求出第i个数 据元素的地址来,这也是顺序表具有按数据元素的序号随机存取的特点。

(2)顺序表上基本运算的实现

  顺序表的初始化:顺序表的初始化即构造一个空表,这对表是一个加工型的运算,因此,将L设为引用参数, 首先动态分配存储空间,然后,将length置为0,表示表中没有数据元素。

  顺序表的插入运算

线性表的插入是指在表的第i(i的取值范围: 1≤i≤n+1)个位置上插入一个值为 x 的新元素, 插入后使原表长为 n的表成为表长为 n+1 表。

顺序表上完成这一运算则通过以下步骤进行: ① 将ai~an 顺序向下移动,为新元素让出位置;(注意数据的移动方向:从后往前依次 后移一个元素) ② 将 x 置入空出的第i个位置; ③ 修改表长。

?   删除运算

线性表的删除运算是指将表中第 i (i 的取值范围为 :1≤ i≤n)个元素从线性表中去掉, 删除后使原表长为 n 的线性表成为表长为 n-1 的线性表。

顺序表上完成这一运算的步骤如下: ① 将ai+1~an 顺序向上移动;(注意数据的移动方向:从前往后依次前移一个元素) ② 修改表长。

顺序表的删除运算与插入运算相同,其时间主要消耗在了移动表中元素上。

2、线性表的链式存储结构

  单链表

表示 :链表是通过一组任意的存储单元来存储线性表中的数据元素的。为建立起数据元素之间 的线性关系,对每个数据元素ai,除了存放数据元素的自身的信息 ai 之外,还需要和ai一起 存放其后继 ai+1 所在的存储单元的地址,这两部分信息组成一个“结点”。其中,存放数据元素信息的称为数据域,存放其后继地址的称为指针域。

单链表上基本运算的实现

  建立单链表:

●头插法——在链表的头部插入结点建立单链表

  链表与顺序表不同,它是一种动态管理的存储结构,链表中的每个结点占用的存储空间 不是预先分配,而是运行时系统根据需求而生成的,因此建立单链表从空表开始,每读入一 个数据元素则申请一个结点,然后插在链表的头部。

●尾插法——在单链表的尾部插入结点建立单链表

  头插入建立单链表简单,但读入的数据元素的顺序与生成的链表中元素的顺序是相反的, 若希望次序一致,则用尾插入的方法。因为每次是将新结点插入到链表的尾部,所以需加入 一个指针 r 用来始终指向链表中的尾结点,以便能够将新结点插入到链表的尾部。

头结点的加入会带来以下两个优点

  第一个优点:由于开始结点的位置被存放在头结点的指针域中,所以在链表的第一个位 置上的操作就和在表的其它位置上的操作一致,无需进行特殊处理;

  第二个优点:无论链表是否为空,其头指针是指向头结点在的非空指针(空表中头结点 的指针域为空),因此空表和非空表的处理也就统一了。

查找操作:

●按序号查找 Get_LinkList(L,i)

  从链表的第一个元素结点起,判断当前结点是否是第i个,若是,则返回该结点的指针, 否则继续后一个,表结束为止,没有第i个结点时返回空。

插入运算

●后插结点:设p指向单链表中某结点,s指向待插入的值为x的新结点,将s插入到p的 后面。

  操作如下: ①s->next=p->next; ②p->next=s; 注意:两个指针的操作顺序不能交换。

删除运算

●删除结点 设p指向单链表中某结点,删除p。要实现对结点p的删除,首先要找到 p的前驱结点q,然后完成指针的操作即可。

  操作如下:①q=L; while (q->next!=p) q=q->next; //找*p的直接前驱

?        ②q->next=p->next; free(p);

循环链表

  对于单链表而言,后一个结点的指针域是空指针,如果将该链表头指针置入该指针域, 则使得链表头尾结点相连,就构成了单循环链表。

双向链表

  每个结点再加一个指向前驱的指针域,用这种结点组成的链表称为双向链表。

双向链表中结点的插入:设 p 指向双向链表中某结点,s 指向待插入的值为 x 的新结点, 将s 插入到p 的前面。

  操作如下: ① s->prior=p->prior; ② p->prior->next=s; ③ s->next=p; ④ p->prior=s;

指针操作的顺序不是唯一的,但也不是任意的,操作①必须要放到操作④的前面完成, 否则*p 的前驱结点的指针就丢掉了。

双向链表中结点的删除:设 p 指向双向链表中某结点,删除*p。

操作如下: ①p->prior->next=p->next; ②p->next->prior=p->prior; free(p);

顺序表和链表的比较

顺序表 单链表
以地址相邻表示关系 用指针表示关系
随机访问,取元素O(1) 顺序访问,取元素O(n)
插入、删除需要移动元素O(n) 插入、删除不用移动元素O(n)(用于查找位置)


技术分享图片

  总之,两种存储结构各有长短,选择那一种由实际问题中的主要因素决定。通常“较稳定” 的线性表选择顺序存储,而频繁做插入删除的即动态性较强的线性表宜选择链式存储。

数据结构(一)线性表

标签:get   除了   链式   从后往前   alt   引用   src   link   简单   

原文地址:https://www.cnblogs.com/ST-2017/p/10280025.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!