创建链表的过程详解
本人是一名刚开始学习算法的小白,今天遇到了一些关于链表的创建问题,查了一些资料,我把它们整理了一下,希望大家多多指教。
整体的代码:
#include<iostream>
using namespace std;
struct Node {
int val;
Node* next;
};
#创建
Node* creatlist(int n) {
Node* Head=new Node; //头节点 不存储数据
Head->next = NULL;
Node* pre = Head; //指向下一个节点的过渡值
cout << "请依次输入" << n << "个链表的值:";
for (int i = 0;i < n;i++) {
Node* temp = new Node;
cin >> temp->val;
pre->next = temp;
pre = temp;
temp->next = NULL;
}
return Head;
}
#显示
void display(Node* head) {
Node* temp=head->next;
int e;
cout << "该链表的遍历依次为:";
while (temp!=NULL) {
e = temp->val;
cout << e << " ";
temp = temp->next;
}
cout << "\n";
}
int main() {
int nums;
cout << "请输入链表的长度:";
cin >> nums;
Node* head = creatlist(nums);
display(head);
return 0;
}
解释
1、基本概念:
链表是物体存储单元上不连续的储存结构,数据元素是由链表上的指针所连接。
每个节点都包含两部分:存储数据的数据域,和存储下一个节点的地址的指针域。
根据上图,利用数据结构struct建立一个节点:
struct Node {
int val; //数据域
Node* next; //指数域
};
创建链表:
#创建
Node* creatlist(int n) {
//头节点 不存储数据,指针域指向空
Node* Head=new Node;
Head->next = NULL;
//为了让节点连接成链接,定义pre,最开始pre等于Head
Node* pre = Head;
cout << "请依次输入" << n << "个链表的值:";
for (int i = 0;i < n;i++) {
//每次循环都创建一个新的节点
Node* temp = new Node;
//把值赋给temp节点的数据域
cin >> temp->val;
//pre的指数域指向的下一个节点temp,把pre和temp连接起来
pre->next = temp;
//把temp节点赋给pre,重新定义pre
pre = temp;
//在下次for循环再一次创建新temp节点前,temp的指数域指向空
temp->next = NULL;
}
//把头节点返回,知道头节点,节点与节点之间又相互连接,所以知道每个节点中的值
return Head;
}
Node* pre 在这个程序中的作用是将不同节点连接成链接,
最开始pre等于head,pre的指数域指向temp1,然后将temp1赋给pre,temp1的指数域指向空,
下次循环建立temp2,pre的指数域指向temp2,然后将temp2赋给pre,temp2的指数域指向空。
创建链表的关键是要把节点连接起来,也就是要让前一个节点的指针域指向下一个节点:
显示链表:只要输入链表的头节点,就可以不断通过节点的指向来显示出所有节点的val:
void display(Node* head) {
Node* temp=head->next;
int e;
cout << "该链表的遍历依次为:";
while (temp!=NULL) {
e = temp->val;
cout << e << " ";
temp = temp->next;
}
cout << "\n";
}
习题1:合并两个链表
class Solution {
public:
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
ListNode* preHead = new ListNode(-1);
ListNode* prev = preHead;
while (l1 != nullptr && l2 != nullptr) {
if (l1->val < l2->val) {
prev->next = l1;
l1 = l1->next;
} else {
prev->next = l2;
l2 = l2->next;
}
prev = prev->next;
}
// 合并后 l1 和 l2 最多只有一个还未被合并完,我们直接将链表末尾指向未合并完的链表即可
prev->next = l1 == nullptr ? l2 : l1;
return preHead->next;
}
};
习题2:删除链表中的元素
struct Node {
int data;
Node* next;
};
int Delete(int i) { //删除i处的数据
Node* temp;
temp = Head;
int j = 0;
while (temp && j < i - 1) {
temp = temp->next;
j++;
}
if (!temp || j > i - 1) {
cout << "删除位置错误";
return -1;
}
else {
Node* s;
s = temp->next;
temp->next = s->next;
delete s;
}
}
struct ListNode {
int val;
ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};
ListNode* deleteDuplicates(ListNode* head) {
ListNode* pre=head;
while(pre!=NULL && pre->next!=NULL){
if(pre->val == pre->next->val){
pre->next = pre->next->next;
}
else{
pre = pre->next;
}
}
return head;
}
习题3:判断两个链表是否相交
解法一:双指针法
可以理解成两个人速度一致, 走过的路程一致。那么肯定会同一个时间点到达终点。如果到达终点的最后一段路两人都走的话,那么这段路上俩人肯定是肩并肩手牵手的。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
if(headA==NULL||headB==NULL) {return NULL;}
ListNode *p1=headA;
ListNode *p2=headB;
while(p1!=p2){
p1= p1==NULL?headB:p1->next;
p2= p2==NULL?headA:p2->next;
}
return p1;
}
};
解法二:暴力法
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
ListNode *p1=headA;
ListNode *p2=headB;
while(p1!=p2){
p1= p1==NULL?headA:p1->next;
p2= p2==NULL?headB:p2->next;
}
return p1;
}
};
解法三:哈希表法
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
unordered_set<ListNode*> set;
ListNode* hA = headA; ListNode* hB = headB;
while(hA) {
set.insert(hA);
hA = hA->next;
}
while(hB) {
if(set.count(hB) == 1) return hB;
hB = hB->next;
}
return NULL;
}
};
参考:
链接: 用c++写一个链表
链接: 哔哩哔哩视频