数据结构单链表之反转链表 | 第九套

1,052 阅读4分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

给定指向链表头节点的指针,任务是反转链表。我们需要通过改变节点之间的链接来反转列表。

例子: 

输入:以下链表的头部 
1->2->3->4->NULL 
输出:链表应改为, 
4->3->2->1->NULL

输入:以下链表的头部 
1->2->3->4->5->NULL 
输出:链表应改为, 
5->4->3->2->1->NULL

输入:NULL 
输出:NULL 输入:1->NULL 
输出:1->NULL

  1. 将三个指针 prev 初始化为 NULL,curr 为 head,next 为 NULL。

  2. 遍历链表。 在循环中,执行以下操作。 
    // 在改变当前的下一个之前,存储下一个节点
    next = curr->next
    // 现在更改当前的下一个这是实际发生逆转的地方 
    curr->next = prev 
    // 将 prev 和 curr 向前移动一步 prev = curr 
    curr = next

RGIF2.gif

#include <iostream>
using namespace std;

struct Node {
	int data;
	struct Node* next;
	Node(int data)
	{
		this->data = data;
		next = NULL;
	}
};

struct LinkedList {
	Node* head;
	LinkedList() { head = NULL; }

	void reverse()
	{
		Node* current = head;
		Node *prev = NULL, *next = NULL;

		while (current != NULL) {
			next = current->next;
			current->next = prev;
			prev = current;
			current = next;
		}
		head = prev;
	}

	void print()
	{
		struct Node* temp = head;
		while (temp != NULL) {
			cout << temp->data << " ";
			temp = temp->next;
		}
	}

	void push(int data)
	{
		Node* temp = new Node(data);
		temp->next = head;
		head = temp;
	}
};

int main()
{
	LinkedList ll;
	ll.push(20);
	ll.push(4);
	ll.push(15);
	ll.push(85);

	cout << "Given linked list\n";
	ll.print();

	ll.reverse();

	cout << "\nReversed Linked list \n";
	ll.print();
	return 0;
}

输出:

Given linked list
85 15 4 20 
Reversed Linked list 
20 4 15 85

时间复杂度:  O(n) 
空间复杂度:  O(1)
递归方法: 

   1)将列表分为两部分 - 第一个节点和
      链表的其余部分。
   2) 对链表的其余部分调用 reverse。
   3)将休息链接到第一个。
   4) 修复头部指针
#include <iostream>
using namespace std;

struct Node {
	int data;
	struct Node* next;
	Node(int data)
	{
		this->data = data;
		next = NULL;
	}
};

struct LinkedList {
	Node* head;
	LinkedList()
	{
		head = NULL;
	}

	Node* reverse(Node* head)
	{
		if (head == NULL || head->next == NULL)
			return head;
		Node* rest = reverse(head->next);
		head->next->next = head;

		head->next = NULL;

		return rest;
	}

	void print()
	{
		struct Node* temp = head;
		while (temp != NULL) {
			cout << temp->data << " ";
			temp = temp->next;
		}
	}

	void push(int data)
	{
		Node* temp = new Node(data);
		temp->next = head;
		head = temp;
	}
};

int main()
{
	LinkedList ll;
	ll.push(20);
	ll.push(4);
	ll.push(15);
	ll.push(85);

	cout << "Given linked list\n";
	ll.print();

	ll.head = ll.reverse(ll.head);

	cout << "\nReversed Linked list \n";
	ll.print();
	return 0;
}

输出:

Given linked list
85 15 4 20 
Reversed Linked list
20 4 15 85

时间复杂度:  O(n) 
空间复杂度:  O(1)

一种更简单的尾递归方法 

下面是这个方法的实现。

#include <bits/stdc++.h>
using namespace std;

struct Node {
	int data;
	struct Node* next;
};

void reverseUtil(Node* curr, Node* prev, Node** head);

void reverse(Node** head)
{
	if (!head)
		return;
	reverseUtil(*head, NULL, head);
}

void reverseUtil(Node* curr, Node* prev, Node** head)
{
	if (!curr->next) {
		*head = curr;
		curr->next = prev;
		return;
	}

	Node* next = curr->next;

	curr->next = prev;

	reverseUtil(next, curr, head);
}

Node* newNode(int key)
{
	Node* temp = new Node;
	temp->data = key;
	temp->next = NULL;
	return temp;
}

void printlist(Node* head)
{
	while (head != NULL) {
		cout << head->data << " ";
		head = head->next;
	}
	cout << endl;
}

int main()
{
	Node* head1 = newNode(1);
	head1->next = newNode(2);
	head1->next->next = newNode(3);
	head1->next->next->next = newNode(4);
	head1->next->next->next->next = newNode(5);
	head1->next->next->next->next->next = newNode(6);
	head1->next->next->next->next->next->next = newNode(7);
	head1->next->next->next->next->next->next->next
		= newNode(8);
	cout << "Given linked list\n";
	printlist(head1);
	reverse(&head1);
	cout << "\nReversed linked list\n";
	printlist(head1);
	return 0;
}

