链表
链表不一定由结构体构成,也可能是数与数之间的固定指向


一般来说,有头链表使用时更方便
无头链表 代码演示:
#include <iostream>
#include<map>
#include<ctime>
#include<cstdio>
#include<vector>
#include<cstdlib>
#include<unordered_map>
#include<stack>
using namespace std;
#define DIGIT_LEN 3
typedef struct Node {
int data;
Node* next;
}Node;
Node* getNewNode(int val) {
Node* p = (Node*)malloc(sizeof(Node));
p->data = val;
p->next = NULL;
return p;
}
void clear(Node* head) {
if (head == NULL) return;
for (Node* p = head, *q; p; p = q) {
q = p->next;
free(p);
}
return;
}
Node* insert(Node* head, int pos, int val) {
if (pos == 0) {
Node* p = getNewNode(val);
p->next = head;
return p;
}
Node* p = head;
for (int i = 0; i < pos - 1; i++) {
p=p->next;
}
Node* node = getNewNode(val);
node->next = p->next;
p->next = node;
return head;
}
Node* erase(Node* head, int pos) {
Node* p = head;
if (pos == 0) {
head->data = 0;
head = head->next;
p->next = NULL;
return head;
}
for (int i = 0; i < pos - 1; i++)
{
p = p->next;
}
p = p->next->next;
return head;
}
void output_linklist(Node *head,int flag=0) {
int n = 0;
for (Node* p = head; p; p = p->next) {
++n;
}
for (int i = 0; i < n; i++) {
printf("%3d", i);
printf(" ");
}
printf("\n");
for (Node* p = head; p; p = p->next) {
printf("%3d", p->data);
if(p->next)printf("->");
}
if (flag == 0)printf("\n\n\n");
else printf("\n");
return;
}
int find(Node* head, int val) {
Node* p = head;
int n = 0;
while (p) {
if (p->data == val)
{
output_linklist(head,1);
for (int i = 0; i < n; i++)
printf(" ");
printf(" ^ \n");
for (int i = 0; i < n; i++)
printf(" ");
printf(" | \n");
return 1;
}
n += 1;
p = p->next;
}
return 0;
}
int main()
{
srand((unsigned int)time(0));
#define MAX_OP 20
Node* head = NULL;
for (int i = 0; i < MAX_OP; i++) {
int pos = rand() % (i + 1), val = rand() % 100;
printf("insert %d at %d to linklist\n", val, pos);
head=insert(head, pos, val);
output_linklist(head);
}
int val;
while (~scanf_s("%d", &val)) {
if (!find(head, val)) {
printf("not found\n");
}
}
clear(head);
return 0;
}
有头节点运用于插入--减少了if
Node* insert(Node* head, int pos, int val) {
Node new_head, * p = &new_head, * node = getNewNode(val);//临时创建头节点
new_head.next = head;
for (int i = 0; i < pos; i++) p = p->next;
node->next = p->next;
p->next = node;
return new_head.next;
}
循环链表

特点:
-
把链表的尾节点当作虚拟头节点
-
通过快慢指针可以分辨是单向链表还是循环链表
代码:哈希
bool hasCycle(ListNode *head) {
unordered_map<ListNode*,int> umap;
ListNode *p=head;
while(p){
umap[p]++;
if(umap[p]==2) return true;
p=p->next;
}
return false;
}
快慢指针
bool hasCycle(ListNode *head) {
ListNode *fast_ptr=head;
ListNode *low_ptr=head;
while(fast_ptr&&fast_ptr->next){
low_ptr=low_ptr->next;
fast_ptr=fast_ptr->next->next;
if(low_ptr==fast_ptr) return true;
}
return false;
}
-
双指针等距移动法:确定链表中的倒数第几位的位置
leetcode:19
双向链表

本文详细介绍了链表的基础概念,包括头节点的使用、无头链表的实现,以及如何通过快慢指针和哈希表检测循环链表。同时探讨了双向链表的特点和LeetCode中的一道相关问题.
1517

被折叠的 条评论
为什么被折叠?



