什么是线性表

数据结构中最常用也最简单的应该就是线性表,它是一种线性结构(废话,不是线性结构怎么会叫线性表?当然不是废话,古人公孙龙就说白马非马,现代生物学家也说鲸鱼不是鱼)。

那什么是线性结构?

按数据逻辑结构来划分,数据结构就分为线性结构和非线性结构。

通俗来说就是排成一条线的结构,想象一下你去食堂排队打饭,前面站着一个人,后面也站着一个人,这样的结构就是线性结构。

线性表的定义

线性表就是线性结构的一种(其实其它像栈、队列什么的也可以说是一种特殊的线性表),先看一下线性表的定义:

零个或多个数据元素的有限序列。

零个或多个意味着线性表的数据元素n大于等于0,当n=0时,也就是空表。

有限意味着这个表的数据有限的,计算机中处理的数据都是有限的。

序列也就是说这一组元素是有顺序的,如果没有顺序乱成一团就不是排队而是打架了。



你去食堂打饭,发现来的时间点不对,一个人都没有,这时就是一张空表。于是你在外面转了一圈,回来一看,妈呀,一根烟的时间打饭窗口就站了几十号人,于是你赶快排在最后面,刚站好,你后面又一下站了十几个人。

这时,排在一个的就是第一个元素,排在最后一个的就是最后一个元素,排在你前面的就叫前驱,排你后面叫后继。而排在第一个的人前面已经没人了,所以第一个元素无前驱。同理,排在最后的一个无后继。

你排在中间实在太无聊了,于是数了一下,队伍总共100个人,也就是说线性表当前的长度为100。你又算了一下,从打饭窗口到门口可以排150个人,也就是说理论上队伍最多只能排150个人,150就是线性表的最大存储容量。如果还有人要排进来就要站到门外面了,就会发生数据溢出。

接口定义

后面我们将要介绍到多种实现线性表的方式,但不管哪种方式实现的线性表都是一样的,里面定义方法也是一样的。使用接口可以确保每种方式都实现了相同的操作,方便程序解耦,更利于其它模块调用以及编写单元测试。

下面给出定义的接口:

public interface ILinearList<T>
{
/// <summary>
/// 数组长度
/// </summary>
int Length
{
get;
} /// <summary>
/// 数组是否为空
/// </summary>
/// <returns></returns>
bool IsEmpty(); /// <summary>
///清空表
/// </summary>
void Clear(); /// <summary>
///通过索引获取数据元素
/// </summary>
/// <param name="index"></param>
/// <returns></returns>
T GetItem(int index); /// <summary>
/// 返回数据元素的索引
/// </summary>
/// <param name="t"></param>
/// <returns></returns>
int LocateItem(T t); /// <summary>
/// 将数据元素插入到指定位置
/// </summary>
/// <param name="item"></param>
/// <param name="index"></param>
void Insert(T item, int index); /// <summary>
/// 在数组末尾添加元素
/// </summary>
/// <param name="item"></param>
void Add(T item); /// <summary>
/// 删除指定索引的元素
/// </summary>
/// <param name="index"></param>
void Delete(int index);
}

线性表顺序存储结构

线性表有两种物理结构——顺序存储结构和链式存储结构。我们先来看看顺序存储结构。

顺序存储结构就和前面的排队一样,设计一个排队窗口,定下最多可以排多少人,然后按顺序一个个这么排下去。也就是说在内存中分配一块内存空间,然后把相同数据类型的数据元素依次存放下去。

如何实现

使用一维数组,把第一个数据元素存到数组下标为0的位置中,接着把线性表相邻的元素存储在数组中相邻的位置。

用C#实现,可以直接使用泛型数组。

初始化

首先我们先定义一些属性及字段:

    private T[] list;

    private int length = 0;

    public int MaxSize
{
private set;
get;
} public int Length
{
get { return length; }
}

构建线性表只需要给定数组最大容量(MaxSize)然后将list集合初始化就行了,这些我们可以直接放在构造函数里面:

    public SequentialList(int maxSize)
{
if (maxSize <= 0)
{
throw new Exception("the maxSize can not be less than zero");
}
MaxSize = maxSize;
list = new T[maxSize];
}

元素获取

