剑指offer--从尾到头打印链表

题目描述

输入一个链表,按链表值从尾到头的顺序返回一个ArrayList。

     之前接触过链表的逆置所以这里上来直接用了三指针方法。

struct ListNode {

       int val;

       struct ListNode *next;

       ListNode(int x) :

             val(x), next(NULL) {

       }

 };



class Solution {

public:

vector printListFromTailToHead(ListNode* head) {

vector array;

if (head == NULL)

return array;

if (head->next == NULL)

{

array.push_back(head->val);

return array;

}

ListNode *n1=head;

ListNode *n2 = n1->next;

ListNode *n3 = n2->next;

n1->next = NULL;

while (n2 != NULL)

{

n2->next = n1;

n1 = n2;

n2 = n3;

if (n3 == NULL)

break;

n3 = n3->next;

}



while (n1)

{

array.push_back(n1->val);

n1 = n1->next;

}

return array;

}

};

    定义了三个指针其实就是在不断的操作指针指向他的前一个数据,

剑指offer--从尾到头打印链表_第1张图片

    最初让n1指向了空,然后让n2指向了n1,就是在不断的执行这个过程,定义三个指针的原因是因为,我们操作完n2指向n1之后n2的next就变成了n1,这时候就不能找到链表的下一个位置了,必须让n3来记录这个位置,n3就是在做这个事情。

   还有就是注意

while (n2 != NULL)

{

n2->next = n1;

n1 = n2;

n2 = n3;

if (n3 == NULL)

break;

n3 = n3->next;

}

   While循环的判断条件,这里我写的是n2不等于空,这里就要注意当n2是结点最后一个数据的时候,n3已经是空了,但是这时候是依然会进入while循环,因为你要让n2当前指向的这个最后一个数据节点指向倒数第二个数据,之后让n2等于n3,但是n3如果在等于n3的next就会有问题,因为n3已经是空了,还去访问它的next就导致程序崩溃,所以这里要判断一下。

   写完这个程序之后感觉很简单,但是仔细一想,这样我就把传进来的参数链表给修改了,虽然牛客网通过了测试,但是仔细一想这里是从尾到头打印,而不是说让你的链表逆置过来,所以我们尽量不去修改传进来的参数,这里就自然的想到了栈。栈本来就是一个先进后出的数据结构正好符合我们从头到尾遍历链表却从尾到头来打印。

class Solution {

public:

vector printListFromTailToHead(ListNode* head) {

vector array;

if (head == NULL)

return array;

if (head->next == NULL)

{

array.push_back(head->val);

return array;

}

stack s;

ListNode *now = head;

while (now)

{

s.push(now->val);

now = now->next;

}

while (!s.empty())

{

array.push_back(s.top());

s.pop();

}

return array;

}

};

   也成功通过了牛客的测试,我认为运用栈的这个更好一些,没有去修改传进来的参数。

下边是分享的今天的选择题: 

(1)静态链表既有顺序存储的优点,又有动态链表的优点。所以,它存取表中第i个元素的时间与i无关。
(2)静态链表中能容纳的元素个数的最大数在表定义时就确定了,以后不能增加.
(3)静态链表与动态链表在元素的插入、删除上类似,不需做元素的移动。
以上错误的是()

A.(1),(2)

B.(1)

C.(1),(2),(3)

D.(2)

   我选的时候认为三个都是错的,但是只有1是错的也就是说选择B。想了半天终于明白自己为什么做错了,静态链表、动态链表是什么都不知道。

   静态链表是用类似于数组方法实现的,是顺序的存储结构,在物理地址上是连续的,而且需要预先分配地址空间大小。所以静态链表的初始长度一般是固定的,在做插入和删除操作时不需要移动元素,仅需修改指针。

剑指offer--从尾到头打印链表_第2张图片

剑指offer--从尾到头打印链表_第3张图片

   这是用我们的数组去模拟链表的实现,长度是一开始就定好的。并且存取第i个元素时,需要从头遍历到i-1和元素,由第i-1个节点的cursor,才能知道第i个元素存储的位置,因此和i是相关的。插入和删除操作无需移动元素,只需要修改cursor游标的值即可,就像修改动态链表中的指针一样。

   动态链表是用内存申请函数(malloc/new)动态申请内存的,所以在链表的长度上没有限制。动态链表因为是动态申请内存的,所以每个节点的物理地址不连续,要通过指针来顺序访问

你可能感兴趣的:(个人总结,小程序)