线性表是一种十分基础且重要的数据结构,它主要包括以下内容:

  • 数组
  • 链表
  • 队列

接下来,我将对这四种数据结构做一个详细的总结,其中对链表实现了十几种常见的操作。希望对你有所帮助。

1.数组

数组(Array)是一种线性表数据结构。它用一组连续的内存空间,来存储一组具有相同类型的数据。 注意点:①.数组是一种线性表;②.连续的内存空间和相同类型的数据 由于第二个性质,数组支持 “随机访问”,根据下表随机访问的时间复杂度为O(1);但与此同时却使得在数组中删除,插入数据需要大量的数据搬移工作。

低效的“插入”和“删除”

插入操作

假如数组的长度为n,我们需要将一个数据插入到数组的第k个位置,我们需要将第k~n位元素都顺序地往后挪动一位。 最好情况时间复杂度为O(1),此时对应着在数组末尾插入元素; 最坏情况时间复杂度为O(n),此时对应着在数组开头插入元素; 平均情况时间复杂度为O(n),因为我们在每个位置插入元素的概率相同,故(1+2+3+……+n)/n=O(n); 但是根据我们的需求,有一个特定的场景。如果数组的数据是有序的,那么我们在插入时就一定要那么做;但是如果数组中存储的数据并没有任何规律,数组只是被当成一个存储数据的集合,我们可以有一个取巧的方法: 直接将第k个元素搬移到数组元素的最后,把新的数据直接放入第k个位置即可(是不是很简单啊),这时插入元素的复杂度为O(1)。

删除操作

和插入操作一样,为了保证内存的连续性,删除操作也需要搬移数据。 最好情况时间复杂度为O(1),此时对应着删除数组末尾的元素; 最坏情况时间复杂度为O(n),此时对应着删除数组开头的元素; 平均情况时间复杂度为O(n),因为我们删除每个位置的元素的概率相同,故(1+2+3+……+n)/n=O(n); 当然,在某些特殊情况下,我们并不一定非要进行复杂的删除操作。我们只是将需要删除的数据记录,并且假装它以经被删除了。直到数组没有更多空间存储数据时,我们再触发一次真正的删除操作即可。

这其实就和生活中的垃圾桶类似,垃圾并没有消失,只是被“标记”成了垃圾,而直到垃圾桶塞满时,才会清理垃圾桶。

警惕数组访问越界

在 C 语言中,只要不是访问受限的内存,所有的内存空间都是可以自由访问的。如果疏忽会造成严重的后果。当然,Java会自动检测。

2.链表

  • 链表结点表示
  • 打印单链表
  • 单链表根据索引插入结点
  • 获取单链表的长度
  • 打印单链表的长度
  • 单链表删除指定索引的结点
  • 单链表实现元素查找,返回是否存在布尔值
  • 单链表删除指定索引的后续节点
  • 单链表反转
  • 递归地进行单链表反转
  • 检测链表中是否含有环
  • 删除倒数第k个结点
  • 求中间节点
  • 有序链表合并

链表结点表示

 public class Node{int data;Node Next;}

