上一篇文章讲了Linkedlist的add(),get(),toString,没有看的朋友可以去看一下:手动基本实现Linkedlist集合(一),开始后面的实现
1.添加remove(int index),移除节点方法
-
解释:就是讲一个节点从链表中删除
-
实现:改变要删除节点的前后节点指向问题
-
原链表格式
-
删除进行的操作
-
简单陈述:让它前面的next,指向它的后面;让它后面的previous,指向它的前面
-
注意点:当删除第一个,或最后一个时,注意改变first,或last
-
当删除第一个,或最后一个时,注意他们没有前一个节点,或后一个节点,指向的是null
// 因为删除 也需要遍历,将查找里的遍历与,判断索引有效都分离出来
public void remove(int index){
canIndex(index);
Node node = getNode(index);
// 前一个节点
Node up = node.previous;
// 后一个节点
Node down = node.next;
// 防止是第一个
if (up != null){
// 当是最后一个时候,这时倒数第二个变为最后一个,往后应该指向(最后一个的下一个--null)
up.next = down;
}
// 防止是最后一个
if (down != null){
// 当是第一个时候,这时第二个应该变为第一个,往前指向(第一个的上一个--null)
down.previous = up;
}
// 删除第一个,改变first
if (index == 0){
firsrt = down;
}
// 删除最后一个,改变last,同时 size减一
if (index == --size){
last = up;
}
}
2.优化前一篇的部分代码
// 索引有效性
public void canIndex(int index){
if (index <0 || index >= size){
throw new RuntimeException("索引不合法:"+index);
}
}
// 只查找
public Node getNode(int index){
Node node ;
// 遍历查找
if (index <= (size>>2)){
node = firsrt;
for (int i = 0; i < index; i++) {
node = node.next;
}
}else {
node = last;
for (int i = size-1; i > index; i--) {
node = node.previous;
}
}
return node;
}
// 根据下标找到对象
public Object get(int index){
canIndex(index);
Node node = getNode(index);
return node.element;
}
3.添加 add(int index,object obj),插入方法
- 将一个节点插入节点内部,改变两条指向,新加两条指向
- 插入节点示意图:
- 上面这是中间插入示意图,但是应该注意插入到第一个位置 的不同:
public void add(int index,Object object){
Node newnode = new Node(object); // 新元素
canIndex(index); // 索引有效
Node indexNode = getNode(index);//根据下标找出这个被挤走元素
Object element = indexNode.element;
// 不插在第一个位置
if (index != 0){
Node up = indexNode.previous;
up.next = newnode; // 1
newnode.previous = up; // 2
indexNode.previous = newnode; // 3
newnode.next = indexNode; // 4
}else {
// 插在第一个位置
newnode.next = indexNode;
indexNode.previous = newnode;
// 改变first
firsrt = newnode;
}
// 改变个数
size++;
}
- 应该用插入中间,插入第一个,插入最后一个作为检验机制
public static void main(String[] args) {
// LinkedList
Linklist04 link = new Linklist04();
link.add("ll");
link.add("kk");
link.add("hh");
link.add("gg");
link.add("ff");
// 应该用插入中间,插入第一个,插入最后一个作为检验机制
System.out.println(link);
link.add(4,"4");
System.out.println(link);
link.add(3,"3");
System.out.println(link);
link.add(0,"1");
System.out.println(link);
}
4.增加泛型,优化代码,封装部分代码,完整代码:
public class Node {
Node previous; //上一个节点
Node next; // 下一个节点
Object element; //本节点里的元素
public Node(Node previous, Node next, Object element) {
super();
this.previous = previous;
this.next = next;
this.element = element;
}
public Node(Object element) {
super();
this.element = element;
}
}
public class Linklist05<E> {
private Node firsrt; // 第一个节点
private Node last; // 最后一个节点
private int size; //元素个数
public Linklist05() {
super();
}
public void add(int index,E elenent){
Node newnode = new Node(elenent); // 新元素
canIndex(index);
Node indexNode = getNode(index);//根据下标找出这个被挤走元素
Object element = indexNode.element;
// 不插在第一个位置
if (index != 0){
Node up = indexNode.previous;
up.next = newnode;
newnode.previous = up;
indexNode.previous = newnode;
newnode.next = indexNode;
}else {
// 插在第一个位置
newnode.next = indexNode;
indexNode.previous = newnode;
// 改变first
firsrt = newnode;
}
// 改变个数
size++;
}
// 因为删除 也需要遍历,将查找里的遍历与,判断索引有效都分离出来
public void remove(int index){
canIndex(index);
Node node = getNode(index);
// 前一个节点
Node up = node.previous;
// 后一个节点
Node down = node.next;
// 防止是第一个
if (up != null){
// 当是最后一个时候,这时倒数第二个变为最后一个,往后应该指向(最后一个的下一个--null)
up.next = down;
}
// 防止是最后一个
if (down != null){
// 当是第一个时候,这时第二个应该变为第一个,往前指向(第一个的上一个--null)
down.previous = up;
}
// 删除第一个,改变first
if (index == 0){
firsrt = down;
}
// 删除最后一个,改变last,并且 size减一
if (index == --size){
last = up;
}
}
// 改进查找,当在前一半里时,从first处开始遍历
// 反之,从 last处 从后往前遍历
public E get(int index){
canIndex(index);
Node node = getNode(index);
return (E)node.element;
}
// 只查找
private Node getNode(int index){
Node node ;
// 遍历查找
if (index <= (size>>2)){
node = firsrt;
for (int i = 0; i < index; i++) {
node = node.next;
}
}else {
node = last;
for (int i = size-1; i > index; i--) {
node = node.previous;
}
}
return node;
}
// 索引有效性
private void canIndex(int index){
if (index <0 || index >= size){
throw new RuntimeException("索引不合法:"+index);
}
}
// 现在不考虑链表循环
public void add(E element) {
Node node = new Node(element);
// 第一次添加元素
if (null == firsrt) {
firsrt = node;
last = firsrt;
}else {
// 将新节点 上一个指向 之前的last
node.previous = last;
// last的下一个指向新对象
last.next = node;
// 改变 last
last = node;
}
size++;
}
// 重写toString
@Override
public String toString() {
StringBuffer sb = new StringBuffer("[");
Node temp = firsrt;
while (temp.next != null) {
sb.append(temp.element+",");
temp = temp.next;
}
sb.append(temp.element+"]");
return sb.toString();
}
}
总结:
- 实现linkedlist集合,是根据双向链表实现,实现步骤:
- 节点类
- 集合的构造方法
- add(E element), 添加元素方法
- toString(), 打印集合方法
- get(int index), 获取元素方法
- remove(int index),移除元素
- add(int index,E elenent), 插入元素方法
- 对于 添加元素,注意: 头节点与尾节点的变化,size++
- 对于 移除元素,注意: 头节点与尾节点的变化,size–
- 对于 与位置相关的方法,第一步应该判断索引位置是否合法