简单聊一下数组和链表

写在前面

数组和链表是数据结构中最基础的两种结构,其他的都是由这两者转化而来;
因此,掌握这两种结构至关重要!下面,时光就带大家来学习一下数组和链表;

思维导图:

在这里插入图片描述

1,什么是线性表?

线性表是具有相同类型的n(>=0)个数据元素的有限序列(a0,a1,a2,…,an),ai是表项,n是表长度;

那么为什么要提到线性表呢?
因为数组和链表都是线性表的结构,只不过它们的存储方式不一样;
根据存储方式不同,可将线性表分为顺序表链式表
线性表是数据结构中的逻辑结构。可以存储在数组上,也可以存储在链表上。
一句话,用数组来存储的线性表就是顺序表

2,数组和链表

数组:在内存中,是一块连续的内存区域;
链表:是由不连续的内存空间组成;
在这里插入图片描述

3,数组和链表的区别

数组优点: 随机访问性强,查找速度快(连续内存空间导致的);
数组缺点: 插入和删除效率低 可能浪费内存 内存空间要求高,必须有足够的连续内存空间。 数组大小固定,不能动态拓展

链表的优点: 插入删除速度快 内存利用率高,不会浪费内存 大小没有固定,拓展很灵活。 (每一个数据存储了下一个数据的地址,增删效率高)
**链表的缺点:**不能随机查找,必须从第一个开始遍历,查找效率低

4,数组和链表的代码实现

说了这么多,让我们用代码来写一个数组和链表。
数组:
1,先写一个实体类DynamicArray;

主要包括属性有数组容量,结点数据和数组长度;

package com.java.model;

public class DynamicArray {
    //动态数组最大容量
    public final static int capacity = 100;

    //顺序表的结点数据
    public int[] data;
    //顺序表的长度,用来标识数组中的元素个数
    public int size;

    //构造函数
    public DynamicArray(int[] data, int size) {
        this.data = data;
        this.size = size;
    }
}

2,再写数组方法类DynamicArrayDao;

主要包括数组的各种操作方法,插入、查找等;

package com.java.dao;

import com.java.model.DynamicArray;
import static com.java.model.DynamicArray.capacity;

public class DynamicArrayDao {

    //初始化数组
    public DynamicArray Init_Array(){
        //数组数据域初始化
        int[] data1=new int[capacity];

        //DynamicArray初始化
        DynamicArray myArray=new DynamicArray(data1,0);

        //数组赋值
        for(int i=0;i<capacity;i++){
            myArray.data[i]=0;
        }
        return myArray;
    }

    //插入指定值
    public void PushBack_Array(DynamicArray array,int value){
        if(array==null){
            return;
        }
        //如果线性表容量小于或等于数组容量
        if(array.size==capacity){
            return;
        }
        //插入元素
        array.data[array.size]=value;
        array.size++;
    }

    //根据位置删除
    public void RemoveByPos_Array(DynamicArray array,int pos){
        if (array == null){
            return;
        }
        //判断位置是否有效
        if(pos < 0 || pos >= array.size){
            return;
        }
        //删除元素
        for (int i = pos; i < array.size -1; i ++){
            array.data[i] = array.data[i + 1];
        }
        array.size--;
    }

    //查找元素,返回该值第一次出现时对应的下标位置
    public int Find_Array(DynamicArray array,int value){
        if(array==null){
            return -1;
        }
        //找到该值第一次出现的位置,-1表示没有找到;
        int pos=-1;
        for(int i=0;i<array.size;i++){
            if(array.data[i]==value){
                pos=i;
                break;
            }
        }
        return pos;
    }

    //根据位置查找到某个元素
    public int At_Array(DynamicArray array,int pos){
        if(array==null){
            return -1;
        }
        return array.data[pos];
    }

    //根据值删除
    public void RemoveByValue_Array(DynamicArray array,int value){
        if(array==null){
            return;
        }
        //首先找到该值对应的数组下标
        int pos=Find_Array(array,value);
        //调用根据位置删除的方法
        RemoveByPos_Array(array,pos);
    }

