我们以前学过的线性数据结构底层原理都是依托静态数组来实现的,今天我们讲学习一个最简单的动态数据结构---->链表!
掌握链表有助于学习更加复杂的数据结构,例如:二叉树、trie
链表的优点是不需要处理固定的问题,真正的动态,缺点是丧失了随机访问的能力
在生活中可以形象表示链表的东西有很多,比如自行车车链
在数据结构中我们学习的是他们的最基本的操作增删改查,下面让我们来逐步了解链表的实现
增加:
1.在头部添加
2.在尾部添加
3.在中间进行添加:
这种添加情况需要对在头结点进行添加时进行特别处理,比如判断头结点是否为空等
进行虚拟头结点进行添加操作:
public void addHead(T ele) {
this.add(0, ele);
}
public void addTail(T ele) {
this.add(this.size, ele);
}
// 在指定位置添加结点, 关键点: 找到待插入位置的前一个结点
public void add(int index, T ele) {
if (index < 0 || index > this.size) {
throw new IllegalArgumentException("index is invalid!");
}
Node node = new Node(ele);
// 给链表增加一个虚拟头结点, 解决在链表的头部添加时的特殊处理
Node dummyHead = new Node(null);
dummyHead.next = head;
Node prev = dummyHead;
for (int i = 0; i < index; i++) {
prev = prev.next;
}
node.next = prev.next;
prev.next = node;
// 更新头结点
head = dummyHead.next;
this.size++;
}
在增加和删除的时候需要知道操作位置上前节点pre,删除和查找不需要
删除:
在头部进行删除: 在尾部进行删除:
在中间进行删除:
使用虚拟头结点则不需要对头结点进行特殊操作
//将链表中的元素进行删除
public void delete(int index) {
if (index < 0 || index >= this.size) {
}
//无虚拟头结点
// if (index == 0) {
// Node delnode = head;
// head = delnode.next;
// delnode.next = null;
// this.size--;
// } else {
// Node pre = head;
// Node cur = pre.next;
// for (int i = 1; i < index; i++) {
// pre = pre.next;
// cur=cur.next;
// }
// Node delnode =cur;
// pre.next = delnode.next;
// delnode.next = null;
// this.size--;
// cur = cur.next;
//有虚拟头节点
Node dummyNode=new Node(null);
dummyNode.next=head;
Node pre=dummyNode;
Node cur=pre.next;
for (int i = 0; i < index; i++) {
pre=pre.next;
cur=cur.next;
}
Node delnode =cur;
pre.next = delnode.next;
delnode.next = null;
this.size--;
cur = cur.next;
}
在链表中也有一些方法需要让我们掌握,一下代码仅供参考:
//根据索引找对应的元素
public T get(int index){
if(index<0||index>=this.size){
return null;
}
Node cur=head;
for (int i = 0; i < index; i++) {
cur=cur.next;
}
return cur.ele;
}
//获取头节点的元素
public T getFirst(){
return get(0);
}
//获取尾结点的元素
public T getLast(){
return get(this.size-1);
}
//判断是否包含该元素
public boolean contain(T ele){
Node cur=head;
for (int i = 0; i < this.size; i++) {
if(cur.ele.compareTo(ele)==0){
return true;
}
cur=cur.next;
}
return false;
}
//将链表中的某个元素进行替换
public void set(T ele,int index) {
if(index<0||index>=this.size){
}
Node cur=head;
for (int i = 0; i < index; i++) {
cur=cur.next;
}
cur.ele=ele;
}