数据结构–链表
定义
链表是一种线性表,但是不像数组一样连续存储,而是将每组数据存储一个结点中,每个结点中又有着指向下一个结点的指针
优点:
缺点:
-
访问时间复杂度为O(n) -
不能随机访问,没有索引 -
增加了结点的指针域,空间开销大
实现
我们自定义一个链表
public class MyLink<T> {}
结点
首先链表要有结点,结点中有指针域和数据域,我们定义一个结点类
private class Node {
private T value;
private Node next;
public Node(T value) {
this.value = value;
this.next = null;
}
@Override
public String toString() {
return value.toString();
}
}
链表的基本属性和方法
private Node head;
private int size;
public MyLink() {
this.head = null;
this.size = 0;
}
public boolean isEmpty() {
return this.size == 0;
}
public int getSize() {
return this.size;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
Node cur = head;
while (cur != null && cur.next != null) {
sb.append(cur + "->");
cur = cur.next;
}
return sb.toString();
}
增
add()1.0
public void add(int index, T value) {
if (index < 0 || index > size) {
throw new IllegalArgumentException("要添加的位置不合法");
}
Node node = new Node(value);
if (head == null) {
head = node;
this.size++;
return;
}
if (index == 0) {
node.next = head;
head = node;
this.size++;
return;
}
Node pre = head;
for (int i = 0; i < index - 1; i++) {
pre = pre.next;
}
node.next = pre.next;
pre.next = node;
this.size++;
}
public void addTail(T value) {
Node node = new Node(value);
if (head == null) {
head = node;
} else {
Node curNode = head;
while (curNode.next != null) {
curNode = curNode.next;
}
curNode.next = node;
}
this.size++;
}
public void addHead(T value) {
Node node = new Node(value);
node.next = head;
head = node;
}
add()2.0,增加了虚拟头结点,使得每一个结点都有其前驱结点
public void add(int index, T value) {
if (index < 0 || index > size) {
throw new IllegalArgumentException("要添加的位置不合法");
}
Node dummyHead = new Node(null);
dummyHead.next = head;
Node node = new Node(value);
Node preNode = dummyHead;
for (int i = 0; i < index; i++) {
preNode = preNode.next;
}
node.next = preNode.next;
preNode.next = node;
head = dummyHead.next;
this.size++;
}
public void addTail(T value) {
this.add(this.size, value);
}
public void addHead(T value) {
this.add(0, value);
}
删
remove()1.0
public T remove(int index) {
if (index < 0 || index >= size) {
throw new IllegalArgumentException("index不合法");
}
T res = null;
if (index == 0) {
res = head.value;
head = head.next;
this.size--;
} else {
Node pre = head;
for (int i = 0; i < index - 1; i++) {
pre = pre.next;
}
res = pre.next.value;
pre.next = pre.next.next;
this.size--;
}
return res;
}
public T removeHead() {
T res = null;
if(head == null){
return res;
}
res = head.value;
head = head.next;
this.size--;
return res;
}
public T removeTail() {
T res = null;
if(head == null){
return res;
}
if(this.size==1){
this.size--;
res = head.value;
head = null;
}else{
Node pre = head;
for (int i = 0; i < this.size-2; i++) {
pre = pre.next;
}
res = pre.next.value;
this.size--;
}
return res;
}
remove()2.0
public T remove(int index) {
if (index < 0 || index >= size) {
throw new IllegalArgumentException("index不合法");
}
Node dummyHead = new Node(null);
dummyHead.next = head;
Node pre = dummyHead;
for (int i = 0; i < index; i++) {
pre = pre.next;
}
Node delNode = pre.next;
T res = delNode.value;
pre.next = delNode.next;
delNode.next = null;
head = dummyHead.next;
this.size--;
return res;
}
public T removeHead() {
return remove(0);
}
public T removeTail() {
return remove(this.size - 1);
}
改
public void set(int index,T value){
if (index < 0 || index >= size) {
throw new IllegalArgumentException("index不合法");
}
Node curNode = head;
for (int i = 0; i < index; i++) {
curNode = curNode.next;
}
curNode.value = value;
}
public void setHead(T value){
this.set(0, value);
}
public void setTail(T value){
this.set(this.size-2, value);
}
查
public boolean isContains(T v){
Node curNode = head;
while (curNode != null && !curNode.value.equals(v)) {
curNode = curNode.next;
}
return curNode != null;
}
测试
package com.company.project.subject.day3;
import java.util.Random;
public class MyLinkTest {
public static void main(String[] args) {
MyLink<Integer> myLink = new MyLink<>();
for (int i = 0; i < 5; i++) {
myLink.addTail(new Random().nextInt(100));
}
System.out.println("尾插:" + myLink);
myLink.addHead(0);
System.out.println("头插:" + myLink);
myLink.add(1, 1);
System.out.println("索引为1的位置插入:" + myLink);
myLink.removeHead();
System.out.println("删除头结点: " + myLink);
myLink.remove(2);
System.out.println("删除索引为2的结点:" + myLink);
myLink.removeTail();
System.out.println("删除尾结点:" + myLink);
System.out.println("指定索引1的结点:" + myLink.get(1));
System.out.println("查找头结点:" + myLink.getHead());
System.out.println("查找尾结点:" + myLink.getTail());
System.out.println("是否包含元素1:"+myLink.isContains(1));
myLink.set(0,100 );
System.out.println("修改索引0的结点内容为100: "+myLink);
myLink.setTail(100);
System.out.println("修改尾结点内容为100: "+myLink);
}
}
|