dummyHead | 有了虚拟头结点,所有的位置都有前驱。 |
怎么头插? | 当前链表有节点时:让当前的对象指向要插入数的结点,然后dummyHead指向当前对象就行了。 node.next=dummyHead.next; dummyHead.next=node; 当前链表没结点时: node.next=dummyHead.next; dummyHead.next=node; 为什么一样的代码。 |
为什么一样的代码? | 因为虚拟头结点的存在大家都有前驱,因为当前链表没节点时:node.next=null,dummyHead.next=null 都是null。 |
有虚拟头结点后,所有结点都是该结点的“后继”,结点,无论当前是否存在有效元素,插入步骤一致,省去了判断头。 |
/**
* 头插
*/
public class LinkedListWithHead {
private int size;
private Node dummyHead=new Node();
public void addFirst(int val){
Node node=new Node();
node.val=val;
node.next=dummyHead.next;
dummyHead.next=node;
// Node node=new Node(val,dummyHead.next);
// dummyHead.next=node;
// dummyHead.next=new Node(val,dummyHead.next);
size++;
}
关于任意位置的插入代码: 找前驱走index步
在索引为Index 的位置插入新节点valueadd(2,20)在索引为2的地方插入200 prev指针是从dummyHead开始走 走index步走到待插入位置的前驱结点 package seqlist; /** * 初始化定义dummyHead */ public class LinkedListWithHead { private int size; private Node dummyHead=new Node(); public class Node { int val; Node next; // public Node(int val, Node next) { // // } }
//-------------插入部分---------------> /** * 头插 */ public void addFirst(int val){ Node node=new Node(); node.val=val; node.next=dummyHead.next; dummyHead.next=node; // Node node=new Node(val,dummyHead.next); // dummyHead.next=node; // dummyHead.next=new Node(val,dummyHead.next); size++; } /** * 在索引为Index 的位置插入新节点value * @param index * @param val */ public void add(int index,int val){ if (index<0 || index >size){ System.err.println(" add index illegal!"); return; } Node prev=dummyHead; //prev 走index 步找到前驱,但是i会自己++ for (int i = 0; i < index; i++) { prev=prev.next; } //此时prev到达指定位置 /** * 写法1 */ Node node=new Node(); node.val=val; node.next=prev.next; prev.next=node; size++; /** * 写法2 */ // //node 的值是val 后继结点就是prev.next,说的后继就是被插队的人 // Node node=new Node(val,prev.next); // //然后让前驱指向node: // prev.next=node; // size++; /** * 写法3 其实就是匿名写法,让写法2合起来 */ // prev.next=new Node(val,prev.next); // size++; } public String toString(){ String ret=""; for (Node x=dummyHead.next; x!=null; x=x.next) { ret+=x.val; ret+="->"; } ret+="null"; return ret; }
package seqlist; /** * 带头单链表的测试类 */ public class LinkedListWithHeadTest { public static void main(String[] args) { //类的产生对象为LinkedListWithHead LinkedListWithHead linkedListWithHead=new LinkedListWithHead(); linkedListWithHead.addFirst(3); linkedListWithHead.addFirst(1); linkedListWithHead.addFirst(5); System.out.println(linkedListWithHead); linkedListWithHead.add(1,2); linkedListWithHead.add(0,4); System.out.println(linkedListWithHead); } }
5->1->3->null
4->5->2->1->3->null
有虚拟头的删除方法 |
找前驱走index步
//------------------删除部分-----------> /** * 删除单链表中索引为index位置的结点,返回删除的结点值 * @param index * @return */ public int remove(int index){ //1.索引的合法性 if(rangCheck(index)){ Node prev=dummyHead; //走Index步--->找到前驱 for (int i = 0; i < index; i++) { prev=prev.next; } int oldValue=prev.next.val; //删除开始---->定义cur来存储删除结点地址 Node cur=prev.next; prev.next=cur.next; cur.next=null; size--; return oldValue; } System.err.println("index illegal!"); return -1; } private boolean rangCheck(int index) { if (index<0||index >=size){ return false; } return true; }
package seqlist; /** * 带头单链表的测试类 */ public class LinkedListWithHeadTest { public static void main(String[] args) { //类的产生对象为LinkedListWithHead LinkedListWithHead linkedListWithHead=new LinkedListWithHead(); linkedListWithHead.addFirst(3); linkedListWithHead.addFirst(1); linkedListWithHead.addFirst(5); linkedListWithHead.addFirst(7); linkedListWithHead.addFirst(6); linkedListWithHead.addFirst(8); System.out.println(linkedListWithHead); linkedListWithHead.remove(2); linkedListWithHead.remove(4); linkedListWithHead.remove(4); System.out.println(linkedListWithHead); } }
index illegal!
8->6->7->5->1->3->null
8->6->5->1->null
全删(有虚拟头) |
/** * 删除所有值为val的结点 * @param val */ public void removeAllValue(int val){ Node prev =dummyHead; while (prev.next !=null){ if (prev.next.val==val){ //找到了可以删除 /** * 写法1 */ // Node x=prev.next; // prev.next=x.next; // x.next=null; /** * 写法2 */ prev.next=prev.next.next; //一句话就删掉了,再加上prev.next.next=null就会异常; // 错: prev.next.next=null; size--; }else { //prev移动一定要放在else里 //因为如果有多个val要都删完才能走prev prev = prev.next; } } }
package seqlist; /** * 带头单链表的测试类 */ public class LinkedListWithHeadTest { public static void main(String[] args) { //类的产生对象为LinkedListWithHead LinkedListWithHead linkedListWithHead=new LinkedListWithHead(); linkedListWithHead.addFirst(1); linkedListWithHead.addFirst(1); linkedListWithHead.addFirst(1); linkedListWithHead.addFirst(1); linkedListWithHead.addFirst(1); linkedListWithHead.addFirst(1); linkedListWithHead.addFirst(1); System.out.println(linkedListWithHead); System.out.println("------删除1----------"); linkedListWithHead.removeAllValue(1); System.out.println(linkedListWithHead); } }
输出
1->1->1->1->1->1->1->null
------删除1----------
null
all代码 |
package seqlist;
/**
* 初始化定义dummyHead
*/
public class LinkedListWithHead {
private int size;
private Node dummyHead=new Node();
public class Node {
int val;
Node next;}
//-------------插入部分--------------->
/**
* 头插
*/
public void addFirst(int val){
Node node=new Node();
node.val=val;
node.next=dummyHead.next;
dummyHead.next=node;
// Node node=new Node(val,dummyHead.next);
// dummyHead.next=node;
// dummyHead.next=new Node(val,dummyHead.next);
size++;
}
/**
* 在索引为Index 的位置插入新节点value
* @param index
* @param val
*/
public void add(int index,int val){
if (index<0 || index >size){
System.err.println(" add index illegal!");
return;
}
Node prev=dummyHead;
//prev 走index 步找到前驱,但是i会自己++
for (int i = 0; i < index; i++) {
prev=prev.next;
}
//此时prev到达指定位置
/**
* 写法1
*/
Node node=new Node();
node.val=val;
node.next=prev.next;
prev.next=node;
size++;
/**
* 写法2
*/
// //node 的值是val 后继结点就是prev.next,说的后继就是被插队的人
// Node node=new Node(val,prev.next);
// //然后让前驱指向node:
// prev.next=node;
// size++;
/**
* 写法3 其实就是匿名写法,让写法2合起来
*/
// prev.next=new Node(val,prev.next);
// size++;
}
//--------------------------------
public String toString(){
String ret="";
for (Node x=dummyHead.next; x!=null; x=x.next) {
ret+=x.val;
ret+="->";
}
ret+="null";
return ret;
}
//------------------删除部分----------->
/**
* 删除单链表中索引为index位置的结点,返回删除的结点值
* @param index
* @return
*/
public int remove(int index){
//1.索引的合法性
if(rangCheck(index)){
Node prev=dummyHead;
//走Index步--->找到前驱
for (int i = 0; i < index; i++) {
prev=prev.next;
}
int oldValue=prev.next.val;
//删除开始---->定义cur来存储删除结点地址
Node cur=prev.next;
prev.next=cur.next;
cur.next=null;
size--;
return oldValue;
}
System.err.println("index illegal!");
return -1;
}
private boolean rangCheck(int index) {
if (index<0||index >=size){
return false;
}
return true;
}
/**
* 删除所有值为val的结点
* @param val
*/
public void removeAllValue(int val){
Node prev =dummyHead;
while (prev.next !=null){
if (prev.next.val==val){
//找到了可以删除
/**
* 写法1
*/
// Node x=prev.next;
// prev.next=x.next;
// x.next=null;
/**
* 写法2
*/
prev.next=prev.next.next;
//一句话就删掉了,再加上prev.next.next=null就会异常;
// 错: prev.next.next=null;
size--;
}else {
//prev移动一定要放在else里
//因为如果有多个val要都删完才能走prev
prev = prev.next;
}
}
}
}