数据结构的分类


尾部插入,是最简单的情况。直接把插入的元素放在数组尾部的空闲位置即可,等同于更新元素的操作。
中间插入
中间插入,由于数组的每一个元素都有其固定下标,所以不得不首先把插入位置及后面的元素向后移动,腾出地方,再把要插入的元素放到对应的数组位置上。 ```java package com.mu.array;
/**
中间插入 */ public class MyArray { private int[] array; private int size; //数组实际元素数量
public MyArray(int capacity) {
this.array = new int[capacity];size = 0;
}
/**
- 数组插入元素 *
- @param index 插入位置
@param element 插入的元素 */ public void insert(int index, int element) throws Exception { //判断访问下标是否超出范围 if (index < 0 || index > size) {
throw new IndexOutOfBoundsException("超出数组实际元素范围!");
} //从右向左循环,将元素逐个向右挪1位 for (int i = size - 1; i >= index; i—) {
array[i + 1] = array[i];
} //腾出的位置放入新元素 array[index] = element; size++; }
/**
输出数组 */ public void output() { for (int i = 0; i < size; i++) {
System.out.print(array[i]+",");
} }
public static void main(String[] args) throws Exception { MyArray myArray = new MyArray(10); myArray.insert(0,3); //不用挪,因为数组中还没元素 myArray.insert(1,7); myArray.insert(2,9); myArray.insert(3,5); myArray.insert(1,6); myArray.output(); } }
<a name="y03fg"></a>#### 超范围插入- 假如有一个长度为6的数组,已经装满了元素,此时还想插入一个新元素。这就涉及到数组的扩容了,此时可以创建一个新的数组,长度是旧数组的2倍,再把旧数组中的元素统统复制过去,这样就实现了数组的扩容。- **arraycopy( )方法:**- arraycopy()方法用于将一个[数组](https://so.csdn.net/so/search?q=%E6%95%B0%E7%BB%84&spm=1001.2101.3001.7020)的元素快速拷贝到另一个数组。其中的参数如下- System.arraycopy(src, srcPos, dest, destPos, length);- src表示源数组,srcPos表示源数组中拷贝元素的起始位置。dest表示目标数组,destPos表示拷贝到目标数组的起始位置,length表示拷贝元素的个数。- 需要注意的是在进行数组拷贝时,目标数组必须有足够的空间来存放拷贝的元素,否则就会发生下标越界异常。```javapackage com.mu.array;/*** 超范围插入*/public class MyArray2 {private int[] array;private int size;public MyArray2(int capacity) {this.array = new int[capacity];size = 0;}/*** 插入元素方法** @param index 插入位置* @param element 插入元素*/public void insert(int index, int element) throws Exception {if (index < 0 || index > size) {throw new IndexOutOfBoundsException("超出数组实际元素范围!");}//若元素数量已达到数组容量上限,则对数组进行扩容if (size >= array.length) {resize();}//从右向左循环,将元素逐个向右挪1位,将插入位置腾出来for (int i = size - 1; i >= index; i--) {array[i + 1] = array[i];}//腾出的位置放入新元素array[index] = element;size++;}/*** 数组扩容方法*/public void resize() {int[] arrayNew = new int[array.length * 2];System.arraycopy(array, 0, arrayNew, 0, array.length);array = arrayNew;}/*** 输出数组*/public void output() {for (int i = 0; i < size; i++) {System.out.println(array[i]);}System.out.println("数组扩容后的大小:"+array.length);}public static void main(String[] args) throws Exception {MyArray2 myArray2 = new MyArray2(4);myArray2.insert(0,3);myArray2.insert(1,7);myArray2.insert(2,9);myArray2.insert(3,5);//超范围插入myArray2.insert(1,6);myArray2.output();}}
删除元素
- 数组的删除操作和插入的过程相反,如果删除的元素位于数组中间,其后的元素都需要向前挪一位。 ```java package com.mu.array;
/**
删除操作 */ public class MyArray3 { private int[] array; private int size;
public MyArray3() {
this.array = new int[]{1,2,3};size = array.length;
}
/**
- 删除操作 *
@param index 删除位置 */ public int delete(int index) { if (index < 0 || index >= size) {
throw new IndexOutOfBoundsException("超出数组实际元素范围!");
} int deletedElement = array[index]; //从左向右循环,将元素逐个向左挪1位 for (int i = index; i < size - 1; i++) {
array[i] = array[i + 1];
} size—; return deletedElement; }
/**
输出数组 */ public void output() { for (int i = 0; i < size; i++) {
System.out.println(array[i]);
} }
public static void main(String[] args) { MyArray3 myArray3 = new MyArray3(); myArray3.output(); int delete = myArray3.delete(2); System.out.println(“删除的元素:”+delete); myArray3.output();
} }
<a name="BuvNy"></a># 链表<a name="Kyk28"></a>## 链表的基本操作```javapackage com.mu.linked;public class MyLinkedList {//头结点指针private Node head;//尾结点指针(为了尾部插入的方便,增加了尾结点指针)private Node last;//链表实际长度private int size;/*** 链表节点*/private static class Node {int data;Node next;Node(int data) {this.data = data;}}/*** 查找节点** @param index 查找的位置* @return 查找的结点*/public Node get(int index) throws Exception {if (index < 0 || index > size) {throw new IndexOutOfBoundsException("超出链表节点范围");}Node temp = head; // 1.将查找的指针定位到头结点for (int i = 0; i < index; i++) {temp = temp.next; // 2.根据头结点的next指针,定位后面的结点}return temp;}/*** 链表插入元素** @param data 插入元素* @param index 插入位置*/public void insert(int data, int index) throws Exception {if (index < 0 || index > size) {throw new IndexOutOfBoundsException("超出链表节点范围");}//将插入的数据包装到Node节点中Node insertNode = new Node(data);if (size == 0) {//空链表head = insertNode;last = insertNode;} else if (index == 0) {//头部插入insertNode.next = head; //1.把新节点的next指针指向原先的头结点head = insertNode;//2.把新节点变为链表的头结点} else if (index == size) {//尾部插入last.next = insertNode;//1.把最后一个节点的next指针指向新插入的节点last = insertNode;//把新节点变为链表的尾结点} else {//中间插入Node prevNode = get(index - 1); //1.获取插入位置的前置结点insertNode.next = prevNode.next; //2.新节点的next指针指向插入位置的结点prevNode.next = insertNode; //3.前置结点的next指针,指向新节点}size++;}/*** 链表删除元素** @param index 删除位置* @return 删除的结点*/public Node remove(int index) throws Exception {if (index < 0 || index >= size) {throw new IndexOutOfBoundsException("超出链表结点范围");}Node removeNode = null;if (index == 0) {//删除头结点removeNode = head;head = head.next; //1.把链表的头结点设为原头结点的next指针} else if (index == size - 1) {//删除尾部结点Node prevNode = get(index - 1);//1.获取倒数第2个结点removeNode = prevNode.next;prevNode.next = null; //2. 将倒数第2个结点的next指针指向空即可last = prevNode; //3.尾结点指针指向preNode} else {//删除中间结点Node prevNode = get(index - 1); //1.目标结点的前置结点removeNode = prevNode.next;prevNode.next = prevNode.next.next; //2.把要删除的目标节点的前置结点的next指针指向要删除的元素的下一个结点}size--;return removeNode;}/*** 输出链表*/public void output() {Node temp = head;while (temp != null) {System.out.println(temp.data);temp = temp.next;}}public static void main(String[] args) throws Exception {MyLinkedList myLinkedList = new MyLinkedList();myLinkedList.insert(3, 0);myLinkedList.insert(4, 1);myLinkedList.insert(5, 2);myLinkedList.insert(6, 3);Node remove = myLinkedList.remove(2);myLinkedList.remove(2);myLinkedList.output();}}
数组VS链表
| 查找 | 更新 | 插入 | 删除 | |
|---|---|---|---|---|
| 数组 | O(1) | O(1) | O(n) | O(n) |
| 链表 | O(n) | O(1) | O(1) | O(1) |
