链表---双向链表之节点的增删改查

双向链表:
双向链表是在单向链表的基础上,在每个节点上加了一个向前的指针。这俩个指针分别指向直接后继和直接前驱,使得双向链表更加方便。

Java代码实现:
(代码中有注释)

public class DoubleLinkedlistDemo {

public static void main(String[] args) {
	// TODO Auto-generated method stub

	//双向链表的测试代码
	//先创建四个节点
	HeroNode2 hero1 = new HeroNode2(1,"诸葛亮","小猪");
	HeroNode2 hero2 = new HeroNode2(2,"黄月英","小黄");
	HeroNode2 hero3 = new HeroNode2(3,"吕布","小吕");
	HeroNode2 hero4 = new HeroNode2(4,"貂蝉","小貂");
	
	//创建一个双向链表
	DoubleLinkedlist doubleLinkedlist = new DoubleLinkedlist();
	doubleLinkedlist.add(hero1);
	doubleLinkedlist.add(hero2);
	doubleLinkedlist.add(hero3);
	doubleLinkedlist.add(hero4);
	
	//打印双向链表
	System.out.println("打印双向链表----");
	doubleLinkedlist.list();
	
	//修改节点测试
	//先创建一个新的节点
	HeroNode2 newHeroNode = new HeroNode2(4, "董卓", "小董");
	doubleLinkedlist.update(newHeroNode);
	System.out.println("修改后的双向链表情况-----");
	doubleLinkedlist.list();
	
	//测试删除
	doubleLinkedlist.del(3);
	System.out.println("删除一个节点后的双向链表的情况----");
	doubleLinkedlist.list();
	
	//测试按编号顺序添加节点
	//先创建一个新节点
	HeroNode2 nHeroNode = new HeroNode2(3, "吕布", "小吕");
	//将新节点按编号顺序添加到链表中
	doubleLinkedlist.addByOrder(nHeroNode);
	System.out.println("按编号顺序添加节点后的双向链表的情况----");
	doubleLinkedlist.list();
	}
}


//创建一个双向链表
class DoubleLinkedlist{
	//初始化
	private HeroNode2 head = new HeroNode2(0,"","");
	
//返回头结点
public HeroNode2 getHead() {
	return head;
}

//遍历双向链表
//显示链表[遍历]
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.找到当前链表的最后节点 
 * 2.将最后这个节点的next指向新的节点
 * 3.将新节点的pre指向前一个节点
 */
public void add(HeroNode2 heroNode) {
	// 因为head节点不能动,所以需要一个辅助遍历temp
	HeroNode2 temp = head;
	// 遍历链表,找到最后
	while (true) {
		// 找到链表的最后
		if (temp.next == null) {
			break;
		}
		// 如果没有找到最后,则将temp后移
		temp = temp.next;
	}
	// 当退出while循环时,temp就指向了链表的最后
	temp.next = heroNode;
	heroNode.pre = temp;
}

// 通过节点的编号顺序来插入节点,将节点插入到指定位置(单链表是一个已排好序的链表)
// 如果这个节点的编号已经存在,则插入失败,并提示失败信息

public void addByOrder(HeroNode2 heroNode) {
	// 因为头结点不能动,仍然需要一个辅助指针(变量)来帮助找到添加的位置
	// 双向链表,所以找到需要插入的位置
	HeroNode2 temp = head.next;
	boolean flag = false;// 标志添加的编号是否存在,默认为false
	while (true) {
		if (temp == null) {
			// 说明temp已经在链表的最后
			break;
		}
		if (temp.no > heroNode.no) {
			// 说明位置找到,就在temp前插入
			break;
		} else if (temp.no == heroNode.no) {
			// 说明想要添加的heroNode的编号已经存在
			flag = true;// 说明编号存在
			break;
		}
		temp = temp.next;// 后移
	}
	// 判断flag的值
	if (flag) {
		// 说明编号存在,不能添加
		System.out.printf("准备插入的节点的编号%d已经存在,不能加入\n", heroNode.no);
	} else {
		// 插入到链表中,temp前
		heroNode.next = temp.pre.next;
		temp.pre.next = heroNode;
		heroNode.pre = temp.pre;
		temp.pre = heroNode;
	}
}
	
//修改一个节点的内容
//修改的方法和修改单向链表节点的方法一样
public void update(HeroNode2 newHeroNode) {
	//判断是否为空
	if(head.next == null) {
		System.out.println("链表为空~~~");
		return;
	}
	//找到需要修改的节点,根据no编号
	//定义一个辅助变量
	HeroNode2 temp = head.next;
	boolean flag = false;//表示是否找到该节点
	while(true) {
		if(temp == null) {
			break;//已经遍历完链表
		}
		if(temp.no == newHeroNode.no) {
			//表示找到相应的节点
			flag = true;
			break;
		}
		temp = temp.next;
	}
	//根据flag判断是否找到修改的节点
	if(flag) {
		temp.name = newHeroNode.name;
		temp.nickname = newHeroNode.nickname;
	}else {
		//没有找到
		System.out.printf("没有找到编号为%d的节点,不能修改\n",newHeroNode.no);
	}
}

//删除节点
//说明:
/**
 * 对于双向链表,可以直接找到要删除的这个节点
 * 找到之后自我删除即可
 */
public void del(int no) {
	
	//判断当前链表是否为空
	if(head.next == null) {
		//当前链表为空链表
		System.out.println("链表为空,无法删除");
		return;
	}
	
	HeroNode2 temp = head.next;
	boolean flag = false;//标识是否找到待删除的节点
	while(true) {
		if(temp == null) {
			//说明到了链表的最后节点的next
			break;
		}
		if(temp.no == no) {
			//说明找到了待删除节点的前一个节点
			flag = true;
			break;
		}
		//对链表进行遍历时,节点后移
		temp = temp.next;
	}
	//判断flag
	if(flag) {
		//找到对应的节点,可以进行删除操作
		temp.pre.next = temp.next;
		//如果删除的是最后一个节点,就不需要执行这句,否则出现空指针异常
		if(temp.next != null) {
			temp.next.pre = temp.pre;
		}
	}else {
		System.out.printf("要删除的节点%d不存在!!!\n",no);
	}
}
}

//定义一个HeroNode2,每个HeroNode对象就是一个节点
class HeroNode2{
	public int no;
	public String name;
	public String nickname;
	public HeroNode2 next;//指向下个节点,默认为null
	public HeroNode2 pre;//指向前一个节点,默认为null
	//构造器
	public HeroNode2(int no,String name,String nickname) {
		this.no = no;
		this.name = name;
		this.nickname = nickname;
	}
	//重新toString
	@Override
	public String toString() {
		return "HeroNode [no = "+no+",name = "+name+",nick = "+nickname+"]";
	}
}

你可能感兴趣的:(Java数据结构)