当前位置:   article > 正文

数据结构(1)线性结构——数组、链表、堆栈、队列(介绍和JAVA代码实现)_队列链表堆栈和数都是线性数据结构

队列链表堆栈和数都是线性数据结构

目录

1.1.线性表

1.1.1.数组

1.逻辑简介

 2.代码实现

 1.1.2.链表

1.逻辑简介

 2.代码实现

1.2.堆栈

1.2.1.逻辑简介

1.2.2.代码实现

1.3.队列

1.3.1.逻辑简介

1.3.2.代码实现

1.4.性能对比


1.1.线性表

线性表是指由同种元素构成的有序且线性的一种数据结构,由于其有序且线性的特点,可以抽象出对其的一个操作集:

  1. ElementType findKth(int k)//查找位序为K的元素
  2. int find(ElementType e)//查找元素e出现的第一次位置
  3. void insert(ElementType e,int i)//在位序i前面插入一个元素
  4. void delete(int i)//删除位序i的元素
  5. int length()//返回线性表的长度

线性表的实现有两种:

  • 数组
  • 队列

1.1.1.数组

1.逻辑简介

数组操作中要注意的操作是在中间插入或者删除,要涉及元素的位移。

在数组中间删除:

删除数组中间某个位置的元素,为了保持连续,后面的元素要挨个前移。

在数组中间插入:

在数组中间某个位置插入元素,首先要腾出位置,也就是说,该位置后面的元素要挨个后移

 2.代码实现

使用代码实现顺序表

  1. public class Array{
  2. //数组
  3. private Object[] array;
  4. private int maxSize;
  5. //初始化一个空数组
  6. public void initArray(int maxSize){
  7. this.maxSize=maxSize;
  8. array=new Object[maxSize];
  9. }
  10. //查找位序为K的元素
  11. public Object findKth(int K){
  12. return array[K];
  13. }
  14. //查找元素X第一次出现的位置
  15. public int find(Object X){
  16. int i=0;
  17. while(!X.equals(array[i])){
  18. i++;
  19. }
  20. return i;
  21. }
  22. //查找最后一个非空元素位置的位序
  23. public int findLastTh(Object[] targetArray){
  24. int i=0;
  25. for (int j=0;j<targetArray.length;j++){
  26. if(array[j]!=null){
  27. i=j;
  28. }
  29. }
  30. return i;
  31. }
  32. //在i位序插入一个元素
  33. public void insert(Object X,int i){
  34. System.out.println("当前数组的容量:"+array.length);
  35. //判断是否存满,是否需要追加空间。
  36. if(isFull()){
  37. newSpace();
  38. }
  39. //若插入位置上没有元素则直接插入
  40. if(array[i]==null){
  41. array[i]=X;
  42. }
  43. else
  44. //若插入位置上有元素则当前位置开始顺序后移一位
  45. {
  46. for (int j = findLastTh(array); j >= i; j--) {
  47. array[j + 1] = array[j];
  48. }
  49. array[i] = X;
  50. }
  51. }
  52. //判断数组是否已经存满
  53. public boolean isFull(){
  54. return array[array.length-1]!=null ? true:false;
  55. }
  56. //为数组开辟新空间
  57. public void newSpace(){
  58. //copy原数组
  59. Object[] tempArry=this.array;
  60. //记录原数组
  61. //追加新空间,追加容量为初始化容量的一倍
  62. array=new Object[maxSize+maxSize];
  63. //将原数组元素,copy到新数组
  64. for (int i=0;i<=findLastTh(tempArry);i++){
  65. array[i]=tempArry[i];
  66. }
  67. System.out.println("扩容后数组容量:"+array.length);
  68. }
  69. //打印表中所有元素
  70. public void print() {
  71. int i=0;
  72. String s="";
  73. while (i<=findLastTh(array)) {
  74. s=s+i+":"+array[i]+"\t";
  75. i++;
  76. }
  77. System.out.println(s);
  78. }
  79. }

 1.1.2.链表

1.逻辑简介

链表操作中要注意的操作是在中间插入或者删除,要涉及指针的操作。

在链表中间删除:

在链表中间删除一个元素,即将该元素前一个节点的指针指向要删除节点的下一个节点,即要删除节点的指针所指向的位置,然后将要删除的节点的指针指向空。

 2.代码实现

链表中的每个节点:

  1. public class Node{
  2. //数据域
  3. Object data;
  4. //指针域
  5. Node next;
  6. public Object getData() {
  7. return data;
  8. }
  9. public void setData(Object data) {
  10. this.data = data;
  11. }
  12. public Node getNext() {
  13. return next;
  14. }
  15. public void setNext(Node next) {
  16. this.next = next;
  17. }
  18. }