元素的获取非常简单,直接通过下标返回就可以了:

    public T GetItem(int index)
{
return list[index];
}

添加元素

添加元素直接将数据元素放在数组的末尾(排队时新来一个人直接站在最后就好),并将length加1就行了:

    public void Add(T item)
{
if (isFull()) //判断数组是否已满
{
throw new Exception("This linear list is full");
}
length++;
list[length - 1] = item;
}

将元素插入至指定位置

打饭时,每新来一个人就直接排到队伍的最后面。但是现实却总是不那么美好,总有一些人会来插队。今天你去食堂去晚了,一看队伍已经站了差不多一百个人,所以机智的你看了下队伍的前列,在前面发现了坐在你边上的美女同事,于是赶快和她打个招呼以极其自然的方式插到了她的前面。你的插入对排在美女同事前面的人来说没有任何影响,他们的位置保持不变,但是排在她后面就要相应的全部向后移一个位置:

    public void Insert(T item, int index)
{
if (isFull())
{
throw new Exception("This linear list is full");
}
if (index < 0 || index > length)
{
throw new Exception("Location exception");
}
length++;
for (int i = length - 1; i > index; i--)
{
list[i] = list[i - 1];
}
list[index] = item;
}

删除

你正在排队打饭,突然发现肚子疼,心想总不能等下一边吃进去一边拉出来吧,于是赶快从队伍里退出来奔向洗手间,这个时候,排在你后面的人自然是满脸欢笑地目送你离开,他们所有人都可以往前面移一个位置:

    public void Delete(int index)
{
if (index < 0 || index > length - 1)
{
throw new Exception("Location exception");
}
length--;
for (int i = index; i < length; i++)
{
list[i] = list[i + 1];
}
}

完整代码如下(代码烂,轻拍):

/// <summary>
/// 线性表顺序结构
/// </summary>
public class SequentialList<T> : ILinearList<T>
{
private T[] list; private int length = 0; public int MaxSize
{
private set;
get;
} public int Length
{
get { return length; }
} public SequentialList(int maxSize)
{
if (maxSize <= 0)
{
throw new Exception("the maxSize can not be less than zero");
}
MaxSize = maxSize;
list = new T[maxSize];
} public bool IsEmpty()
{
return length == 0;
} public void Clear()
{
length = 0;
} public T GetItem(int index)
{
return list[index];
} public int LocateItem(T t)
{
for (int i = 0; i < list.Length; i++)
{
if (list[i].Equals(t))
{
return i;
}
}
return -1;
} public void Insert(T item, int index)
{
if (isFull())
{
throw new Exception("This linear list is full");
}
if (index < 0 || index > length)
{
throw new Exception("Location exception");
}
length++;
for (int i = length - 1; i > index; i--)
{
list[i] = list[i - 1];
}
list[index] = item;
} public void Add(T item)
{
if (isFull())
{
throw new Exception("This linear list is full");
}
length++;
list[length - 1] = item;
} public void Delete(int index)
{
if (index < 0 || index > length - 1)
{
throw new Exception("Location exception");
}
length--;
for (int i = index; i < length; i++)
{
list[i] = list[i + 1];
}
} bool isFull()
{
return length >= MaxSize;
}
}