    //打印
    public void Print_Array(DynamicArray array){
        if(array==null){
            return;
        }
        for(int i=0;i<array.size;i++){
            System.out.print(array.data[i]+",");
        }
    }

    //清空数组
    public void Clear_Array(DynamicArray array){
        if(array==null){
            return;
        }
        for(int i=0;i<array.size;i++){
            array.data[i]=0;
        }
        array.size=0;
    }

    //获得动态数组当前元素个数
    public int Size_Array(DynamicArray array){
        if(array==null){
            return -1;
        }
        return array.size;
    }
}

3,主函数Main;

包括测试各种函数等;

package com.java.main;

import com.java.dao.DynamicArrayDao;
import com.java.model.DynamicArray;
import static com.java.model.DynamicArray.capacity;

public class DynamicArrayMain {
    public static void main(String[] args) {
        DynamicArrayDao dynamicArrayDao=new DynamicArrayDao();
        //初始化动态数组
        DynamicArray myArray=dynamicArrayDao.Init_Array();
        System.out.println("初始化动态数组:");
        //获取容量
        System.out.println("数组容量:"+capacity);
        System.out.println("数组实际大小:"+dynamicArrayDao.Size_Array(myArray));
        //插入元素
        for(int i=0;i<10;i++){
            dynamicArrayDao.PushBack_Array(myArray,i);
        }
        System.out.println();

        System.out.println("插入元素之后:");
        //获取容量
        System.out.println("数组容量:"+capacity);
        System.out.println("数组实际大小:"+dynamicArrayDao.Size_Array(myArray));
        System.out.println();

        //打印插入元素
        System.out.println("打印插入的元素:");
        dynamicArrayDao.Print_Array(myArray);
        System.out.println();

        //根据元素位置删除元素
        dynamicArrayDao.RemoveByPos_Array(myArray,2);
        //根据元素值删除元素
        dynamicArrayDao.RemoveByValue_Array(myArray,7);
        System.out.println();

        //打印删除后的数组
        System.out.println("打印删除后的元素:");
        dynamicArrayDao.Print_Array(myArray);
        System.out.println();

        //查找元素为5的位置
        System.out.println();
        System.out.print("元素5的位置为: ");
        int pos=dynamicArrayDao.Find_Array(myArray,5);
        System.out.println(pos);

        //查找位置为7的元素值
        System.out.println();
        System.out.print("位置为7的元素为: ");
        int value=dynamicArrayDao.At_Array(myArray,7);
        System.out.println(value);

        //获取容量
        System.out.println();
        System.out.println("此时的数组容量:"+capacity);
        System.out.println("此时的数组实际大小:"+dynamicArrayDao.Size_Array(myArray));
        System.out.println();
    }
}

运行效果:
在这里插入图片描述

链表:
1,先建立链表结点以及整个链表的实体类;

这里有两个实体类:
LinkNode是结点,包括结点的数据域和指针域;
LinkList是整个链表,包括头结点以及链表元素个数;

package com.java.model;

public class LinkNode {
    //链表结点的数据域
    public Object data;
    //链表结点的指针域
    public LinkNode next;

    public LinkNode() {
        super();
        // TODO Auto-generated constructor stub
    }

    //构造方法
    public LinkNode(Object data, LinkNode next) {
        super();
        this.data = data;
        this.next = next;
    }

}

package com.java.model;

public class LinkList {
    //链表的头结点
    public LinkNode head;
    //链表的元素个数
    public int size;

    public LinkList() {
        super();
        // TODO Auto-generated constructor stub
    }

    ///构造方法
    public LinkList(LinkNode head, int size) {
        super();
        this.head = head;
        this.size = size;
    }

}

2,再写链表方法类LinkListDao;

package com.java.dao;

import com.java.model.LinkList;
import com.java.model.LinkNode;

