特点:
每一个节点都是在堆内存上独立new出来的,节点内存不连续。
缺点:
- 内存占用量大,每一个节点多出内存地址的空间
- 节点内存不连续,无法进行内存随机访问
- 链表搜索效率不高,只能从头节点逐节点遍历
单向链表特点:
- 每一个节点除了数据域,还有一个next指针域指向下一个节点(存储了下一个节点的地址),但是无法回退到前一个节点
- 末尾节点的指针域是NULL
数组链表如何选择:
-
数组
- 下标访问/随机访问对、搜索多
-
链表:
- 增加、删除多
单链表的实现:
#include <iostream>
#include <stdlib.h>
#include <time.h>
using namespace std;
// 节点类型
struct Node
{
Node(int data = 0):data_(data),next_(nullptr)
{}
int data_;
Node* next_;
};
// 单链表
class Clink
{
public:
Clink()
{
// 给head_初始化指向头节点
head_ = new Node();
}
~Clink()
{
// 节点的释放
Node* p = head_;
while (p != nullptr)
{
head_ = head_->next_;
delete p;
p = head_;
}
head_ = nullptr;
}
public:
// 链表尾插法 O(n)
void InsertTail(int val)
{
// 先找到当前链表的末尾节点
Node* p = head_;
while (p->next_ != nullptr)
{
p = p->next_;
}
// 生成新节点
Node* node = new Node(val);
// 把新节点挂在尾节点的后面
p->next_ = node;
}
//链表的头插法 O(1)
void InserHead(int val)
{
Node* node = new Node(val);
node->next_ = head_->next_;
head_->next_ = node;
}
// 链表节点的删除
void Remove(int val)
{
Node* q = head_;
Node* p = head_->next_;
while (p!=nullptr)
{
if (p->data_ == val)
{
// 删除一个节点本身的操作是O(1)
q->next_ = p->next_;
delete p;
return;
}
else
{
q = p;
p = p->next_;
}
}
}
// 删除多个节点
void RemoveAll(int val)
{
Node* q = head_;
Node* p = head_->next_;
while (p!=nullptr)
{
if (p->data_ == val)
{
q->next_ = p->next_;
delete p;
// 对指针p进行重置
p = q->next_;
}
else
{
q = p;
p = p->next_;
}
}
}
// 搜索
bool Find(int val)
{
Node* p = head_->next_;
while (p!=nullptr)
{
if (p->data_ == val)
{
return true;
}
else
{
p = p->next_;
}
}
}
// 链表打印
void show()
{
Node* p = head_->next_;
while (p!=nullptr)
{
cout << p->data_ << " ";
p = p->next_;
}
cout << endl;
}
private:
Node* head_;// 指向链表的头节点
};
int main()
{
int arr[] = { 25,37,52,78,88,92,98,108 };
int brr[] = { 13,23,40,56,62,77,109 };
Clink link1;
Clink link2;
for (int v : arr)
{
link1.InsertTail(v);
}
for (int v : brr)
{
link2.InsertTail(v);
}
link1.show();
link2.show();
return 0;
}