链表——Java实现链表反转的两种方法

前提

链表是多个不一定连续的内存块(节点),通过节点保存的后置指针或前置指针串联起来的一种数据结构;
链表不支持随机访问;
下面的反转链表没有特别提示的都是带头链表(引入了哨兵的链表),用java实现,节点类如下:

/**
 * @Author Haoqi
 * @Description 链表节点
 **/
Class Node{
	int data;
	Node next;
	/**
	 * 构造哨兵节点
	 **/
	public Node() {
        this.data = -1;
        this.next = null;
    }
	//其他构造方法
	//...
}

两种实现

原地反转

通过指针的变化,在链表自身进行反转,不会产生另外一个新链表;

public static Node reverseLinkList(Node head){
	if(head.next == null){
		return head;
	}
	Node prev = head.next;
	Node pcur = prev.next;
	while(pcur != null){
		prev.next = pcur.next;
		pcur.next = head.next;
		head.next = pcur;
		pcur = prev.next;
	}
	return head;
}
  • head节点是哨兵节点,不存数据只是,只是为了简化代码;
  • 第一个判断看链表是否为空链表,即除了哨兵没有其他数据节点;
  • 实现需要两个指针,一个前置指针 prev ,一个移动指针pcur;
  • 循环结束条件是移动指针为null;
  • 注意指针操作顺序防止指针丢失,这里可以逐步画图演示,辅助理解
  • pcur指针指向的是下次循环结束后的第一个数据节点 head.next = pcur;
  • 最后pcur向后移动,但每次循环开始结束prev一直是pcur的前置节点;
  • 时间复杂度O(n)

头插法反转

顾名思义,遍历旧链表,反复向新链表的第一个节点位置插入,产生的新链表就是旧链表的反转;

public static Node reverseLinkList(Node head){
	if(head.next == null){
		return head;
	}
	Node newHead = new Node();
	Node pcur = head.next;
    Node curNextTmp = null;
	while(pcur != null){
		curNextTmp = pcur.next;
		pcur.next = newHead.next;
		newHead.next = pcur;
		pcur = curNextTmp;
	}
	return newHead;
}
  • head节点是哨兵节点,不存数据只是,只是为了简化代码;
  • 第一个判断看链表是否为空链表,即除了哨兵没有其他数据节点;
  • 实现需要新建一个带头空链表newHead,一个移动指针pcur和一个缓存curNextTmp;
  • 循环结束条件是移动指针为null;
  • 每次循环,先将pcur的后续节点缓存起来,然后再向新链表第一个数据节点处插入pcur(头插),最后将pcur移到缓存的后续节点;
  • 时间复杂度为O(n)

熄灯

怎么写出正确的链表?画图理解记忆,再多默写几次就行。

你可能感兴趣的:(算法和数据结构,链表,数据结构,java,算法,缓存)