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

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

1.1.线性表

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

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

线性表的实现有两种:

  • 数组
  • 队列

1.1.1.数组

1.逻辑简介

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

在数组中间删除:

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

dd9156e36b7348438c2bfda3179da316.png

在数组中间插入:

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

c9a50f12f0674a50b64473f76c6c07be.png

2.代码实现

使用代码实现顺序表:

public class Array{
  //数组
    private Object[] array;
    private int maxSize;
    //初始化一个空数组
    public void initArray(int maxSize){
        this.maxSize=maxSize;
        array=new Object[maxSize];
    }
    //查找位序为K的元素
    public  Object findKth(int K){
        return array[K];
    }
    //查找元素X第一次出现的位置
    public  int find(Object X){
        int i=0;
        while(!X.equals(array[i])){
            i++;
        }
        return i;
    }
    //查找最后一个非空元素位置的位序
    public int findLastTh(Object[] targetArray){
        int i=0;
        for (int j=0;j<targetArray.length;j++){
            if(array[j]!=null){
                i=j;
            }
        }
        return i;
    }
    //在i位序插入一个元素
    public void insert(Object X,int i){
        System.out.println("当前数组的容量:"+array.length);
        //判断是否存满,是否需要追加空间。
        if(isFull()){
            newSpace();
        }
        //若插入位置上没有元素则直接插入
        if(array[i]==null){
            array[i]=X;
        }
        else
        //若插入位置上有元素则当前位置开始顺序后移一位
        {
            for (int j = findLastTh(array); j >= i; j--) {
                array[j + 1] = array[j];
            }
            array[i] = X;
        }
    }
    //判断数组是否已经存满
    public boolean isFull(){
        return array[array.length-1]!=null ? true:false;
    }
    //为数组开辟新空间
    public void newSpace(){
        //copy原数组
        Object[] tempArry=this.array;
            //记录原数组
        //追加新空间,追加容量为初始化容量的一倍
        array=new Object[maxSize+maxSize];
        //将原数组元素,copy到新数组
        for (int i=0;i<=findLastTh(tempArry);i++){
              array[i]=tempArry[i];
            }
        System.out.println("扩容后数组容量:"+array.length);
    }
    //打印表中所有元素
    public void print() {
        int i=0;
        String s="";
        while (i<=findLastTh(array)) {
            s=s+i+":"+array[i]+"\t";
            i++;
        }
        System.out.println(s);
    }
}


1.1.2.链表

1.逻辑简介

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

在链表中间删除:

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

f59581ab720347cb8cd65aae0b41a296.png

2.代码实现

链表中的每个节点:

public class Node{
        //数据域
        Object data;
        //指针域
        Node next;
        public Object getData() {
            return data;
        }
        public void setData(Object data) {
            this.data = data;
        }
        public Node getNext() {
            return next;
        }
        public void setNext(Node next) {
            this.next = next;
        }
}

使用链表实现顺序表:

public class List {
    //节点
    public class Node{
        //数据域
        Object data;
        //指针域
        Node next;
        public Object getData() {
            return data;
        }
        public void setData(Object data) {
            this.data = data;
        }
        public Node getNext() {
            return next;
        }
        public void setNext(Node next) {
            this.next = next;
        }
    }
    //尾指针
    Node last;
    //遍历指针
    Node flag;
    //头节点
    Node header;
    //初始化头节点
    //初始化末尾指针
    public List(){
        this.header=new Node();
        this.header.setData("header");
        this.last=header;
    }
    //插入
    public void insert(Object data){
        Node newNode=new Node();
        newNode.setData(data);
        last.setNext(newNode);
        //指针后移
        last=newNode;
    }
    //指定位置插入
    //插入在指定节点的后面
    //header位序为0,依次类推
    //此方法无法实现直接挂在末尾,挂在末尾请用上面的无参insert()
    public void insert(int X,Object data){
        //遍历指针指向头节点
        this.flag=header;
        //计数器
        int i=0;
        Node newNode=new Node();
        newNode.setData(data);
        //查找动作
        while(i<X){
            flag=flag.getNext();
            i++;
        }
        //删除动作
        //后面节点挂在当前节点后
        newNode.setNext(flag.getNext());
        //当前节点挂在目标节点后
        flag.setNext(newNode);
    }
    //遍历打印链表
    public void printf(){
        //遍历指针指向头节点
        this.flag=header;
        //消息
        String message="";
        while (flag.getNext()!=null){
            message=message+flag.getData()+"—>";
            flag=flag.getNext();
        }
        //拼接最后一个节点
        message=message+flag.getData()+"—>";
        System.out.println(message);
    }
    //删除指定位序节点
    public void delete(int X){
        //遍历指针指向头节点
        this.flag=header;
        //计数器
        int i=0;
        //查找动作
        while(i<X-1){
            flag=flag.getNext();
            i++;
        }
        //删除动作
        flag.setNext(flag.getNext().getNext());
    }
}

1.2.堆栈

1.2.1.逻辑简介

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

3a26f7042a154f4a8d5ec0d8e262fe2a.png

堆栈的操作集可抽象为:

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

1.2.2.代码实现

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

