浅谈数组和链表

?写在前面:

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

思维导图:

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;
11
12    //构造函数
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    }
108
109    //获得动态数组当前元素个数
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();
21
22        System.out.println("插入元素之后:");
23        //获取容量
24        System.out.println("数组容量:"+capacity);
25        System.out.println("数组实际大小:"+dynamicArrayDao.Size_Array(myArray));
26        System.out.println();
27
28        //打印插入元素
29        System.out.println("打印插入的元素:");
30        dynamicArrayDao.Print_Array(myArray);
31        System.out.println();
32
33        //根据元素位置删除元素
34        dynamicArrayDao.RemoveByPos_Array(myArray,2);
35        //根据元素值删除元素
36        dynamicArrayDao.RemoveByValue_Array(myArray,7);
37        System.out.println();
38
39        //打印删除后的数组
40        System.out.println("打印删除后的元素:");
41        dynamicArrayDao.Print_Array(myArray);
42        System.out.println();
43
44        //查找元素为5的位置
45        System.out.println();
46        System.out.print("元素5的位置为: ");
47        int pos=dynamicArrayDao.Find_Array(myArray,5);
48        System.out.println(pos);
49
50        //查找位置为7的元素值
51        System.out.println();
52        System.out.print("位置为7的元素为: ");
53        int value=dynamicArrayDao.At_Array(myArray,7);
54        System.out.println(value);
55
56        //获取容量
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 stub
12    }
13
14    //构造方法
15    public LinkNode(Object data, LinkNode next) {
16        super();
17        this.data = data;
18        this.next = next;
19    }
20
21}
 
 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 stub
12    }
13
14    ///构造方法
15    public LinkList(LinkNode head, int size) {
16        super();
17        this.head = head;
18        this.size = size;
19    }
20
21}
 

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        }
29
30        //第一步,创建新的结点,也就是待插入的结点
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要加1
41        list.size++;
42
43    }
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        //第一步,找到待删除结点的前面一个结点pCurrent
53        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要减1
60        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    }
92
93}
 

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();
11
12        //数据插入链表
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");
18
19        //打印链表
20        System.out.println("插入数据之后的链表为:");
21        linkListDao.Print_LinkList(list);
22        System.out.println();
23
24        //删除指定位置的值
25        linkListDao.RemoveByPos_LinkList(list, 2);
26
27        //打印链表
28        System.out.println("删除元素C之后的链表为:");
29        linkListDao.Print_LinkList(list);
30        System.out.println();
31
32        //获得链表长度
33        System.out.println("链表长度为:");
34        System.out.println(linkListDao.Size_LinkList(list));
35
36        //查找值为3的位置
37        System.out.println("值为D的位置为:");
38        linkListDao.Find_LinkList(list, "D");
39        System.out.println();
40
41        //返回第一个结点元素的值
42        System.out.println("第一个结点元素为:");
43        System.out.println(linkListDao.Front_LinkList(list));
44    }
45}
 

运行结果:

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

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

原文地址:https://www.cnblogs.com/huke123/p/12382176.html

时间: 2024-11-08 10:29:56

浅谈数组和链表的相关文章