打印单链表

 public class Method {//打印单链表public static void PrintNode (Node list){for(Node x=list;x!=null;x=x.Next)System.out.print(x.data+" ");System.out.println();}

单链表根据索引插入结点

     public static Node insert(Node first,int index,Node a){Node ret = new Node();ret.Next=first;//创建一个虚拟头节点Node p=ret;while((index--)!=0) p=p.Next;//完成节点的插入操作a.Next=p.Next;p.Next=a;//返回真正的链表头节点地址return ret.Next;//函数返回链表的头节点}

获取单链表的长度

     public static int GetLength(Node first){int n=0;for(Node x=first;x!=null;x=x.Next){++n;}return n;}

打印单链表的长度

     public static void PrintLength(Node first){System.out.println("Length : "+GetLength(first));}

单链表删除指定索引的结点

     public static Node Delete(Node first,int index){if(index<0||index>=GetLength(first)) return first;else{Node ret=new Node();ret.Next=first;Node p=ret;while((index--)!=0) p=p.Next;//完成节点的删除操作p.Next=p.Next.Next;return ret.Next;}}

单链表实现元素查找,返回是否存在布尔值

     public static boolean Find(Node first,int key){for(Node x=first;x!=null;x=x.Next){if(x.data==key) return true;}return false;}

单链表删除指定索引的后续节点

     public static void RemoveAfter(Node first,int index){Node ret=new Node();ret.Next=first;Node p=ret;while((index--)!=0) p=p.Next;p.Next.Next=null;​}

单链表反转

    public static Node  reverse(Node list){Node curr=list,pre=null;while(curr!=null){Node next=curr.Next;curr.Next=pre;pre=curr;curr=next;}return pre;}

递归地进行单链表反转

    public static Node reverseRecursively(Node head){if(head==null||head.Next==null) return head;//递归的终止条件,返回反转后链表的头节点Node reversedListHead=reverseRecursively(head.Next);head.Next.Next=head;//改变这两个结点之间的指向顺序head.Next=null;return  reversedListHead;//返回反转后的链表头节点}

检测链表中是否含有环

    public static boolean checkCircle(Node list){if(list==null) return false;Node fast=list.Next;Node slow=list;while(fast!=null&&fast.Next!=null){fast=fast.Next.Next;slow=slow.Next;if(slow==fast) return true;}return false;}

删除倒数第k个结点

    public static Node deleteLastKth(Node list,int k){//利用两个指针,fast和slow,它们之间差k个位置,判断如果fast.Nest=null,也就代表着slow这个位置就是倒数第k个结点Node fast=list;int i=1;while(fast!=null&&i<k){fast=fast.Next;++i;}if(fast==null) return list;Node slow=list;Node prev=null;while(fast.Next!=null){fast=fast.Next;prev=slow;slow=slow.Next;}if(prev==null){list=list.Next;}else{prev.Next=prev.Next.Next;}return list;}

求中间节点

    public static Node findMiddleNode(Node list){if(list==null) return null;Node fast=list;Node slow=list;while(fast!=null&&fast.Next!=null){fast=fast.Next.Next;slow=slow.Next;}return slow;}

有序链表合并

    public static Node mergeTwoLists(Node l1,Node l2){Node soldier=new Node();Node p=soldier;while(l1!=null&&l2!=null){if(l1.data<l2.data){p.Next=l1;l1=l2.Next;}else{p.Next=l2;l2=l2.Next;}p=p.Next;}if(l1!=null){ p.Next=l1;}if(l2!=null){ p.Next=l2;}return soldier.Next;}

3.栈

  • 顺序栈
  • 链式栈

1.基于数组实现的顺序栈

  • 构造函数
  • 入栈操作
  • 出栈操作
  • 打印操作
package Stack;//基于数组实现的顺序栈
public class ArrayStack {private int[] items;private int count;//栈中的元素个数private int n;//栈的大小//初始化数组,申请一个大小为n的数组空间
public ArrayStack(int n){this.items=new int[n];this.n=n;this.count=0;
}//入栈操作
public boolean push(int item){//数组空间不足,直接返回false,入栈失败if(count==n) return false;//将data放在下标为count的位置,并且count加一items[count]=item;++count;return true;
}//出栈操作
public int pop(){//栈为空,直接返回-1;if(count==0) return -1;//返回下标为count-1的数组元素,并且栈中元素个数count减一int tmp=items[count-1];--count;return tmp;
}
public void PrintStack(){for(int i=count-1;i>=0;--i){System.out.print(items[i]+" ");}System.out.println();}
}

2.基于链表的链式栈

  • 入栈操作
  • 出栈操作
  • 打印操作
package Stack;public class LinkedListStack {private Node top;//栈顶(最近添加的元素)private int N;//元素数量private class Node{//定义了结点的嵌套类int data;Node Next;}public boolean isEmpty(){return top==null;}public int size(){return N;}public void push(int data){/*Node newNode=new Node();//判断是否为空栈//if(top==null) newNode=top;top.data=data;top.Next=newNode;N++;*/Node newNode=top;top=new Node();top.data=data;top.Next=newNode;++N;}public int pop(){//从栈顶删除元素if(top==null) return -1;//这里用-1表示栈中没有数据int data=top.data;top=top.Next;N--;return data;}public void PrintStack(){for(Node x=top;x!=null;x=x.Next){System.out.print(x.data+" ");}System.out.println();}}

4.普通队列

  • 基于数组实现的普通队列
  • 基于链表实现的队列
  • 基于数组实现的循环队列

1.基于数组实现的普通队列

  • 构造函数
  • 入队操作
  • 出队操作
  • 打印队列中的元素
package Queue;//用数组实现队列
public class ArrayQueue {//数组:items,数组大小:nprivate int[] items;private int n=0;//head表示队头下标,tail表示队尾下标private int head=0;private int tail=0;//申请一个大小为capacity的数组public ArrayQueue(int capacity){items=new int[capacity];n=capacity;}//入队(一),基础版public boolean enqueue(int item){//如果tail==n,表示队列末尾已经没有空间了if(tail==n) return false;items[tail]=item;++tail;return true;}//入队(二),改进版public boolean enqueue1(int item){//如果tail==n,表示队列末尾已经没有空间了if(tail==n){//tail==n&&head==0,表示整个队列都占满了if(head==0) return false;//数据搬移for(int i=head;i<tail;++i){items[i-head]=items[i];}//搬移完成后重新更新head和tailtail=tail-head;head=0;}items[tail]=item;++tail;return true;}//出队public int dequeue(){//如果head==tail,表示队列为空if(head==tail) return -1;//这里用-1表示队列为空int ret=items[head];++head;return ret;}//打印队列public void PrintQueue(){for(int i=head;i<tail;++i){System.out.print(items[i]+" ");}System.out.println();}}

2.基于链表实现的队列

  • 构造函数
  • 入队操作
  • 出队操作
  • 打印队列中的元素
package Queue;//基于链表实现的队列
public class LinkedListQueue {private Node head;//指向最早添加的结点的链接private Node tail;//指向最近添加的结点的链接private int N;//队列中的元素数量private class Node{//定义了结点的嵌套类int data;Node Next;}public boolean isEmpty(){return head==null;}public int size(){ return N;}//向表尾添加元素,即入队public void enqueue(int data){Node newNode=tail;tail=new Node();tail.data=data;tail.Next=null;if(isEmpty()) head=tail;else newNode.Next=tail;++N;}public int dequeue(){//从表头删除元素int data=head.data;head=head.Next;if(isEmpty()) tail=null;N--;return data;}//打印输出队列元素public void PrintQueue(){for(Node x=head;x!=null;x=x.Next){System.out.print(x.data+" ");}System.out.println();}
}

3.基于数组实现的循环队列

  • 构造函数
  • 入队操作
  • 出队操作
  • 打印队列中的元素
 package Queue;​public class CircularQueue {//数组items,数组大小nprivate int[] items;private int n=0;//head表示队头下标,tail表示队尾下标private int head=0;private int tail=0;​//申请一个大小为capacity的数组public CircularQueue(int capacity){items = new int[capacity];n=capacity;}​//入队public boolean enqueue(int item){//队列满了if((tail+1)%n==head) return false;items[tail]=item;tail=(tail+1)%n;//实现计数的循环return true;}​//出队public int dequeue(){//如果head==tail,表示队列为空if(head==tail) return -1;//以-1表示队列为空int ret=items[head];head=(head+1)%n;return ret;}​//打印队列public void PrintQueue(){if(n==0) return;for(int i=head;i%n!=tail;i=(i+1)%n){System.out.print(items[i]+" ");}System.out.println();}}

说明

文章代码太多,我本来是希望分成几篇文章写的,但是由于一些原因,最终放在了一起,略显臃肿。代码都是经过测试用例测试过的,应该不会有错误。

如果体验不太好,可以移步我的Github,里面观感较好。

题外话:对于算法初学者,推荐一本十分 nice 的书籍 《算法第四版》,里面各种配图十分详细。如果你需要电子版文件,公众号后台回复算法4即可获得下载链接。回复 算法01 送你一份 算法与数据结构思维导图。最后,希望我们一起进步,一起成长! @孙志超 ,码字不易,点个赞再走~

echart data放入数组_线性表(数组、链表、队列、栈)详细总结相关推荐

  1. Algorithms_基础数据结构(04)_线性表之链表_单向循环链表约瑟夫环问题

    文章目录 大纲图 链表的经典面试题目 如何设计一个LRU缓存淘汰算法 约瑟夫问题 结构 分析 大纲图 链表的经典面试题目 如何设计一个LRU缓存淘汰算法 tip:单向链表 约瑟夫问题 N个人围成一圈, ...

  2. Algorithms_基础数据结构(02)_线性表之链表_单向链表

    文章目录 大纲图 链表的经典面试题目 如何设计一个LRU缓存淘汰算法 约瑟夫问题 顺序表VS 链表 链表的定义 链表的特点 常见的链表结 单向链表 单向链表的查找 单向链表的插入 头插 尾部插入 中间 ...

  3. c++如何输入数组_工作表数组计算之一:行列数相同的数组间运算

    大家好,今天我们继续讲解VBA数组与字典解决方案的第12讲,从这讲开始我们开始讲数组的运算了.通过之前的讲解,我了解了数组的定义,数组的性质,一些重要的知识点我们再回顾一下: a) 在数组的录入时需要 ...

  4. Algorithms_基础数据结构(03)_线性表之链表_双向链表

    文章目录 大纲图 双向链表 双向链表的基本结构 双向链表的基本操作 头插 尾插 中间部位插入 删除头部 删除尾部 删除中间位置的数据 查找 更新 Code 总结 大纲图 双向链表 Algorithms ...

  5. 算法实例_线性表 By:比方

    算法实例_线性表 By:比方 什么是线性表? 从线性表的功能逻辑上来看,线性表就是由n(n>=0)个数据元素的排序组合,数据由x1,x2,x3,...,xn结构有序的顺序排列. 线性表的结构和特 ...

  6. C语言试题二十三之编写一个函数void function(int tt[m][n],int pp[n]),tt指向一个m行n列的二维函数组,求出二维函数组每列中最小元素,并依次放入pp所指定一维数组中

    1. 题目 请编写一个函数void function(int tt[m][n],int pp[n]),tt指向一个m行n列的二维函数组,求出二维函数组每列中最小元素,并依次放入pp所指定一维数组中.二 ...

  7. 数据结构 (一) ----- 数据结构基本概念基于数组实现线性表

    相关文章: <数据结构 (一) ----- 数据结构基本概念&基于数组实现线性表> 文章目录 数据结构基本概念 一.逻辑结构 二.存储结构 三.数据结构定义 四.数据结构的通用的几 ...

  8. java中线性表删除元素和删除指定元素_线性表的插入和删除(Java版)

    1.线性表的定义: (1).线性表是一种可以在任意位置插入和删除数据元素操作.由n(n≥0)个相同类型数据元素a0, a1,-, an-1组成的线性结构.除了第一个元素没有前驱元素和最后一个元素没有后 ...

  9. 数据结构_Java_基于 线性表-单链表的初始化、逆序、去重、非递减序列的合并(开辟新链表先整体插入一个链表全部元素,再遍历另外一个链表寻找合适位置插入 、开辟新链表实现舍弃原链表)等操作实现

    写在前面 不久前学习了数据结构线性表-数组-链表的相关知识,用C/C++语言实现了 单链表的系列相关操作 .见往期博客: 数据结构实验2_C语言_基于顺序表的非递减有序表的合并.线性表元素的增.删.改 ...

最新文章

  1. 2016 实习招聘面试经历 - 3
  2. shell公共函数:/etc/init.d/functions
  3. java inputstream 回退_系统学习 Java IO (十)----回退流 PushbackInputStream
  4. python参数化_Python 中如何实现参数化测试的方法示例
  5. 第3阶段——内核启动分析之prepare_namespace()如何挂载根文件系统和mtd分区介绍(6)...
  6. 服务器宕机可能的原因以及服务器宕机解决办法
  7. 学习PHP的必备开发工具
  8. 微信小程序开发【前端+后端(java)】
  9. Nginx主配置文件的优化-nginx主配置文件的优化
  10. 软件项目组织架构安排
  11. 阿里云的yum源配置
  12. Docker运维笔记-Docker端口映射
  13. SFTP上传本地文件报错找不到文件或路径
  14. 深入理解地址翻译 CSAPP
  15. PacketTrace基本使用
  16. hdu 4210 Su-domino-ku
  17. vue2.0支持compiler
  18. 树的重心——DFS求解
  19. 乔布斯初心与终点:疯子一样的不知妥协
  20. MySQL同步机制、主从复制半同步和双主配置

热门文章

  1. Spark的RDD检查点实现分析
  2. 洛谷P1328生活大爆炸版石头剪刀布
  3. 【Android】Error:Execution failed for task ':app:lint'
  4. [基础]sizeof和strlen
  5. android获取手机的IMSI码
  6. 中文数字转换为阿拉伯数字
  7. 关于使用类成员函数作为回调的方法
  8. 软件测试--selenium安装使用
  9. php获取元素位置,jquery如何获取当前元素的位置
  10. 软件测试—软件测试基础知识—测试用例设计的方法之场景法、正交试验法和错误推断法