思路:

双向链表的遍历,添加,修改,删除的操作思路:
遍历和单链表一样,只是可以向前也可以向后;
添加到链表最后:先找到双向链表的最后一个节点然后temp.next=newHeroNode,newHeroNode.pre=temp;
修改和单链表一样;
删除:可以实现自我删除某个节点,直接找到要删除的这个节点然后temp.pre.next=temp.next,temp.next.pre=temp.pre

基于单链表的例子,用双链表实现水浒英雄打印及相应操作:

结点类:

class HeroNode2 {
	int no;
	String name;
	String nickname;
	HeroNode2 next;// next默认为null,指向下一个结点
	HeroNode2 pre;// 指向前一个结点

	public HeroNode2(int no, String name, String nickname) {
		this.no = no;
		this.name = name;
		this.nickname = nickname;
	}

	@Override
	public String toString() {
		return "HeroNode [no=" + no + ", name=" + name + ", nickname=" + nickname + "]";
	}

}

遍历:

// 遍历链表
	public void list() {
		if (head.next == null) {
			System.out.println("链表为空");
			return;
		}
		HeroNode2 temp = head.next;
		while (true) {
			// 判断是否到链表最后
			if (temp == null) {
				break;
			}
			// 输出节点信息
			System.out.println(temp);
			// temp后移
			temp = temp.next;
		}
	}

添加:
(1)直接添加到链表最后:

// 添加结点到链表最后
	public void add(HeroNode2 heroNode) {
		// 头节点不能动,所以用辅助指针
		HeroNode2 temp = head;
		// 遍历链表到最后
		while (true) {
			if (temp.next == null) {
				break;
			}
			temp = temp.next;
		}
		// 连接到双向链表
		temp.next = heroNode;
		heroNode.pre = temp;
	}

(2)按照编号顺序添加:关键是找到位于添加位置的前一个结点

//添加节点方法二,关键是找到位于添加位置的前一个结点
		public void addByOrder(HeroNode2 heroNode) {
			HeroNode2 temp = head;
			boolean flag=false;//标识添加的编号是否存在,默认false
			while(true) {
				if(temp.next==null) {//已在链表最后
					break;
				}
				if(temp.next.no>heroNode.no) {//位置找到就在temp后面插入
					break;
				}
				else if(temp.next.no==heroNode.no) {
					flag=true;
					break;
				}
				temp = temp.next;
			}
			//判断flag
			if(flag) {
				System.out.printf("待插入的英雄编号%d已存在,不能插入\n",heroNode.no);
			}
			else {
				//注意编号是不是在最后面
				if(temp.next==null) {
					
					temp.next = heroNode;
					heroNode.pre = temp;
				}
				//连接双链表
				else {
					heroNode.next=temp.next;
					heroNode.pre = temp.next.pre;
					temp.next.pre = heroNode;
					temp.next=heroNode;
				}
			}
		}

修改:

// 修改节点信息,根据no编号来修改,即no编号不能改
	public void update(HeroNode2 newHeroNode) {
		// 判断是否为空
		if (head.next == null) {
			System.out.println("链表为空");
			return;
		}
		// 辅助指针
		HeroNode2 temp = head.next;
		boolean flag = false;// 表示是否找到该节点
		while (true) {
			if (temp == null) {
				break;
			}
			if (temp.no == newHeroNode.no) {
				flag = true;
				break;
			}
			temp = temp.next;
		}
		if (flag) {
			temp.name = newHeroNode.name;
			temp.nickname = newHeroNode.nickname;

		} else {
			System.out.printf("没有找到编号%d的结点,不能修改\n", newHeroNode.no);

		}
	}

删除:

// 删除节点,找到待删除结点
	public void del(int no) {
		HeroNode2 temp = head.next;
		boolean flag = false;
		while (true) {
			if (temp == null) {// 已经到链表的最后
				break;
			}
			if (temp.no == no) {
				// 找到待删除结点的前一个结点
				flag = true;
				break;
			}
			temp = temp.next;
		}
		if (flag) {
			temp.pre.next = temp.next;
			//删除最后一个节点时防止空指针
			if(temp.next!=null) {
				temp.next.pre = temp.pre;
			}
		} else {
			System.out.printf("要删除的%d结点不存在\n", no);
		}
	}

完整代码(含测试):

public class DoubleLinkedListDemo {

