1、题目描述:
输入一个链表的头节点,从尾到头反过来打印每个节点的值,链表定义如下:
struct ListNode
{
int m_nKey;
ListNode* m_pNext;
}
2、测试用例
- 功能测试(输入的链表有多个节点;输入的链表只有一个节点)
- 特殊输入测试(输入的链表头结点指针为NULL)
3、解答思路
思路一:对链表进行遍历,然后将链表的数据都依次保存在数组中,接着只需要将数组中的数据按照数组下标进行逆序输出即可。相当于两次遍历。
复杂度分析:时间复杂度0(n),空间复杂度0(n)
代码如下:
void Linked_List_Reversal(ListNode* head)
{
int res[100];
int i = 0;
while(head != NULL)
{
res[i++] = head->data;
head = head->next;
}
while(i != 0)
{
printf("%d", res[i--]);
}
printf("\n");
}
思路二:遍历链表是从头到尾,而题目要求的输出是从尾到头。也就是说,第一个遍历的节点是最后一个输出,而最后一个遍历到的节点第一个输出。实际上就是后进先出,也就类似于栈的操作,所以我们可以考虑用栈来实现。当遍历完整个链表后,再从栈顶开始逐个输出节点的值。
复杂度分析:
void PrintListReversingly_Iteratively(ListNode* pHead)
{
std::stack<ListNode*> nodes;
ListNode* pNode = pHead;
while(pNode != nullptr)
{
nodes.push(pNode);
pNode = pNode->m_pNext;
}
while(!nodes.empty())
{
pNode = nodes.top();
printf("%d\t", pNode->m_nValue);
nodes.pop();
}
}
//注意,这里C语言里面的话没有stack,也没有push、pop等操作,只能自己写相应的函数进行定义,过程较复杂,所以是不太推荐该方式的,下面补充下栈定义等函数
//栈定义
typedef struct Stack
{
int* arr; //存放栈的首地址
int len; //栈的长度
int top; //栈顶的下标
}Stack;
//创建栈
Stack* create_stack(int len)
{
Stack* stack = malloc(sizeof(Stack));
stack->arr = malloc(siezof(int)*len);
stack->len = len;
stack->top = -1;
return stack;
}
//入栈
bool push_stack(Stack* stack,int val)
{
if(full_stack(stack))
return false;
stack->arr[++stack->top] = val;
return true;
}
//出栈
bool pop_stack(Stack* stack)
{
if(empty_stack(stack))
return false;
stack->top--;
return true;
}
//判断栈是否为满
bool full_stack(Stack* stack)
{
return stack->top + 1 >= stack->len;
}
//判断栈是否为空
bool empty_stack(Stack* stack)
{
return stack->top == -1;
}
//显示栈顶
int top_stack(Stack* stack)
{
if(!empty_stack(stack))
return NULL;
return stack->arr[stack->top];
}
思路三:上面说到了栈实现,实际上递归也是一个栈的操作,所以也可以使用递归来实现。要实现反过来输出链表,我们每访问到一个节点的时候,先递归输出它后面的节点,再输出该节点自身,这样就实现了链表反转打印。。
复杂度分析:
void Listprint(ListNode* head)
{
if(head!=NULL && head->next!=NULL)
{
Listprint(ListNode* head->next);
}
if(head!=NULL) //防止为空链表
printf("%d\n",head->data);
}
注意:由于目前学习没有仔细研究过时间复杂度和空间复杂度,所以有些地方没有标注时间复杂度和空间复杂度,后期如果可以会加上。