https://github.com/miaozhongfeng/my-repository.git浅谈数组求和java实验

          这次作业呢,我是用java来写的,虽然java只是自己假期里看的一点点,但是人总是要接触新事物的,应该不断向前.          说明:这次作业有一个遗憾,就是我花了一个下午真真没搞懂POI包的使用,是我的智商问题吗?由于作业提交比较急迫,暂时先放弃,用的java的文件流,男人嘛,就是要敢舍敢弃!(是我胡说八道的).当然,不搞懂它我是不会罢休的!拭目以待!          好了,不瞎扯了.进入正题吧.我用的编译软件是my Eclipse2014(这个软件不得不说:真TM好

浅谈数组与指针

对于一维数组与指针: 对于二维数组与指针:

【JAVA基础教程】-浅谈数组及其内存控制

在用JAVA数据前我们都知道必须要先对数组对象进行初始化.当数组的所有元素都被分配合适的内存空间,当制定了初始值时,数组初始化完成.程序以后将不能重新改变数组对象在内存中的位置和大小.那么: 1.JAVA数组为静态,即一旦初始化后,其长度是不可改变的. 2. 数组变量是引用变量,并不是数组对象本身. 3. 两种初始化方式: 动态初始化:指定数组的长度,初始值自动生成. 静态初始化:指定初始值,长度自动生成. 4. JAVA中,引用变量本身无需初始化,引用变量所引用的对象是需要初始化的. 5. 所

浅谈数组

数组 我们平常在书写代码的时候遇到需要使用多个数据,通过定义多个变量太麻烦了,所以就定义了数组. 数组的概念和作用 数组是一组数据的集合,用来存放多个数据.适用于需要操控多个数据,但是只能使用一个数据的情况. 数组的创建 字面量 var arr = []; 构造函数 var arr = new Array(); 注意事项 当两种方式创建数组,数组参数为1时,如下代码所示 var arr = [5]; //[5]代表数组里只有一个成员5 var arr1 = new Array(5);//[emp

ES6浅谈 -- 数组扩展

1.数组可以用spread参数合并,使用该参数要注意被合并的一定是一个数组对象.另外不管是数组合并还是数组拼接都是浅拷贝,实质是拷贝地址(引用). 2.可以和解构赋值混用,如const [first, ...rest] = [1,2,3,4,5]; 还可以将字符串每个字符拆分然后变成数组元素. 3.Array.from(),将类数组对象和可遍历对象转成数组:Array.of(),将一组值转为数组,与Array不同的是,array只跟一个参数会认为输入了这个数组的长度,而array of则认为是输

ES6浅谈--数组扩展、对象扩展

数组扩展 1.includes()方法,参数为要检测的值.includes方法有点像indexOf(),indexOf未检测到则返回-1,否则返回下标.includes则是返回true或false.includes可以检测NaN.第二个参数表示从什么位置检测. 2.flat和flatMap.flat负责把数组拉平,意思是一个二维数组调用flat方法会变成一维数组.参数传的是数组的维度.例如传2则表示将3维拉成1维.如果数组中有空位则跳过.flatMap有点像flat方法和Map方法的结合.先对每

浅谈二维中的树状数组与线段树

一般来说,树状数组可以实现的东西线段树均可胜任,实际应用中也是如此.但是在二维中,线段树的操作变得太过复杂,更新子矩阵时第一维的lazy标记更是麻烦到不行. 但是树状数组在某些询问中又无法胜任,如最值等不符合区间减法的询问.此时就需要根据线段树与树状数组的优缺点来选择了. 做一下基本操作的对比,如下图. 因为线段树为自上向下更新,从而可以使用lazy标记使得矩阵的更新变的高校起来,几个不足就是代码长,代码长和代码长. 对于将将矩阵内元素变为某个值,因为树状数组自下向上更新,且要满足区间加法等限制

转: 浅谈C/C++中的指针和数组(二)

转自:http://www.cnblogs.com/dolphin0520/archive/2011/11/09/2242419.html 浅谈C/C++中的指针和数组(二) 前面已经讨论了指针和数组的一些区别,然而在某些情况下,指针和数组是等同的,下面讨论一下什么时候指针和数组是相同的. C语言标准对此作了说明: 规则1:表达式中的数组名被编译器当做一个指向该数组第一个元素的指针: 注:下面几种情况例外 1)数组名作为sizeof的操作数 2)使用&取数组的地址 规则2:下标总是与指针的偏移量

转:浅谈C/C++中的指针和数组(一)

转自:http://www.cnblogs.com/dolphin0520/archive/2011/11/09/2242138.html 浅谈C/C++中的指针和数组(一) 指针是C/C++的精华,而指针和数组又是一对欢喜冤家,很多时候我们并不能很好的区分指针和数组,对于刚毕业的计算机系的本科生很少有人能够熟练掌握指针以及数组的用法和区别.造成这种原因可能跟现在大学教学以及现在市面上流行的很多C或者C++教程有关,这些教程虽然通俗易懂,但是在很多关键性的地方却避而不谈或者根本阐述不清楚,甚至很