输出

Given linked list
1 2 3 4 5 6 7 8 

Reversed linked list
8 7 6 5 4 3 2 1

使用堆栈:

  • 将节点(值和地址)存储在堆栈中,直到输入所有值。
  • 完成所有条目后,将 Head 指针更新到最后一个位置(即最后一个值)。
  • 开始弹出节点(值和地址)并以相同的顺序存储它们,直到堆栈为空。
  • 将堆栈中最后一个 Node 的 next 指针更新为 NULL。

下面是上述方法的实现:

#include <bits/stdc++.h>
#include <iostream>
using namespace std;

class Node
{
public:
	int data;
	Node* next;
};

void reverseLL(Node** head)
{
	stack<Node*> s;
	Node* temp = *head;
	while (temp->next != NULL)
	{
		
		// Push all the nodes
		// in to stack
		s.push(temp);
		temp = temp->next;
	}
	*head = temp;

	while (!s.empty())
	{
		temp->next = s.top();
		s.pop();
		temp = temp->next;
	}
	temp->next = NULL;
}

void printlist(Node* temp)
{
	while (temp != NULL)
	{
		cout << temp->data << " ";
		temp = temp->next;
	}
}

void insert_back(Node** head, int value)
{

	Node* temp = new Node();
	temp->data = value;
	temp->next = NULL;

	if (*head == NULL)
	{
	*head = temp;
	return;
	}
	else
	{
	Node* last_node = *head;
	while (last_node->next != NULL)
	{
		last_node = last_node->next;
	}
	last_node->next = temp;
	return;
	}
}

int main()
{
	Node* head = NULL;

	insert_back(&head, 1);
	insert_back(&head, 2);
	insert_back(&head, 3);
	insert_back(&head, 4);
	cout << "Given linked list\n";
	printlist(head);
	reverseLL(&head);
	cout << "\nReversed linked list\n";
	printlist(head);
	return 0;
}
**输出**

```C++
Given linked list
1 2 3 4 
Reversed linked list
4 3 2 1 

使用数组:

1. 创建一个链表。
2. 然后,做一个count(head)函数来统计节点数。
3. 用计数的大小初始化一个数组。
4. 并开始一个while(p->next!=NULL)循环并将所有节点的数据存储到数组中。
5. 然后将数组从最后一个索引打印到第一个。

#include <iostream>
#include<cstdlib>
using namespace std;

typedef struct node
{
int val;
struct node* next;
}node;

node* head=NULL;

int count(node* head) 
{
node* p=head;
int k=1;
while(p!=NULL)
{
	p=p->next;
	k++;
}
return k;
}

node *ll_reverse(node* head) 
{
node* p=head;
long int i=count(head),j=1;
long int arr[i];
while(i && p!=NULL)
{
	arr[j++]=p->val;
	p=p->next;
	i--;
}
j--;
while(j) 
{
	cout<<arr[j--]<<" ";
}

return head;
}

node* insert_end(node* head,int data) 
{
node* q=head,*p=(node*)malloc(sizeof(node));
p->val=data;
while(q->next!=NULL)
{
	q=q->next;
}
q->next=p;
p->next=NULL;
return head;
}

node *create_ll(node* head,int data) 
{
node* p=(node*)malloc(sizeof(node));
p->val=data;
if(head==NULL)
{
	head=p;
	p->next=NULL;
	return head;
}
else
{
	head=insert_end(head,data);
	return head;
}
}

int main()
{
int i=5,j=1;
while(i--)
{
	head=create_ll(head,j++);
}
head=ll_reverse(head);
	return 0;
}
输入:1->2->3->4->5
输出:5->4->3->2->1

时间复杂度:O(n) 空间复杂度:O(n)

🥇 往期优质文章

数据结构单链表之链表介绍 | 第一套
数据结构单链表之链表与数组 | 第二套
数据结构单链表之链表插入 | 第三套
数据结构单链表之删除节点 | 第四套
数据结构单链表之删除给定位置的链表节点 | 第五套
数据结构单链表之查看数组与链表的方法 | 第六套-1
数据结构单链表之查看数组与链表的方法 | 第六套-2
数据结构单链表之查找链表的长度(迭代和递归) | 第七套
数据结构单链表之交换链表中的节点而不交换数据 | 第八套

📣尾注: 想要获取更多数据结构相关的知识,你可以关注我:海拥,我希望你觉得这篇文章有帮助。

如果你看到这里,感谢你的阅读 :)

💌 欢迎大家在评论区提出意见和建议!💌

如果你真的从这篇文章中学到了一些新东西,喜欢它,收藏它并与你的小伙伴分享。🤗最后,不要忘了❤或📑支持一下哦。