15 链表反转

题目描述

输入一个链表,反转链表后,输出新链表的表头。

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

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值