• 数据结构(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
    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
    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(i1){
    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.性能对比

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

    • 查找和遍历时是数组性能更好,因为存储是挨在一起的。链表的话则需要通过指针来寻址。
    • 增加和删除时链表性能更好,因为数组中间元素的增加删除涉及后面元素的位移,明显不如链表只动一个元素的性能。
  • 相关阅读:
    计算机组成原理平时作业四
    Linux 中如何使用 id 命令
    C#&Winform&ListView实现缺陷图片浏览器
    apply()拦截proxy
    服务器环境搭建
    自动化测试类型有哪些?是怎么分类的
    javaEE -8(9000字详解网络编程)
    JDK多版本切换
    笔试强训第16天
    使用QT制作QQ登录界面
  • 原文地址:https://blog.csdn.net/Joker_ZJN/article/details/127797131