浅谈数组和链表

206 阅读9分钟

​写在前面:

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

思维导图:

1,什么是线性表?

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

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

数组来存储的线性表就是顺序表

2,数组和链表

数组:在内存中,是一块连续的内存区域;
链表:是由不连续的内存空间组成;

3,数组和链表的区别

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

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

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

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

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

 1package com.java.model; 2 3public class DynamicArray { 4    //动态数组最大容量 5    public final static int capacity = 100; 6 7    //顺序表的结点数据 8    public int[] data; 9    //顺序表的长度,用来标识数组中的元素个数10    public int size;1112    //构造函数13    public DynamicArray(int[] data, int size) {14        this.data = data;15        this.size = size;16    }17}

2,再写数组方法类DynamicArrayDao;

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

  1package com.java.dao;  2  3import com.java.model.DynamicArray;  4import static com.java.model.DynamicArray.capacity;  5  6public class DynamicArrayDao {  7  8    //初始化数组  9    public DynamicArray Init_Array(){ 10        //数组数据域初始化 11        int[] data1=new int[capacity]; 12 13        //DynamicArray初始化 14        DynamicArray myArray=new DynamicArray(data1,0); 15 16        //数组赋值 17        for(int i=0;i<capacity;i++){ 18            myArray.data[i]=0; 19        } 20        return myArray; 21    } 22 23    //插入指定值 24    public void PushBack_Array(DynamicArray array,int value){ 25        if(array==null){ 26            return; 27        } 28        //如果线性表容量小于或等于数组容量 29        if(array.size==capacity){ 30            return; 31        } 32        //插入元素 33        array.data[array.size]=value; 34        array.size++; 35    } 36 37    //根据位置删除 38    public void RemoveByPos_Array(DynamicArray array,int pos){ 39        if (array == null){ 40            return; 41        } 42        //判断位置是否有效 43        if(pos < 0 || pos >= array.size){ 44            return; 45        } 46        //删除元素 47        for (int i = pos; i < array.size -1; i ++){ 48            array.data[i] = array.data[i + 1]; 49        } 50        array.size--; 51    } 52 53    //查找元素,返回该值第一次出现时对应的下标位置 54    public int Find_Array(DynamicArray array,int value){ 55        if(array==null){ 56            return -1; 57        } 58        //找到该值第一次出现的位置,-1表示没有找到; 59        int pos=-1; 60        for(int i=0;i<array.size;i++){ 61            if(array.data[i]==value){ 62                pos=i; 63                break; 64            } 65        } 66        return pos; 67    } 68 69    //根据位置查找到某个元素 70    public int At_Array(DynamicArray array,int pos){ 71        if(array==null){ 72            return -1; 73        } 74        return array.data[pos]; 75    } 76 77    //根据值删除 78    public void RemoveByValue_Array(DynamicArray array,int value){ 79        if(array==null){ 80            return; 81        } 82        //首先找到该值对应的数组下标 83        int pos=Find_Array(array,value); 84        //调用根据位置删除的方法 85        RemoveByPos_Array(array,pos); 86    } 87 88    //打印 89    public void Print_Array(DynamicArray array){ 90        if(array==null){ 91            return; 92        } 93        for(int i=0;i<array.size;i++){ 94            System.out.print(array.data[i]+","); 95        } 96    } 97 98    //清空数组 99    public void Clear_Array(DynamicArray array){100        if(array==null){101            return;102        }103        for(int i=0;i<array.size;i++){104            array.data[i]=0;105        }106        array.size=0;107    }108109    //获得动态数组当前元素个数110    public int Size_Array(DynamicArray array){111        if(array==null){112            return -1;113        }114        return array.size;115    }116}

3,主函数Main;

包括测试各种函数等;

 1package com.java.main; 2 3import com.java.dao.DynamicArrayDao; 4import com.java.model.DynamicArray; 5import static com.java.model.DynamicArray.capacity; 6 7public class DynamicArrayMain { 8    public static void main(String[] args) { 9        DynamicArrayDao dynamicArrayDao=new DynamicArrayDao();10        //初始化动态数组11        DynamicArray myArray=dynamicArrayDao.Init_Array();12        System.out.println("初始化动态数组:");13        //获取容量14        System.out.println("数组容量:"+capacity);15        System.out.println("数组实际大小:"+dynamicArrayDao.Size_Array(myArray));16        //插入元素17        for(int i=0;i<10;i++){18            dynamicArrayDao.PushBack_Array(myArray,i);19        }20        System.out.println();2122        System.out.println("插入元素之后:");23        //获取容量24        System.out.println("数组容量:"+capacity);25        System.out.println("数组实际大小:"+dynamicArrayDao.Size_Array(myArray));26        System.out.println();2728        //打印插入元素29        System.out.println("打印插入的元素:");30        dynamicArrayDao.Print_Array(myArray);31        System.out.println();3233        //根据元素位置删除元素34        dynamicArrayDao.RemoveByPos_Array(myArray,2);35        //根据元素值删除元素36        dynamicArrayDao.RemoveByValue_Array(myArray,7);37        System.out.println();3839        //打印删除后的数组40        System.out.println("打印删除后的元素:");41        dynamicArrayDao.Print_Array(myArray);42        System.out.println();4344        //查找元素为5的位置45        System.out.println();46        System.out.print("元素5的位置为: ");47        int pos=dynamicArrayDao.Find_Array(myArray,5);48        System.out.println(pos);4950        //查找位置为7的元素值51        System.out.println();52        System.out.print("位置为7的元素为: ");53        int value=dynamicArrayDao.At_Array(myArray,7);54        System.out.println(value);5556        //获取容量57        System.out.println();58        System.out.println("此时的数组容量:"+capacity);59        System.out.println("此时的数组实际大小:"+dynamicArrayDao.Size_Array(myArray));60        System.out.println();61    }62}

运行效果:


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

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

 1package com.java.model; 2 3public class LinkNode { 4    //链表结点的数据域 5    public Object data; 6    //链表结点的指针域 7    public LinkNode next; 8 9    public LinkNode() {10        super();11        // TODO Auto-generated constructor stub12    }1314    //构造方法15    public LinkNode(Object data, LinkNode next) {16        super();17        this.data = data;18        this.next = next;19    }2021}
 1package com.java.model; 2 3public class LinkList { 4    //链表的头结点 5    public LinkNode head; 6    //链表的元素个数 7    public int size; 8 9    public LinkList() {10        super();11        // TODO Auto-generated constructor stub12    }1314    ///构造方法15    public LinkList(LinkNode head, int size) {16        super();17        this.head = head;18        this.size = size;19    }2021}

2,再写链表方法类LinkListDao;

 1package com.java.dao; 2 3import com.java.model.LinkList; 4import com.java.model.LinkNode; 5 6public class LinkListDao { 7    //初始化链表 8    public LinkList Init_LinkList(){ 9        //设置头结点的指针域和数据域10        LinkNode node=new LinkNode(0,null);11        LinkList list=new LinkList(node,0);12        return list;13    }14    //指定位置插入15    public void Insert_LinkList(LinkList list, int pos, Object data){16        //判断list是否有效17        if(list==null){18            return;19        }20        //判断data是否有效21        if (data==null){22            return;23        }24        //判断位置pos是否有效25        if (pos<0 || pos>list.size){26            //在链表的尾部插入27            pos = list.size;28        }2930        //第一步,创建新的结点,也就是待插入的结点31        LinkNode newNode=new LinkNode(data,null);32        //第二步,找到待插入结点前面一个结点pCurrent,并使其等于list的头结点33        LinkNode pCurrent=list.head;34        for(int i = 0 ; i < pos ; i++){35            pCurrent=pCurrent.next;36        }37        //第三步,新结点入链表,进行插入操作38        newNode.next=pCurrent.next;39        pCurrent.next=newNode;40        //第四步,链表的size要加141        list.size++;4243    }44    //删除指定位置的值45    public void RemoveByPos_LinkList(LinkList list, int pos){46        if(list==null){47            return;48        }49        if(pos<0||pos>=list.size){50            return;51        }52        //第一步,找到待删除结点的前面一个结点pCurrent53        LinkNode pCurrent=list.head;54        for (int i = 0; i < pos; i++) {55            pCurrent=pCurrent.next;56        }57        //第二步,进行删除操作58        pCurrent.next=pCurrent.next.next;59        //第三步,链表的size要减160        list.size--;61    }62    //获得链表的长度63    public int Size_LinkList(LinkList list){64        return list.size;65    }66    //查找指定元素的位置67    public void Find_LinkList(LinkList list, Object data){68        //注意这里要从头结点的下一个结点开始,因为头结点不存放数据信息69        LinkNode pCurrent=list.head.next;70        for (int i = 0; i < list.size; i++) {71            if(pCurrent.data==data){72                System.out.print(i+",");73            }74            pCurrent=pCurrent.next;75        }76    }77    //返回第一个结点元素的值78    public Object Front_LinkList(LinkList list){79        return list.head.next.data;80    }81    //打印链表结点82    public void Print_LinkList(LinkList list){83        if(list==null){84            return;85        }86        LinkNode pCurrent=list.head.next;87        for (int i = 0; i < list.size; i++) {88            System.out.print(pCurrent.data+",");89            pCurrent=pCurrent.next;90        }91    }9293}

3,主函数Main;

测试各种方法类;

 1package com.java.main; 2 3import com.java.dao.LinkListDao; 4import com.java.model.LinkList; 5 6public class LinkListMain { 7    public static void main(String[] args) { 8        LinkListDao linkListDao=new LinkListDao(); 9        //创建链表10        LinkList list=linkListDao.Init_LinkList();1112        //数据插入链表13        linkListDao.Insert_LinkList(list, 0, "A");14        linkListDao.Insert_LinkList(list, 1, "B");15        linkListDao.Insert_LinkList(list, 2, "C");16        linkListDao.Insert_LinkList(list, 3, "D");17        linkListDao.Insert_LinkList(list, 4, "D");1819        //打印链表20        System.out.println("插入数据之后的链表为:");21        linkListDao.Print_LinkList(list);22        System.out.println();2324        //删除指定位置的值25        linkListDao.RemoveByPos_LinkList(list, 2);2627        //打印链表28        System.out.println("删除元素C之后的链表为:");29        linkListDao.Print_LinkList(list);30        System.out.println();3132        //获得链表长度33        System.out.println("链表长度为:");34        System.out.println(linkListDao.Size_LinkList(list));3536        //查找值为3的位置37        System.out.println("值为D的位置为:");38        linkListDao.Find_LinkList(list, "D");39        System.out.println();4041        //返回第一个结点元素的值42        System.out.println("第一个结点元素为:");43        System.out.println(linkListDao.Front_LinkList(list));44    }45}

运行结果:

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

右下角点个再看吧!蟹蟹哦~