public class LinkListDao {
    //初始化链表
    public LinkList Init_LinkList(){
        //设置头结点的指针域和数据域
        LinkNode node=new LinkNode(0,null);
        LinkList list=new LinkList(node,0);
        return list;
    }
    //指定位置插入
    public void Insert_LinkList(LinkList list, int pos, Object data){
        //判断list是否有效
        if(list==null){
            return;
        }
        //判断data是否有效
        if (data==null){
            return;
        }
        //判断位置pos是否有效
        if (pos<0 || pos>list.size){
            //在链表的尾部插入
            pos = list.size;
        }

        //第一步,创建新的结点,也就是待插入的结点
        LinkNode newNode=new LinkNode(data,null);
        //第二步,找到待插入结点前面一个结点pCurrent,并使其等于list的头结点
        LinkNode pCurrent=list.head;
        for(int i = 0 ; i < pos ; i++){
            pCurrent=pCurrent.next;
        }
        //第三步,新结点入链表,进行插入操作
        newNode.next=pCurrent.next;
        pCurrent.next=newNode;
        //第四步,链表的size要加1
        list.size++;

    }
    //删除指定位置的值
    public void RemoveByPos_LinkList(LinkList list, int pos){
        if(list==null){
            return;
        }
        if(pos<0||pos>=list.size){
            return;
        }
        //第一步,找到待删除结点的前面一个结点pCurrent
        LinkNode pCurrent=list.head;
        for (int i = 0; i < pos; i++) {
            pCurrent=pCurrent.next;
        }
        //第二步,进行删除操作
        pCurrent.next=pCurrent.next.next;
        //第三步,链表的size要减1
        list.size--;
    }
    //获得链表的长度
    public int Size_LinkList(LinkList list){
        return list.size;
    }
    //查找指定元素的位置
    public void Find_LinkList(LinkList list, Object data){
        //注意这里要从头结点的下一个结点开始,因为头结点不存放数据信息
        LinkNode pCurrent=list.head.next;
        for (int i = 0; i < list.size; i++) {
            if(pCurrent.data==data){
                System.out.print(i+",");
            }
            pCurrent=pCurrent.next;
        }
    }
    //返回第一个结点元素的值
    public Object Front_LinkList(LinkList list){
        return list.head.next.data;
    }
    //打印链表结点
    public void Print_LinkList(LinkList list){
        if(list==null){
            return;
        }
        LinkNode pCurrent=list.head.next;
        for (int i = 0; i < list.size; i++) {
            System.out.print(pCurrent.data+",");
            pCurrent=pCurrent.next;
        }
    }

}

3,主函数Main;

测试各种方法类;

package com.java.main;

import com.java.dao.LinkListDao;
import com.java.model.LinkList;

public class LinkListMain {
    public static void main(String[] args) {
        LinkListDao linkListDao=new LinkListDao();
        //创建链表
        LinkList list=linkListDao.Init_LinkList();

        //数据插入链表
        linkListDao.Insert_LinkList(list, 0, "A");
        linkListDao.Insert_LinkList(list, 1, "B");
        linkListDao.Insert_LinkList(list, 2, "C");
        linkListDao.Insert_LinkList(list, 3, "D");
        linkListDao.Insert_LinkList(list, 4, "D");

        //打印链表
        System.out.println("插入数据之后的链表为:");
        linkListDao.Print_LinkList(list);
        System.out.println();

        //删除指定位置的值
        linkListDao.RemoveByPos_LinkList(list, 2);

        //打印链表
        System.out.println("删除元素C之后的链表为:");
        linkListDao.Print_LinkList(list);
        System.out.println();

        //获得链表长度
        System.out.println("链表长度为:");
        System.out.println(linkListDao.Size_LinkList(list));

        //查找值为3的位置
        System.out.println("值为D的位置为:");
        linkListDao.Find_LinkList(list, "D");
        System.out.println();

        //返回第一个结点元素的值
        System.out.println("第一个结点元素为:");
        System.out.println(linkListDao.Front_LinkList(list));
    }
}

运行结果:
在这里插入图片描述

文中代码格式是仿照MVC模式写的,建议大家也这样写,比较整齐我感觉。
这次就分享到这里了,后续还有一系列的数据结构的文章哦,请大家期待!

发布了295 篇原创文章 · 获赞 100 · 访问量 9万+

猜你喜欢

转载自blog.csdn.net/qq_37084904/article/details/104561331
今日推荐