题目描述
输入一个链表,反转链表后,输出新链表的表头。
1、 分析
本题目需要初始化一个链表,反转链表即将原链表中的元素按逆序重新排列;
即需要新建一个链表,将原链表中值逆序赋值给新链表,关键在于怎么访问逆序访问链表中的元素;
单链表逆序访问,很麻烦,因为单链表定义了next指针域用于遍历后面结点元素,无法直接从链表末尾向前访问结点;
//单链表结构
typedef struct Link
{
char elem; //代表数据域
struct Link * next; //代表指针域,指向直接后继元素
}link;
循环链表,是将单链表首尾相连,可以通过遍历到尾部结点,在循环一遍,也只从头结点遍历到链表尾部,无法直接逆序访问;
//循环链表结构
typedef struct node{
int number;
struct node *next;
}person;
双向链表中next指向后续结点,pre指向前驱结点,可以通过pre实现链表的逆序访问,故本题使用双向链表实现;
//双向链表结构
typedef struct line{
struct line *prior;//指向直接前趋
int data;
struct line *next;//指向直接后继
}line;
2、思路
先初始化双向链表,并返回原链表的尾部结点地址,用前驱变量;
新建一个单链表或双向链表,原双向链表通过pre访问前驱结点,然后将结点元素值赋给新链表,实现链表反转;
3、代码实现
链表初始化
link * initLink(){
link *head = (link *)malloc(sizeof(link));
head->next =NULL;
head->pre =NULL;
head->elem = 0;
link *temp = head;
int i;
for(i=0;i<10;i++){
//初始化结点
link *body = (link *)malloc(sizeof(link));
body->elem = i;
body->next = NULL;
body->pre = NULL;
//新增结点
temp->next = body;
body->pre = temp;
temp = temp->next;
// printf("%d\n",temp->elem);
}
// printf("%d\n",temp->pre->elem);
printf("%d\n",temp->elem);//使用非法地址??
return temp;
}
链表反转
int func(link *qq){
link *head = (link *)malloc(sizeof(link));
//printf("head首地址:%d\n",head);
head->next = NULL;
head->pre = NULL;
link *temp = head;
//printf("temp首地址:%d\n",temp);
while(qq->pre != NULL){
//初始化结点
link *body = (link *)malloc(sizeof(link));
body->next = NULL;
body->pre = NULL;
//给结点元素赋值
body->elem = qq->elem;
//新增结点
temp->next = body;
body->pre = temp;
//遍历上一个元素
qq = qq->pre;
//新建的链表遍历变量指向下一个结点
temp = temp->next;
printf("%d\n",body->elem);
}
//printf("temp首地址:%d\n",temp);
//printf("head首地址:%d\n",head);
return head->next->elem;
}
4、完整代码
#include<stdio.h>
#include<malloc.h>
/*反转链表:输入一个链表,反转链表后,输出一个新链表的表头*/
/*思路1:使用两个单链表,将已经初始化的链表A从尾到头,元素值赋给链表A
2、循环链表?不新建一个链表,元素值无法转换,
3、双向链表?使用前驱遍历元素快些,但还需要新建一个链表*/
typedef struct Link{
int elem;
struct Link *next;
struct Link *pre;
}link;
link * initLink();
void display();
int func();
int main(){
//初始化链表
link *q;
q = initLink();//传参可以传入链表长度
// display(head);
// link *newhead = (link *)malloc(sizeof(link));
int a = func(q);
printf("新链表的表头为:%d\n",a);
}
link * initLink(){
link *head = (link *)malloc(sizeof(link));
head->next =NULL;
head->pre =NULL;
head->elem = 0;
link *temp = head;
int i;
for(i=0;i<10;i++){
//初始化结点
link *body = (link *)malloc(sizeof(link));
body->elem = i;
body->next = NULL;
body->pre = NULL;
//新增结点
temp->next = body;
body->pre = temp;
temp = temp->next;
// printf("%d\n",temp->elem);
}
// printf("%d\n",temp->pre->elem);
printf("%d\n",temp->elem);//使用非法地址??
return temp;
}
void display(link *p){
link *temp = p;
while(temp->next !=NULL){
// printf("%d\n",temp->elem);//会打印头元素的值,但头元素未初始化,未垃圾值
temp = temp->next;
printf("%d\n",temp->elem);
}
}
int func(link *qq){
link *head = (link *)malloc(sizeof(link));
printf("head首地址:%d\n",head);
head->next = NULL;
head->pre = NULL;
link *temp = head;
printf("temp首地址:%d\n",temp);
while(qq->pre != NULL){
//初始化结点
link *body = (link *)malloc(sizeof(link));
body->next = NULL;
body->pre = NULL;
//给结点元素赋值
body->elem = qq->elem;
//新增结点
temp->next = body;
body->pre = temp;
//遍历上一个元素
qq = qq->pre;
//新建的链表遍历变量指向下一个结点
temp = temp->next;
printf("%d\n",body->elem);
}
printf("temp首地址:%d\n",temp);
printf("head首地址:%d\n",head);
return head->next->elem;
}
输出结果
C++ 代码实现
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};*/
class Solution {
public:
ListNode* ReverseList(ListNode* pHead) {
if(pHead == NULL || pHead -> next == NULL)
return pHead;
ListNode* p = pHead;
stack<ListNode* > s;
while(p -> next)
{
s.push(p);
p = p -> next;
}
ListNode* head = p;
while(!s.empty())
{
p -> next = s.top();
p = p -> next;
s.pop();
}
p -> next = NULL;
return head;
}
};