遍历和递归实现双向链表反转
2018-02-27 10:44
417 查看
面试中经常问到双向链表的反转问题,下面参考《数据结构与算法分析》给出个
反转链表需要两个指针向前推进,同时记录第三个节点。由于我们的链表结构是带有头节点和尾节点的,所以需要特殊处理一下头尾部节点。
LinkedList实现,同时讨论双向链表的反转实现。
public class LinkedList<E> { private Node<E> head; private Node<E> foot; private int modCount; private int size; public LinkedList() { clear(); } private void clear() { head = new Node<E>(null, null, null); foot = new Node<E>(null, head, null); head.next = foot; modCount++; size = 0; } public int size() { return size; } public void add(E e) { addBefore(size(), e); } private void addBefore(int index, E e) { Node<E> node = getNode(index); Node<E> newNode = new Node<E>(e, node.prev, node); node.prev.next = newNode; node.prev = newNode; size++; modCount++; } private Node<E> getNode(int index) { return getNode(index, 0, size()); } private Node<E> getNode(int index, int lower, int upper) { Node<E> pNode; if (index < lower || index > upper) { throw new ArrayIndexOutOfBoundsException(); } if (index < size() / 2) { pNode = head.next; for (int i = 0; i < index; i++) { pNode = pNode.next; } } else { pNode = foot; for (int i = size(); i > index; i--) { pNode = pNode.prev; } } return pNode; } public void remove(int index) { remove(getNode(index)); } private void remove(Node<E> node) { node.prev.next = node.next; node.next.prev = node.prev; size--; modCount++; } public E set(int index, E e) { Node<E> node = getNode(index); E oldValue = node.element; node.element = e; return oldValue; } public E get(int index) { return getNode(index).element; } private static class Node<E> { Node<E> prev; Node<E> next; E element; public Node(E element, Node<E> prev, Node<E> next) { this.element = element; this.prev = prev; this.next = next; } } }
LinkedList中分别保存了头节点
head和尾节点
foot,现在讨论一下如何实现反转。
如何反转
图解一下反转过程,如下图:反转链表需要两个指针向前推进,同时记录第三个节点。由于我们的链表结构是带有头节点和尾节点的,所以需要特殊处理一下头尾部节点。
方法一 循环遍历法
要实现反转,我们就要反转每一个Node的
next和
prev的指向。
/** * 循环遍历实现反转 */ public void reverse1() { Node<E> cur = head.next; //第一个节点反转后next指向foot Node<E> pre = foot; while (cur != foot) { Node<E> temp = cur; //cur指针后移,记录下一个节点 cur = cur.next; //反转 temp.next = pre; pre.prev = temp; //pre指针后移 pre = temp; } pre.prev = head; head.next = pre; }
方法二 递归法
/** * 递归实现反转 */ public void reverse2() { Node<E> temp = reverse(head.next); head.next.next = foot; foot.prev = head.next; head.next = temp; temp.prev = head; } private Node<E> reverse(Node<E> cur) { if (cur == null || cur.next == foot) { return cur; } //反转后的头指针(foot的prev) Node<E> tail = reverse(cur.next); //反转,和循环遍历思想一致 cur.next.next = cur; cur.prev = cur.next; return tail; }
相关文章推荐
- 链表的反转(递归实现和非递归实现)
- 带头节点链表的反转 循环和递归 C#实现
- java实现单链表反转(遍历方式)
- 一些常用算法[数组全排列算法,单链表反转(递归实现),字符串反转,桶排序]
- 数据结构学习之链表(单向、单循环以及双向)(递归实现)
- 反转链表--递归和非递归实现
- 链表反转的递归和非递归实现方式
- 【leetcode】通过递归反转单链表 - Go语言实现
- 单链表反转(非递归java实现)
- java实现单链表反转(递归方式)
- 单链表反转的循环及递归实现
- Java 单链表的反转 以及 双向链表的实现
- 遍历一次实现单链表顺序反转
- 链表反转的实现(递归反转链表,非递归反转链表)
- 用只含一个链域的节点实现循环链表的双向遍历
- 面试 考虑链表反转的递归实现
- 递归和非递归实现链表反转
- java实现二叉树的三种遍历方式,并把二叉树转为双向链表,输出二叉树
- 递归实现链表反转
- 【剑指offer】链表相关-反转链表&&递归实现16