1.顺序表

只考虑线性表的基本操作,所以以C#接口的形式表示线性表,接口中的方法成员表示基本操作。

1.1 公共接口

    public interface IListDS<T>{T this[int index] { get; }   //索引器int GetLength();             //求长度 void Clear();                //清空操作 bool IsEmpty();              //判断线性表是否为空 void Append(T item);         //附加操作 void Insert(T item, int i);  //插入操作 T Delete(int i);             //删除操作 T GetElem(int i);            //取表元 int Locate(T value);         //按值查找 }

为了和.NET框架中的接口IList相区分,在IList后面加了“DS”,“DS”表示数据结构。
1、求长度:GetLength()
初始条件:线性表存在;
操作结果:返回线性表中所有数据元素的个数。

2、清空操作:Clear()
初始条件:线性表存在且有数据元素;
操作结果:从线性表中清除所有数据元素,线性表为空。

3、判断线性表是否为空:IsEmpty()
初始条件:线性表存在;
操作结果:如果线性表为空返回true,否则返回false。

4、附加操作:Append(T item)
初始条件:线性表存在且未满;
操作结果:将值为item的新元素添加到表的末尾。

5、插入操作:Insert(T item, int i)
初始条件:线性表存在,插入位置正确()(1≤i≤n+1,n为插入前的表长)。
操作结果:在线性表的第i个位置上插入一个值为item的新元素,这样使得原序号为i,i+1,…,n的数据元素的序号变为i+1,i+2,…,n+1,插入后表长=原表长+1。

6、删除操作:Delete(int i)
初始条件:线性表存在且不为空,删除位置正确(1≤i≤n,n为删除前的表长)。
操作结果:在线性表中删除序号为i的数据元素,返回删除后的数据元素。
删除后使原序号为i+1,i+2,…,n的数据元素的序号变为i,i+1,…,n-1,删除后表长=原表长-1。

7、取表元:GetElem(int i)
初始条件:线性表存在,所取数据元素位置正确(1≤i≤n,n为线性表的表长);
操作结果:返回线性表中第i个数据元素。

8、按值查找:Locate(T value)
初始条件:线性表存在。
操作结果:在线性表中查找值为value的数据元素,其结果返回在线性表中首次出现的值为value的数据元素的序号,称为查找成功;否则,在线性表中未找到值为value的数据元素,返回一个特殊值表示查找失败。

1.2 实现类 SeqList

    /// <summary>/// 顺序表/// </summary>/// <typeparam name="T"></typeparam>public class SeqList<T> : IListDS<T>{private int count = 0;         //顺序表的容量 private T[] data;            //数组,用于存储顺序表中的数据元素 private int last;             //指示顺序表最后一个元素的位置 //索引器public T this[int index]{get { return data[index]; }set { data[index] = value; }}public SeqList(int size){data = new T[size];count = 0;}public SeqList():this(10){}public int GetLength(){return count;}public void Clear(){this.count = 0;}public bool IsEmpty(){return count == 0;}public void Append(T item){if (count == data.Length)// 当前数组存满{Console.WriteLine("List is full");}else{data[count] = item;count++;}}public void Insert(T item, int i){if (count == data.Length)// 当前数组存满{Console.WriteLine("List is full");}else{//这里因为从插入位置往后覆盖,第1个被覆盖索引数据就不见了。所以需要从最后面往前覆盖for (int j = count-1; j >= i; j--){data[j + 1] = data[j];}data[i] = item;count++;}}public T Delete(int i){T temp = data[i];for (int j = i+1; j < count; j++){data[j - 1] = data[j];}count--;return temp;}public T GetElem(int i){//索引存在if (i >= 0 && i <= count-1){return data[i];}else{Console.WriteLine("索引不存在");return default(T);}}public int Locate(T value){for (int i = 0; i < data.Length; i++){if (value.Equals(data[i])){return i;}}return -1;}}

1.3 测试:

class Program{static void Main(string[] args){SeqList<string> seqList = new SeqList<string>();seqList.Append("123");seqList.Append("456");seqList.Append("789");Console.Write("第一次加载:");for (int i = 0; i < seqList.GetLength(); i++){Console.Write($"{seqList[i]},");}Console.WriteLine();Console.WriteLine($"第0位置元素:{seqList.GetElem(0)}");Console.WriteLine($"第0索引:{seqList[0]}");Console.Write("Insert后的数据:");seqList.Insert("999", 1);for (int i = 0; i < seqList.GetLength(); i++){Console.Write($"{seqList[i]},");}Console.WriteLine();Console.Write("Delete(0)后的数据:");seqList.Delete(0);for (int i = 0; i < seqList.GetLength(); i++){Console.Write($"{seqList[i]},");}Console.WriteLine();Console.Write("清空后:");seqList.Clear();Console.WriteLine(seqList.GetLength());Console.Read();}}

2.链表

2.1 单链表

在对顺序表进行插入和删除时,需要通过移动数据元素来实现,影响了运行效率。本节介绍线性表的另外一种存储结构——链式存储(Linked Storage),这样的线性表叫链表(Linked List)。链表不要求逻辑上相邻的数据元素在物理存储位置上也相邻,因此,在对链表进行插入和删除时不需要移动数据元素,但同时也失去了顺序表可随机存储的优点。

2.1.1 单链表的存储

链表是用一组任意的存储单元来存储线性表中的数据元素(这组存储单元可以是连续的,也可以是不连续的)。那么,怎么表示两个数据元素逻辑上的相邻关系呢?即如何表示数据元素之间的线性关系呢?为此,在存储数据元素时,除了存储数据元素本身的信息外,还要存储与它相邻的数据元素的存储地址信息。这两部分信息组成该数据元素的存储映像(Image),称为结点(Node)。把存储据元素本身信息的域叫结点的数据域(Data Domain),把存储与它相邻的数据元素的存储地址信息的域叫结点的引用域(Reference Domain)。因此,线性表通过每个结点的引用域形成了一根“链条”,这就是“链表”名称的由来。

如果结点的引用域只存储该结点直接后继结点的存储地址,则该链表叫单链表(Singly Linked List)。把该引用域叫 next。单链表结点的结构如图所示,图中 data 表示结点的数据域。

2.1.2 链式存储结构

插入的情况解析

2.1.3 节点类 Node

新建节点类,注意data与next

// <summary>/// 单链表节点/// </summary>/// <typeparam name="T"></typeparam>public class Node<T>{public T data { get; set; }          //(数据域),存储数据本身public Node<T> next { get; set; }    //(引用域)指针,用来指向下一个元素public Node(T data){this.data = data;this.next = null;}public Node(Node<T> next){this.next = next;}public Node(T data, Node<T> next){this.data = data;this.next = next;}}

2.1.4 实现类 SingleLinkList

/// <summary>/// 单链表/// </summary>/// <typeparam name="T"></typeparam>class SingleLinkList<T> : IListDS<T>{private Node<T> header;public int GetLength(){Node<T> p = header;int len = 0;while (p != null){++len;p = p.next;}return len;}public void Clear(){header = null;}public bool IsEmpty(){return header == null;}public void Append(T item){Node<T> newNode = new Node<T>(item);//如果头节点为空,新节点为头节点if (header == null){header = newNode;}else{Node<T> headNode = header;//下个节点为空时,说明是末尾节点。while (headNode.next != null){headNode = headNode.next;}//把需要添加的node,添加给末尾指针nextheadNode.next = newNode;}}public void Insert(T item, int i){//从第1个节点开始if (i == 0){//头节点不允许插入Console.WriteLine("List is empty or Position is error");}else if (i == 1){//如果是第1个节点Node<T> newNode = new Node<T>(item);newNode.next = header.next;header.next = newNode;}else{Node<T> tempNode = header;int j = 1;//让temp从头开始向后移动到下一个位置,移动到插入前一个位置为止。while (tempNode.next != null && j < i){tempNode = tempNode.next;j++;}if (j == i){Node<T> newNode = new Node<T>(item); //行插入节点Node<T> preNode = tempNode;          //前节点Node<T> currentNode = tempNode.next; //当前节点newNode.next = currentNode;          //插入节点的指针preNode.next = newNode;              //前节点指针}}}public T Delete(int i){//从第1个节点开始if (i == 0){T current = header.data;header = header.next;return current;}else{Node<T> tempNode = header;int j = 1;//让temp从头开始向后移动到下一个位置,移动到插入前一个位置为止。while (tempNode.next != null && j < i){tempNode = tempNode.next;j++;}if (j == i){Node<T> preNode = tempNode;          //前节点Node<T> currentNode = preNode.next;          //前节点Node<T> nexNode = tempNode.next.next; //下一个节点preNode.next = nexNode;              //前节点指针return currentNode.data;}return default(T);}}public T GetElem(int i){return this[i];}public int Locate(T value){if (IsEmpty()){return -1;}else{Node<T> p = header;int i = 1;while (!p.data.Equals(value) && p.next != null){p = p.next;++i;}return i;}}public T this[int index]{get{Node<T> p = header;int len = 0;while (p != null && len < index){++len;p = p.next;}return p.data;}}public override string ToString(){StringBuilder builder = new StringBuilder();builder.Append("单链表:");Node<T> p = header;int len = 0;while (p != null){builder.Append($"{p.data.ToString()},");++len;p = p.next;}return builder.ToString();}}

2.1.5 测试

    class Program{static void Main(string[] args){SingleLinkList<int> singleLink = new SingleLinkList<int>();singleLink.Append(100);singleLink.Append(200);singleLink.Append(300);singleLink.Append(400);singleLink.Append(500);singleLink.Append(600);Console.WriteLine(singleLink.ToString());singleLink.Insert(900, 3);Console.WriteLine("插入:900 index:3");Console.WriteLine(singleLink.ToString());Console.WriteLine("删除index:4,删除的数据为:" + singleLink.Delete(4));Console.WriteLine(singleLink.ToString());Console.WriteLine("现在长度:" + singleLink.GetLength());Console.WriteLine("索引5的数据:" + singleLink[5]);}}

2.2 双向链表

前面介绍的单链表允许从一个结点直接访问它的后继结点,所以, 找直接后继结点的时间复杂度是 O(1)。但是,要找某个结点的直接前驱结点,只能从表的头引用开始遍历各结点。如果某个结点的 Next 等于该结点,那么,这个结点就是该结点的直接前驱结点。也就是说,找直接前驱结点的时间复杂度是 O(n), n是单链表的长度。当然,我们也可以在结点的引用域中保存直接前驱结点的地址而不是直接后继结点的地址。这样,找直接前驱结点的时间复杂度只有 O(1),但找直接后继结点的时间复杂度是 O(n)。如果希望找直接前驱结点和直接后继结点的时间复杂度都是 O(1),那么,需要在结点中设两个引用域,一个保存直接前驱结点的地址,叫 prev,一个直接后继结点的地址,叫 next,这样的链表就是双向链表(Doubly Linked List)。双向链表的结点结构示意图如图所示。

2.2.1 双向链表节点实现

public class DbNode<T>
{private T data; //数据域private DbNode<T> prev; //前驱引用域private DbNode<T> next; //后继引用域
//构造器public DbNode(T val, DbNode<T> p){data = val;next = p;}//构造器public DbNode(DbNode<T> p){next = p;}//构造器public DbNode(T val){data = val;next = null;}
![

2.3 循环链表

有些应用不需要链表中有明显的头尾结点。在这种情况下,可能需要方便地从最后一个结点访问到第一个结点。此时,最后一个结点的引用域不是空引用,而是保存的第一个结点的地址(如果该链表带结点,则保存的是头结点的地址),也就是头引用的值。带头结点的循环链表(Circular Linked List)如图所示。

数据结构2 - 线性表相关推荐

  1. python线性表和队列_[笔记]python数据结构之线性表:linkedlist链表,stack栈,queue队列...

    python数据结构之线性表 python内置了很多高级数据结构,list,dict,tuple,string,set等,在使用的时候十分舒心.但是,如果从一个初学者的角度利用python学习数据结构 ...

  2. c语言用两个栈构造队列伪码,数据结构习题线性表栈队列.doc

    数据结构习题线性表栈队列 线性表(58) 1. 在单链表.双链表和单循环链表中,若仅知道指针p指向某结点,不知道头指针,能否将结点*p从相应的链表中删去?若可以,其时间复杂度各为多少? 2.设线性表的 ...

  3. 【Java数据结构】线性表

    线性表 线性表是最基本.最简单.也是最常用的一种数据结构. 线性表中数据元素之间的关系是一对一的关系,即除了第一个和最后一个数据元素之外,其它数据元素都是首尾相接的(注意,这句话只适用大部分线性表,而 ...

  4. step3 . day2 数据结构之线性表链表

    今天继续学习数据结构的线性表部分,从基础的顺序表到链表,类比写了一些调用函数,完成了表的增删改查排序等问题. 尤其是链表的排序,费了很大的心思终于捋顺写出来了,小有成就感,而且代码一次通过率越来越高, ...

  5. 数据结构之线性表(附代码)

    数据结构 之 线性表(附代码) 线性表思维导图: 线性表定义(逻辑结构): 一.顺序表 1.顺序表思维导图: 2.顺序表的逻辑结构: 3.顺序表基本操作的功能实现: 1.线性表的静态定义: 2.线性表 ...

  6. 数据结构之线性表的基本C语言语法

    一开始没做笔记,大家想看的话可以参考这里 [数据结构绪论] [数据结构(二)] [数据结构--算法和算法分析] [数据结构--渐进时间复杂度] [数据结构--初识线性表] [数据结构--线性表的顺序实 ...

  7. 用Java描述数据结构之线性表的链式存储(链表),模拟LinkedList实现

    上一篇介绍了顺序表:用Java描述数据结构之线性表的顺序存储(顺序表),ArrayList及其方法的介绍 上一篇博客中说明了什么是线性表--线性表就是一个个数据元素逻辑上以一对一的相邻关系(但是在物理 ...

  8. 用Java描述数据结构之线性表的顺序存储(顺序表),ArrayList及其方法的介绍

    我们先来想一想什么是线性表? 线性表是最基本.最简单.也是最常用的一种数据结构.线性表(linear list)是数据结构的一种,一个线性表是n个具有相同特性的数据元素的有限序列. 线性表中数据元素之 ...

  9. c语言如何删除数组中的某一个元素_数据结构之线性表高效删除重复元素

    刚刚学完数据结构之线性表中关于顺序表和单链表的知识,我们知道顺序表中存储数据的结构是一个数组,对于数组来说,在尾部插入.删除元素是比较高效的,但是如果在中间或者开头插入.删除元素,就会涉及数据的搬移, ...

  10. 用标准C语言初始化线性表,C语言数据结构-顺序线性表的实现-初始化、销毁、长度、查找、前驱、后继、插入、删除、显示操作...

    1.数据结构-顺序线性表的实现-C语言 #define MAXSIZE 100 //结构体定义 typedef struct { int *elem; //基地址 int length; //结构体当 ...

最新文章

  1. 【LeetCode】230#二叉搜索树中第K小的元素
  2. java中,字符串和集合判断是否为空
  3. [caffe]深度学习之图像分类模型AlexNet解读
  4. 数据库索引的实现原理及查询优化
  5. 通过一个简单的例子,了解 Cypress 的运行原理
  6. 淘宝客静态单页_单页应用程序的Spring Boot静态Web资源处理
  7. 怎么实现注解_通透!一口气搞懂注解到底怎么用
  8. 问题 A: 阿正的忐忑不安(C语言)
  9. 数字图像处理基本原理和常用方法
  10. c语言文件归并问题_通知:土地有变!土地归并:每亩补9万?明年起:合村并镇!能否启动?1个好消息!...
  11. sklearn相关积累
  12. WPF 弹框 并自动关闭
  13. van-cell 取消点击_支付宝平安好医保怎么样?怎么报销?靠谱吗?怎么取消?_保险测评...
  14. python setuptools 打包 发布
  15. 由中缀表达式计算前缀表达式
  16. 四十八种微信公众号加人方法
  17. 2、硬件工程师之元器件学习—电阻(二)
  18. 基于MATLAB的极限与求导(附完整代码)
  19. 骨架法matlab,matlab中轴线算法骨架
  20. 阿里云服务器如何更换公网ip地址?

热门文章

  1. Linux中ls -l(ll)返回结果中的文件访问权限-rw-r--rw-
  2. Ubuntu 安装 chrome
  3. \pset 、\x命令
  4. C++中若类中没有默认构造函数,如何使用对象数组
  5. 德佑地产房产经纪人区域总监访谈:掌门的态度
  6. 【网络流】 HDU 4309 Seikimatsu Occult Tonneru 状压枚举边
  7. Java开发十大常用网站
  8. python利用myqr库生成二维码
  9. PowerDesigner运行自定义VBS脚本,复制Name到Comment
  10. unicode html转义字符,HTML转义字符 Unicode和CSS伪类介绍(示例代码)