链表
链表不一定由结构体构成,也可能是数与数之间的固定指向
一般来说,有头链表使用时更方便
无头链表 代码演示:
#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
双向链表