C#实现数据结构——线性表(上)的更多相关文章

  1. [从今天开始修炼数据结构]线性表及其实现以及实现有Itertor的ArrayList和LinkedList

    一.线性表 1,什么是线性表 线性表就是零个或多个数据元素的有限序列.线性表中的每个元素只能有零个或一个前驱元素,零个或一个后继元素.在较复杂的线性表中,一个数据元素可以由若干个数据项组成.比如牵手排 ...

  2. [数据结构-线性表1.2] 链表与 LinkedList<T>(.NET 源码学习)

    [数据结构-线性表1.2] 链表与 LinkedList<T> [注:本篇文章源码内容较少,分析度较浅,请酌情选择阅读] 关键词:链表(数据结构)    C#中的链表(源码)    可空类 ...

  3. C# 数据结构 线性表(顺序表 链表 IList 数组)

    线性表 线性表是最简单.最基本.最常用的数据结构.数据元素 1 对 1的关系,这种关系是位置关系. 特点 (1)第一个元素和最后一个元素前后是没有数据元素,线性表中剩下的元素是近邻的,前后都有元素. ...

  4. C#实现数据结构——线性表(下)

    线性表链式存储结构 看了线性表的顺序存储,你肯定想线性表简是挺简单,但是我一开始怎么会知道有多少人排队?要分配多大的数组?而且插入和删除一个元素也太麻烦了,所有元素都要前移/后移,效率又低. 那怎么办 ...

  5. [置顶] ※数据结构※→☆线性表结构(queue)☆============循环队列 顺序存储结构(queue circular sequence)(十)

    循环队列 为充分利用向量空间,克服"假溢出"现象的方法是:将向量空间想象为一个首尾相接的圆环,并称这种向量为循环向量.存储在其中的队列称为循环队列(Circular Queue). ...

  6. [置顶] ※数据结构※→☆线性表结构(queue)☆============优先队列 链式存储结构(queue priority list)(十二)

    优先队列(priority queue) 普通的队列是一种先进先出的数据结构,元素在队列尾追加,而从队列头删除.在优先队列中,元素被赋予优先级.当访问元素时,具有最高优先级的元素最先删除.优先队列具有 ...

  7. 数据结构-线性表的链式存储相关算法(C语言实现)

    链表的简单介绍 为什么需要线性链表 当然是为了克服顺序表的缺点,在顺序表中,做插入和删除操作时,需要大量的移动元素,导致效率下降. 线性链表的分类 按照链接方式: 按照实现角度: 线性链表的创建和简单 ...

  8. 数据结构----线性表顺序和链式结构的使用(c)

    PS:在学习数据结构之前,我相信很多博友也都学习过一些语言,比如说java,c语言,c++,web等,我们之前用的一些方法大都是封装好的,就java而言,里面使用了大量的封装好的方法,一些算法也大都写 ...

  9. python数据结构——线性表

    线性表 线性表可以看作是一种线性结构(可以分为顺序线性结构,离散线性结构) 1. 线性表的种类: 顺序表 元素存储在一大块连续存储的地址中,首元素存入存储区的起始位置,其余元素顺序存放. (元素之间的 ...

随机推荐

  1. 使用NAT方式连网的linux服务器虚拟机搭建

    从一开始我就很纠结centos服务器搭建的过程. 由于自己方向并不在运维上,但是学习开发也需要用到Linux所以就一直没认真去学. 经过自己多方面摸索与学习找到了自己的一套方法. 首先我用到的是 ce ...

  2. sql的一些小东西

    1.sa账户密码丢失. 先用wiondows验证登陆,然后新建查询 “ ALTER LOGIN [sa] WITH PASSWORD = N'NewPassword' ”

  3. Canvas transform浅析

    没有前奏,直接进入主题 transform调用方法: ctx.transform(a,b,c,d,e,f);如下 var ctx = document.getElementById("myC ...

  4. winapi获取鼠标位置

    using System; using System.Drawing; using System.Runtime.InteropServices; using System.Threading; na ...

  5. oracle中使用minus进行数据排除(类似SqlServer except函数)

    minus这个集合操作符号的作用是从一个结果集合中减掉另一个结果集中数据,也就是说从一个结果集中去除两个结果集中的共有部分. 下面是一些例子: 这个例子使用minus从第一个结果集中将两个结果集的公有 ...

  6. UITabBarController自定义二之xib

    UITabBarController自定义二之xib 新建一个xib文件 在UITabBarController的子类方法viewDidLoad方法中加载xib 1.-(void)viewDidLoa ...

  7. 学习springMVC实例1——配置和跳转到HelloWorld

    本文让大家迅速掌握springMVC的使用方法,以最简单的方式理解此框架 一.用eclipse新建一个web项目,命名为springMVC1,tomcat的端口号为9090 二.在WEB-INF目录下 ...

  8. Java学习----不变的常量

    byte: -128~+127 short int:129 long float:1.5f  (1.5被系统默认为double) double:4.5d char:'s'  '1' boolean:t ...

  9. mysql中explain优化分析

    效率比较  range >index  > all

  10. Delphi Keycode

    Keycode表 字母和数字键的键码值(keyCode) 按键 键码 按键 键码 按键 键码 按键 键码 A 65 J 74 S 83 1 49 B 66 K 75 T 84 2 50 C 67 L ...