链表反转问题重新总结 20.1.27

题目:

输入一个链表,反转链表后,反向打印链表

第一种  非递归——借用栈来实现逆序

/**
*    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;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值