java 链表结点的删除的两种方法

题目:给定一个头指针和一个结点指针,定义一个函数在O(1)时间删除该结点。链表的定义如下:

class LNode { // 单链表的存储结构
	int value;
	LNode next;

	public LNode() {
	}

	public LNode(int value) {
		this.value = value;
		this.next = null;
	}

	public LNode(int value, LNode next) {
		this.value = value;
		this.next = next;
	}
}
删除结点的两种方法分析:

方法1:在删除结点i之前,先从链表的表头结点开始遍历到i之前的一个结点h,把h的next指向i的下一个结点j,再删除i结点。这个时间复杂度为O(n),显然不满足题目的要求。

方法2:把j结点的内容复盖给i结点,接下来再把结点i的next指向j的下一个结点之后删除结点j。这个不用遍历链表上结点i之前的结点,只有当i结点是尾结点的时候才需要遍历,整体的时间复杂度为O(1),显然是满足要求的。

对于链表的从尾到头遍历,上节已经讲了。

下面为完整代码:

package LinkList;

import java.util.Stack;

public class DeleteNode {
	public LNode head = new LNode();// 创建空的头节点

	public void insertHead(int value) { // 插入节点,从头开始
		LNode link = new LNode(value); // 创建一个带value值的节点
		link.next = head.next;
		head.next = link;
	}

	// 两种删除链表结点的方法
	public void deleteNode0(LNode pToBeDelete) {// 在删除结点pToBeDelete之前,先从链表的头结点开始遍历到其之前的结点Before
		if (head == null || pToBeDelete == null)
			return;
		LNode beforeDelete = head;
		while (beforeDelete.next.value != pToBeDelete.value) {// 找到要删除的结点之前的那个结点
			beforeDelete = beforeDelete.next;

		}
		if (pToBeDelete.next == null)
			beforeDelete.next = null;
		else
			beforeDelete.next = pToBeDelete.next; // 将pToBeDelete前面的结点beforeDelete直接指向pToBeDelete后面的结点
	}

	public void deleteNode1(LNode pToBeDelete) {// 第二种方法

		if (head == null || pToBeDelete == null)
			return;
		if (pToBeDelete.next != null) { // 如果pToBeDelete后面的结点不为空
			LNode afterNode = pToBeDelete.next;// 将afterNode指向pToBeDelete的下一个结点
			pToBeDelete.value = afterNode.value;// 将afterNode的值赋给pToBeDelete
			pToBeDelete.next = afterNode.next;// 删除afterNode结点

		} else if (head.next == pToBeDelete && pToBeDelete.next == null) {// 只有一个结点pToBeDelete
			head.next = null;
			pToBeDelete = null;

		} else if (pToBeDelete.next == null) {// pToBeDelete是尾结点时,需要从头开始遍历,找到尾结点之前的那个结点,将其下一个指向的结点赋为NULL

			LNode beforeDelete = head;
			while (beforeDelete.next != pToBeDelete) {// 找到要删除的结点之前的那个结点
				beforeDelete = beforeDelete.next;
			}
			beforeDelete.next = null;
		}

	}

	// 从尾到头打印链表方法一:用递归
	public void printNode1(LNode node) {
		if (node != null) {
			printNode1(node.next);
			System.out.print(node.value + " ");

		}
	}

	// 从尾到头打印链表方法二:用栈
	public void printNode2(LNode node) {
		Stack<LNode> stack = new Stack<LNode>();
		// node=node.next;
		while (node != null) {
			stack.push(node);
			node = node.next;

		}
		while (!stack.isEmpty()) {
			LNode pnode = stack.pop();
			System.out.print(pnode.value + " ");
		}
	}

	public static void main(String[] args) {
		DeleteNode deleteNode = new DeleteNode();
		for (int i = 0; i < 10; i++) {
			deleteNode.insertHead(i);
		}
		LNode node = deleteNode.head.next;
		deleteNode.printNode1(node);// 从尾到头打印链表,方法一
		System.out.println();
		deleteNode.printNode2(node);// 从尾到头打印链表,方法二
		System.out.println();
		LNode pToBeDelete = deleteNode.head.next.next.next;// 要删除的结点
		System.out.println(pToBeDelete.value);
		deleteNode.deleteNode0(pToBeDelete);// 用第一种方法删除
		deleteNode.printNode1(node);
		System.out.println();
		System.out.println(pToBeDelete.value);
		deleteNode.deleteNode1(pToBeDelete);// 用第二种方法删除
		deleteNode.printNode2(node);
	}

}
运行结果为:

0 1 2 3 4 5 6 7 8 9 
0 1 2 3 4 5 6 7 8 9 
7
0 1 2 3 4 5 6 8 9 
7
0 1 2 3 4 5 6 8 9 


因为

LNode pToBeDelete = deleteNode.head.next.next.next;// 要删除的结点

的固定值为7,所以第二次在删除时,发现没有这个几点。

将main代码改为:

public static void main(String[] args) {
		DeleteNode deleteNode = new DeleteNode();
		for (int i = 0; i < 10; i++) {
			deleteNode.insertHead(i);
		}
		LNode node = deleteNode.head.next;
		deleteNode.printNode1(node);// 从尾到头打印链表,方法一
		System.out.println();
		deleteNode.printNode2(node);// 从尾到头打印链表,方法二
		System.out.println();
		LNode pToBeDelete = node.next.next;// 要删除的结点
		System.out.println(pToBeDelete.value);
		deleteNode.deleteNode0(pToBeDelete);// 用第一种方法删除
		deleteNode.printNode1(node);
		System.out.println();
		<span style="color:#ff6666;">LNode pToBeDelete1 = node.next.next;// 要删除的结点
		System.out.println(pToBeDelete1.value);</span>
		deleteNode.deleteNode1(pToBeDelete1);// 用第二种方法删除
		deleteNode.printNode2(node);
	}
运行结果为:

0 1 2 3 4 5 6 7 8 9 
0 1 2 3 4 5 6 7 8 9 
7
0 1 2 3 4 5 6 8 9 
6
0 1 2 3 4 5 8 9



  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值