题目:
输入一个链表,反转链表后,反向打印链表
第一种 非递归——借用栈来实现逆序
/**
* public class ListNode {
* int val;
* ListNode next = null;
*
* ListNode(int val) {
* this.val = val;
* }
* }
*/
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Stack;
public class Solution {
public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
ArrayList<Integer> ArrayList1 = new ArrayList<Integer>();
ListNode list;
list = listNode;
Stack<Integer> sta = new Stack<Integer>();
while(listNode!=null){
sta.add(listNode.val);
listNode = listNode.next;
}
while(!sta.isEmpty()){
ArrayList1.add(sta.pop());
}
return ArrayList1;
}
}
第二种 非递归
这种做法是三指针来实现的,比较简单,且易于理解,但如果不够熟练还是会想不清楚的。
先贴代码,然后做个图形助于理解
有以下两种方式,但实际效果一样,各有特点,看各位自己选择哪种了
第一种
public class Solution {
public ListNode ReverseList(ListNode head) {
ListNode pre = null;
ListNode cur = head;
ListNode tmp = null;
while(cur!=null){
tmp = cur.next;//先更新后指针
cur.next = pre;//反向
pre = cur; //更新前指针
cur = tmp; //更新当前指针
}
return pre;
}
}
第二种:
//逆置——非递归
LinkList non_recursive_ListReverse(LinkList L) {
LinkList pre,cur,rear;
pre = L; //带头结点
cur = pre->next;
rear = cur->next;
pre->next = NULL; //pre转向后是最后结点
while (rear) {
cur->next = pre; //换向
pre = cur; //更新pre
cur = rear; //更新cur
rear = rear->next; //更新rear
}
cur->next = pre; //换向
return cur;
}
第二种的图解:
第三种 递归
用递归来做的其实都不太好理解,我也搞了好久才明白
LinkList recursive_ListReverse(LinkList head) {
LinkList cur, rear;
if (head->next == NULL) //递归出口
return head;
LinkList LL = recursive_ListReverse(head->next);//待返回的头结点
cur = head; //更新
rear = head->next; //更新
rear->next = cur; //换向
cur->next = NULL;
return LL;
}
对于链表问题,就得自己写一遍,图画一遍,这样才会有印象,而且要时常过一遍,因为其中有一些细节方面,我们往往会搞不明白,链表主要的问题就是空指针异常,也就是说边界情况没有处理好。最好是做题时时画一幅图,来帮助自己理解
下面给出比较全的代码:可运行于Visual Studio
#include<iostream>
#include<malloc.h>
#include<stdio.h>
using namespace std;
#define ElemType int
typedef struct LNode {
ElemType data;
struct LNode* next;
}LNode,*LinkList;
LinkList L = (LinkList)malloc(sizeof(LNode));//创建了头结点
//LinkList L;//只是定义了一个空指针
//初始化
void InitList(LinkList L) {
L->data = -1;
LinkList q = L;
int val;
cout << "请输入数值空格隔开,换行结束" << endl;
while (cin >> val) {
LinkList p = (LinkList)malloc(sizeof(LNode));
p->data = val;
p->next = NULL;
q->next = p;
q = p;
if(getchar() == '\n')
break;
}
}
//逆置——非递归
LinkList non_recursive_ListReverse(LinkList L) {
LinkList pre,cur,rear;
pre = L; //带头结点
cur = pre->next;
rear = cur->next;
pre->next = NULL; //pre转向后是最后结点
while (rear) {
cur->next = pre; //换向
pre = cur; //更新pre
cur = rear; //更新cur
rear = rear->next; //更新rear
}
cur->next = pre; //换向
return cur;
}
//逆置——递归
/*
当有很多的next->next搞不清楚的时候,用新的指针代替会更加清晰
*/
LinkList recursive_ListReverse(LinkList head) {
LinkList cur, rear;
if (head->next == NULL) //递归出口
return head;
LinkList LL = recursive_ListReverse(head->next);//待返回的头结点
cur = head; //更新
rear = head->next; //更新
rear->next = cur; //换向
cur->next = NULL;
return LL;
}
//链表判空
int ListEmpty(LinkList L) {
LinkList p = L;
if (!p->next)
return 1;
return 0;
}
//遍历
void ListTraverse(LinkList L) {
LinkList p = L;
while (p) {
cout << p->data << " ";
p = p->next;
}
cout << endl;
}
int main() {
InitList(L);
ListTraverse(L);
//ListTraverse(recursive_ListReverse(L->next));//递归输出
ListTraverse(non_recursive_ListReverse(L->next));//非递归输出
return 0;
}