public class Stack {
    //数据域
    Object[] stack;
    //头指针
    int first=0;
    //尾指针
    int last=-1;
    public Stack(int size){
        stack=new Object[size];
    }
    //判断堆栈是否已满
    public Boolean isFull(){
        return (stack.length-1)==last;
    }
    //判断堆栈是否为空
    public Boolean isEmpty(){
        return last==-1;
    }
    //入栈
    public void push(Object o){
        if(!isFull()) {
            stack[++last] = o;
        }
    }
    //出栈
    public Object pop(){
        Object data=null;
        if(!isEmpty()) {
            data=stack[last];
            stack[last] = null;
            last--;
        }
        return data;
    }

1.3.队列

1.3.1.逻辑简介

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

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


48c2caf152ed4afc8b358ee57190d867.png

队列的操作集可抽象为:

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

1.3.2.代码实现

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

public class Queue {
    //数据域
    Object[] stack;
    //头指针
    int first=0;
    //尾指针
    int last=-1;
    public Queue(int size){
        stack=new Object[size];
    }
    public Boolean isFull(){
        return (stack.length-1)==last;
    }
    public Boolean isEmpty(){
        return last==-1;
    }
    public void push(Object o){
        if(!isFull()) {
            stack[++last] = o;
        }
    }
    public Object pop(){
        Object o=stack[first];
        //删除头元素,后续元素顺序前移
        stack[first]=null;
        if(!isEmpty()) {
            for (int i = 1; i <=last; i++) {
                Object temp=stack[i];
                stack[i-1]=temp;
            }
            stack[last--]=null;
        }
        return o;
    }
}

1.4.性能对比

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

  • 查找和遍历时是数组性能更好,因为存储是挨在一起的。链表的话则需要通过指针来寻址。
  • 增加和删除时链表性能更好,因为数组中间元素的增加删除涉及后面元素的位移,明显不如链表只动一个元素的性能。


目录
相关文章
|
27天前
|
存储 Java
Java中的HashMap和TreeMap,通过具体示例展示了它们在处理复杂数据结构问题时的应用。
【10月更文挑战第19天】本文详细介绍了Java中的HashMap和TreeMap,通过具体示例展示了它们在处理复杂数据结构问题时的应用。HashMap以其高效的插入、查找和删除操作著称,而TreeMap则擅长于保持元素的自然排序或自定义排序,两者各具优势,适用于不同的开发场景。
42 1
|
29天前
|
存储 Java
告别混乱!用Java Map优雅管理你的数据结构
【10月更文挑战第17天】在软件开发中,随着项目复杂度增加,数据结构的组织和管理至关重要。Java中的Map接口提供了一种优雅的解决方案,帮助我们高效、清晰地管理数据。本文通过在线购物平台的案例,展示了Map在商品管理、用户管理和订单管理中的具体应用,有效提升了代码质量和维护性。
81 2
|
29天前
|
存储 Java 开发者
Java Map实战:用HashMap和TreeMap轻松解决复杂数据结构问题!
【10月更文挑战第17天】本文深入探讨了Java中HashMap和TreeMap两种Map类型的特性和应用场景。HashMap基于哈希表实现,支持高效的数据操作且允许键值为null;TreeMap基于红黑树实现,支持自然排序或自定义排序,确保元素有序。文章通过具体示例展示了两者的实战应用,帮助开发者根据实际需求选择合适的数据结构,提高开发效率。
60 2
|
12天前
|
缓存 算法 Java
本文聚焦于Java内存管理与调优,介绍Java内存模型、内存泄漏检测与预防、高效字符串拼接、数据结构优化及垃圾回收机制
在现代软件开发中,性能优化至关重要。本文聚焦于Java内存管理与调优,介绍Java内存模型、内存泄漏检测与预防、高效字符串拼接、数据结构优化及垃圾回收机制。通过调整垃圾回收器参数、优化堆大小与布局、使用对象池和缓存技术,开发者可显著提升应用性能和稳定性。
34 6
|
18天前
|
存储 Java 索引
Java中的数据结构:ArrayList和LinkedList的比较
【10月更文挑战第28天】在Java编程世界中,数据结构是构建复杂程序的基石。本文将深入探讨两种常用的数据结构:ArrayList和LinkedList,通过直观的比喻和实例分析,揭示它们各自的优势与局限,帮助你在面对不同的编程挑战时做出明智的选择。
|
26天前
|
存储 算法 Java
Java 中常用的数据结构
【10月更文挑战第20天】这些数据结构在 Java 编程中都有着广泛的应用,掌握它们的特点和用法对于提高编程能力和解决实际问题非常重要。
25 6
|
27天前
|
存储 Java 开发者
Java中的Map接口提供了一种优雅的方式来管理数据结构,使代码更加清晰、高效
【10月更文挑战第19天】在软件开发中,随着项目复杂度的增加,数据结构的组织和管理变得至关重要。Java中的Map接口提供了一种优雅的方式来管理数据结构,使代码更加清晰、高效。本文通过在线购物平台的案例,展示了Map在商品管理、用户管理和订单管理中的具体应用,帮助开发者告别混乱,提升代码质量。
27 1
|
1月前
|
存储 算法 Java
Java常用的数据结构
【10月更文挑战第3天】 在 Java 中,常用的数据结构包括数组、链表、栈、队列、树、图、哈希表和集合。每种数据结构都有其特点和适用场景,如数组适用于快速访问,链表适合频繁插入和删除,栈用于实现后进先出,队列用于先进先出,树和图用于复杂关系的表示和查找,哈希表提供高效的查找性能,集合用于存储不重复的元素。合理选择和组合使用这些数据结构,可以显著提升程序的性能和效率。
|
1月前
|
存储 Java
数据结构第二篇【关于java线性表(顺序表)的基本操作】
数据结构第二篇【关于java线性表(顺序表)的基本操作】
30 6
|
1月前
|
Java 语音技术 容器
java数据结构泛型
java数据结构泛型
27 5