链表
优点:插入删除比顺序表快
缺点:不能随机访问
结构
typdef struct listNode_{
DataType data; //数据域
listNode *next; //指针域
}listNode,*linkedList; //linkedList用于声明头指针
- 首元节点:第一个存数据的节点
- 头指针:指向链表第一个节点的指针
- 为了使首元节点和其他节点的删除插入操作一致,在表头添加头节点,头节点的
next指向首元节点,head指针指向头节点
初始化
申请一块头节点,头节点的指针域指向空,返回头节点地址
linkedList initialLinkedList(){
listNode *head = new listNode;
if (!head) {
cout << "申请失败" << endl;
return nullptr;
}
head->next = nullptr;
return head;
}
插入
头插法
插入节点newNode,更新newNode的指针域,再更新头节点head的指针域
linkedList head_insert(linkedList head, int key) {
listNode *newNode = new listNode;
newNode->data = key;
newNode->next = head->next;
head->next = newNode;
return head;
}
尾插法
先通过遍历找到尾节点,再更新原尾节点的指针域
linkedList rear_insert(linkedList head, int key) {
listNode *newNode = new listNode;
newNode->data = key;
listNode *p = head;
while (p->next) {
p = p->next;
}
newNode->next = p->next;
p->next = newNode;
return head;
}
- 优化:用指针
rear记录尾节点,每次尾插之后更新rear指针
查找
通过遍历查找
listNode *find(linkedList head, int key) {
listNode *p = head->next;
if (!p) {
cout << "链表为空" << endl;
return p;
}
while (p && p->data != key) { //先判空再比较,反过来会非法访问
p = p->next;
}
if (!p)cout << "没找到" << endl;
return p;
}
删除
- 将要删除的节点的前驱的指针域指向要删除节点的后继
- 回收要删除的节点
linkedList Delete(linkedList head, int key) {
listNode *p = head->next;
while (p->next && p->next->data != key) {
p = p->next;
}
if (p->next == nullptr) {
cout << "未找到" << endl;
return head;
}
listNode *temp = p->next;
p->next = p->next->next;
delete temp;
temp=nullptr; //防止temp成为野指针
return head;
}
双向链表与循环链表与单链表类似
双向链表
结构
struct listNode {
int data;
listNode *pre, *next;
};
初始化
LinkedList initial() {
LinkedList head = new listNode;
head->next = head->pre = nullptr;
return head;
}
插入
头插法
LinkedList head_insert(LinkedList head, int key) {
listNode *newNode = new listNode;
newNode->data = key;
newNode->next = head->next;
head->next = newNode;
newNode->pre = head;
if (newNode->next)
newNode->next->pre = newNode;
return head;
}
尾插法
LinkedList rear_insert(LinkedList head, int key) {
listNode *newNode = new listNode;
newNode->data = key;
listNode *p = head;
while (p->next) {
p = p->next;
}
newNode->next = nullptr;
newNode->pre = p;
p->next = newNode;
return head;
}
删除
LinkedList Delete(LinkedList head, int key) {
listNode *p = head->next;
while (p && p->data != key) {
p = p->next;
}
if (!p) {
cout << "未找到" << endl;
return head;
}
p->pre->next = p->next;
if (p->next)p->next->pre = p->pre;
delete p;
p = nullptr;
return head;
}
循环链表
循环链表默认有头节点,循环链表的尾节点的next指针域指向头节点
- 初始化循环链表时,头节点的指针域指向自己
链表逆转
双指针
pre指针指向上一个节点,cur指向当前节点,用temp指向cur的下一个节点cur的next指向pre- 让
pre指向cur,再cur指向temp cur为空退出循环
void reverseLinkedList(listNode *head){
listNode *pre=nullptr;
listNode *cur=head->next;
listNode *tmep=nullptr;
while(cur){
temp=cur->next;
cur->next=pre;
pre=cur;
cur=temp;
}
head->next=pre;
}
快慢指针
要找到链表中倒数第k个节点
fast指针指向链表中第k+1个节点,slow指向链表中第1个节点- 让
fast和slow同时往下遍历 fast为空退出循环,此时slow为倒数第k个节点
listNode find(listNode *head){
listNode *fast=head->next;
listNode *slow=head->next;
for(int i=0;i<k;i++){
fast=fast->next;
if(!fast){
cout<<"error"<<endl;
return nullptr;
}
}
while(fast){
fast=fast->next;
slow=slow->next;
}
return slow;
}
静态链表
用数组存储,指针域存下一个节点的下标,下标0表示空
结构
struct listNode{
DataType data; //数据域
int next; //指针域
};
struct staticList{
int capacity; //数组长度-1
int size; //表中节点个数
listNode *nodes;
int first; //第一个节点的下标
}
跳表
有序链表实现二分查找
- 一个跳表有(logN)层链表,上一层链表节点数是下一层节点数的1/2
- 最底层的是原始链表,包含所有数据
- 每层链表都是有序的
- 上层的节点的其中一个指针域指向下层相同值的节点
head->next指向最上层第一个节点

浙公网安备 33010602011771号