使用链表实现顺序表:

  1. public class List {
  2. //节点
  3. public class Node{
  4. //数据域
  5. Object data;
  6. //指针域
  7. Node next;
  8. public Object getData() {
  9. return data;
  10. }
  11. public void setData(Object data) {
  12. this.data = data;
  13. }
  14. public Node getNext() {
  15. return next;
  16. }
  17. public void setNext(Node next) {
  18. this.next = next;
  19. }
  20. }
  21. //尾指针
  22. Node last;
  23. //遍历指针
  24. Node flag;
  25. //头节点
  26. Node header;
  27. //初始化头节点
  28. //初始化末尾指针
  29. public List(){
  30. this.header=new Node();
  31. this.header.setData("header");
  32. this.last=header;
  33. }
  34. //插入
  35. public void insert(Object data){
  36. Node newNode=new Node();
  37. newNode.setData(data);
  38. last.setNext(newNode);
  39. //指针后移
  40. last=newNode;
  41. }
  42. //指定位置插入
  43. //插入在指定节点的后面
  44. //header位序为0,依次类推
  45. //此方法无法实现直接挂在末尾,挂在末尾请用上面的无参insert()
  46. public void insert(int X,Object data){
  47. //遍历指针指向头节点
  48. this.flag=header;
  49. //计数器
  50. int i=0;
  51. Node newNode=new Node();
  52. newNode.setData(data);
  53. //查找动作
  54. while(i<X){
  55. flag=flag.getNext();
  56. i++;
  57. }
  58. //删除动作
  59. //后面节点挂在当前节点后
  60. newNode.setNext(flag.getNext());
  61. //当前节点挂在目标节点后
  62. flag.setNext(newNode);
  63. }
  64. //遍历打印链表
  65. public void printf(){
  66. //遍历指针指向头节点
  67. this.flag=header;
  68. //消息
  69. String message="";
  70. while (flag.getNext()!=null){
  71. message=message+flag.getData()+"—>";
  72. flag=flag.getNext();
  73. }
  74. //拼接最后一个节点
  75. message=message+flag.getData()+"—>";
  76. System.out.println(message);
  77. }
  78. //删除指定位序节点
  79. public void delete(int X){
  80. //遍历指针指向头节点
  81. this.flag=header;
  82. //计数器
  83. int i=0;
  84. //查找动作
  85. while(i<X-1){
  86. flag=flag.getNext();
  87. i++;
  88. }
  89. //删除动作
  90. flag.setNext(flag.getNext().getNext());
  91. }
  92. }

1.2.堆栈

1.2.1.逻辑简介

堆栈,一种后入先出(LIFO,last in frist out)或者叫先入后出(FILO,first in last out)的线性且有序的数据结构。

堆栈的操作集可抽象为:

  1. Boolean isFull();//判断堆栈是否已满
  2. Boolean isEmpty();//判断堆栈是否为空
  3. void push();//入栈
  4. void pop();//出栈

1.2.2.代码实现

此处的代码实现以数组来存储数据,数组进行出入堆栈的时候会涉及位移操作,比起链表来说还更复杂一点,链表的话直接操作指针的指向即可更加方便。

  1. public class Stack {
  2. //数据域
  3. Object[] stack;
  4. //头指针
  5. int first=0;
  6. //尾指针
  7. int last=-1;
  8. public Stack(int size){
  9. stack=new Object[size];
  10. }
  11. //判断堆栈是否已满
  12. public Boolean isFull(){
  13. return (stack.length-1)==last;
  14. }
  15. //判断堆栈是否为空
  16. public Boolean isEmpty(){
  17. return last==-1;
  18. }
  19. //入栈
  20. public void push(Object o){
  21. if(!isFull()) {
  22. stack[++last] = o;
  23. }
  24. }
  25. //出栈
  26. public Object pop(){
  27. Object data=null;
  28. if(!isEmpty()) {
  29. data=stack[last];
  30. stack[last] = null;
  31. last--;
  32. }
  33. return data;
  34. }

1.3.队列

1.3.1.逻辑简介

队列,一种先进先出(FIFO,first in first out)或者叫后进后出(LILO,last in last out)的线性且有序的数据结构。

队列的理解不难,就像我们生活中排队时的各种队列一样,就是先进先出,后进后出。

 队列的操作集可抽象为:

  1. Boolean isFull();//判断队列是否已满
  2. Boolean isEmpty();//判断队列是否为空
  3. void push();//入队
  4. void pop();//出队

1.3.2.代码实现

此处的代码实现以数组来存储数据,比起链表来说还更复杂一点,链表的话直接操作指针的指向即可更加方便。

  1. public class Queue {
  2. //数据域
  3. Object[] stack;
  4. //头指针
  5. int first=0;
  6. //尾指针
  7. int last=-1;
  8. public Queue(int size){
  9. stack=new Object[size];
  10. }
  11. public Boolean isFull(){
  12. return (stack.length-1)==last;
  13. }
  14. public Boolean isEmpty(){
  15. return last==-1;
  16. }
  17. public void push(Object o){
  18. if(!isFull()) {
  19. stack[++last] = o;
  20. }
  21. }
  22. public Object pop(){
  23. Object o=stack[first];
  24. //删除头元素,后续元素顺序前移
  25. stack[first]=null;
  26. if(!isEmpty()) {
  27. for (int i = 1; i <=last; i++) {
  28. Object temp=stack[i];
  29. stack[i-1]=temp;
  30. }
  31. stack[last--]=null;
  32. }
  33. return o;
  34. }
  35. }

1.4.性能对比

从链表和数组的结构特点和使用过程中可以看到,数组和链表在增删改查各个场景中性能各有优劣:

  • 查找和遍历时是数组性能更好,因为存储是挨在一起的。链表的话则需要通过指针来寻址。
  • 增加和删除时链表性能更好,因为数组中间元素的增加删除涉及后面元素的位移,明显不如链表只动一个元素的性能。
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/528238
推荐阅读
相关标签
  

闽ICP备14008679号