	public static void main(String[] args) {
		//测试
		HeroNode2 hero1 = new HeroNode2(1,"宋江","及时雨");
		HeroNode2 hero2 = new HeroNode2(2,"卢俊义","玉麒麟");
		HeroNode2 hero3 = new HeroNode2(3,"吴用","智多星");
		HeroNode2 hero4 = new HeroNode2(4,"林冲","豹子头");
		HeroNode2 hero5 = new HeroNode2(7,"林","豹子");
		//添加
		DoubleLinkedList doublelinkedlist = new DoubleLinkedList();
		
		//法一
		/*doublelinkedlist.add(hero1);
		doublelinkedlist.add(hero2);
		doublelinkedlist.add(hero3);
		doublelinkedlist.add(hero4);*/
		//法二
		doublelinkedlist.addByOrder(hero1);
		doublelinkedlist.addByOrder(hero5);
		doublelinkedlist.addByOrder(hero3);
		doublelinkedlist.addByOrder(hero2);
		doublelinkedlist.addByOrder(hero4);
		//遍历
		doublelinkedlist.list();
		
		//修改
		HeroNode2 newHeroNode = new HeroNode2(4, "公孙胜", "入云龙");
		doublelinkedlist.update(newHeroNode);
		
		doublelinkedlist.list();
		
		//删除
		System.out.println("删除后:");
		doublelinkedlist.del(3);
		doublelinkedlist.list();
		

	}

}

//创建双向链表类
class DoubleLinkedList{
	// 先初始化一个头结点,头结点不动且不存放具体数据
	private HeroNode2 head = new HeroNode2(0, "", "");

	// 添加结点到链表最后
	public void add(HeroNode2 heroNode) {
		// 头节点不能动,所以用辅助指针
		HeroNode2 temp = head;
		// 遍历链表到最后
		while (true) {
			if (temp.next == null) {
				break;
			}
			temp = temp.next;
		}
		// 连接到双向链表
		temp.next = heroNode;
		heroNode.pre = temp;
	}

	//添加节点方法二,关键是找到位于添加位置的前一个结点
		public void addByOrder(HeroNode2 heroNode) {
			HeroNode2 temp = head;
			boolean flag=false;//标识添加的编号是否存在,默认false
			while(true) {
				if(temp.next==null) {//已在链表最后
					break;
				}
				if(temp.next.no>heroNode.no) {//位置找到就在temp后面插入
					break;
				}
				else if(temp.next.no==heroNode.no) {
					flag=true;
					break;
				}
				temp = temp.next;
			}
			//判断flag
			if(flag) {
				System.out.printf("待插入的英雄编号%d已存在,不能插入\n",heroNode.no);
			}
			else {
				//注意编号是不是在最后面
				if(temp.next==null) {
					
					temp.next = heroNode;
					heroNode.pre = temp;
				}
				//连接双链表
				else {
					heroNode.next=temp.next;
					heroNode.pre = temp.next.pre;
					temp.next.pre = heroNode;
					temp.next=heroNode;
				}
			}
		}
		
	// 修改节点信息,根据no编号来修改,即no编号不能改
	public void update(HeroNode2 newHeroNode) {
		// 判断是否为空
		if (head.next == null) {
			System.out.println("链表为空");
			return;
		}
		// 辅助指针
		HeroNode2 temp = head.next;
		boolean flag = false;// 表示是否找到该节点
		while (true) {
			if (temp == null) {
				break;
			}
			if (temp.no == newHeroNode.no) {
				flag = true;
				break;
			}
			temp = temp.next;
		}
		if (flag) {
			temp.name = newHeroNode.name;
			temp.nickname = newHeroNode.nickname;

		} else {
			System.out.printf("没有找到编号%d的结点,不能修改\n", newHeroNode.no);

		}
	}
	
	// 删除节点,找到待删除结点
	public void del(int no) {
		HeroNode2 temp = head.next;
		boolean flag = false;
		while (true) {
			if (temp == null) {// 已经到链表的最后
				break;
			}
			if (temp.no == no) {
				// 找到待删除结点的前一个结点
				flag = true;
				break;
			}
			temp = temp.next;
		}
		if (flag) {
			temp.pre.next = temp.next;
			//删除最后一个节点时防止空指针
			if(temp.next!=null) {
				temp.next.pre = temp.pre;
			}
		} else {
			System.out.printf("要删除的%d结点不存在\n", no);
		}
	}
	
	// 遍历链表
	public void list() {
		if (head.next == null) {
			System.out.println("链表为空");
			return;
		}
		HeroNode2 temp = head.next;
		while (true) {
			// 判断是否到链表最后
			if (temp == null) {
				break;
			}
			// 输出节点信息
			System.out.println(temp);
			// temp后移
			temp = temp.next;
		}
	}
}

class HeroNode2 {
	int no;
	String name;
	String nickname;
	HeroNode2 next;// next默认为null,指向下一个结点
	HeroNode2 pre;// 指向前一个结点

	public HeroNode2(int no, String name, String nickname) {
		this.no = no;
		this.name = name;
		this.nickname = nickname;
	}

	@Override
	public String toString() {
		return "HeroNode [no=" + no + ", name=" + name + ", nickname=" + nickname + "]";
	}

}