特点:每一个节点都是在堆内存上独立new出来的,节点内存不连续
- 优点:
- 内存利用率高,不需要大块连续内存
- 插入和删除节点不需要移动其它节点,时间复杂度O(1)
- 不需要专门进行扩容操作(数组、vector是需要扩容的)
- 缺点
- 内存占用量比较大,每一个节点需要额外的空间存放地址
- 节点内存不连续,无法进行内存随机访问
- 链表搜索的效率不高,只能从头节点开始逐节点进行遍历
链表分类
- 单向链表
- 每一个节点除了数据域,还有一个next指针域指向下一个节点(存储了下一个节点的地址)
- 末尾节点的指针域是NULL/nullptr
- 双向链表
- TODO
- 循环链表
- TODO
#include<iostream>
#include<stdlib.h>
#include<time.h>
using namespace std;
//单链表的实现
struct ListNode{
ListNode(int data=0):data(data),next(nullptr){};
int data;
ListNode *next;
};
class Clink{
public:
Clink(){
head = new ListNode();
}
~Clink(){
//节点的释放
ListNode *p = head;
while (p!=nullptr)
{
head=head->next;
delete p;
p=head;
}
head=nullptr;
}
public:
//链表的尾插法实现
void InsertTail(int val){
//先找到链表的尾节点
ListNode *p = head;
while(p->next!=nullptr){
p=p->next;
}
//生成新节点
ListNode *q = new ListNode(val);
p->next = q;
}
//链表的头插法
void InsertHead(int val){
//新建要插入的节点
ListNode *q = new ListNode(val);
//新建节点q指向头节点指向的next,
q->next = head->next;
//头节点指向新建节点
head->next = q;
}
//链表节点的删除
void Remove(int val){
ListNode *q = head;
ListNode *p = head->next;
while(p!=nullptr){
if(p->data==val){
q->next = p->next;
delete p;
cout<<"Successfully"<<endl;
return;
}else{
q=q->next;
p=p->next;
}
}
}
//删除所有值为val的节点
void RemoveAll(int val){
ListNode *q = head;
ListNode *p = head->next;
while(p!=nullptr){
if(p->data==val){
q->next = p->next;
delete p;
p=q->next;
cout<<"Successfully"<<endl;
//return;
}else{
q=q->next;
p=p->next;
}
}
}
//搜索节点
bool Search(int val){
ListNode *p = head->next;
while(p!=nullptr){
if(p->data==val){
cout<<"I got it!"<<endl
return true;
}else{
p=p->next;
}
}
cout<<"Failed"<<endl;
return false;
}
//打印链表
void show(){
ListNode *p = head->next;
while(p!=nullptr){
cout<<p->data<<" ";
p=p->next;
}
cout<<endl;
}
private:
ListNode *head;
ListNode *tail;
};
int main(){
Clink link;
srand(time(0));
for(int i=0;i<10;i++){
int val = rand()%100;
cout<<val<<" ";
link.InsertHead(val);
// link.InsertTail(val);
}
link.InsertHead(999);
link.InsertHead(999);
link.InsertHead(999);
link.InsertHead(999);
cout<<endl;
link.show();
link.Remove(999);
link.Remove(0);
link.show();
link.RemoveAll(999);
link.show();
return 0;
}