題目:
輸入一個鏈表,反轉鏈表後,反向打印鏈表
第一種 非遞歸——借用棧來實現逆序
/**
* 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;
}