写在前面:
数组和链表是数据结构中最基础的两种结构,其他的都是由这两者转化而来;
因此,掌握这两种结构至关重要!下面,时光就带大家来学习一下数组和链表;
思维导图:
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模式写的,建议大家也这样写,比较整齐我感觉。
这次就分享到这里了,后续还有一系列的数据结构的文章哦,请大家期待!
右下角点个再看吧!蟹蟹哦~