c++链表的详细讲解

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

c++链表的详细讲解
链表是一种常见的数据结构,可以通过节点之间的指针关系将多
个元素有序地连接起来。

链表的内存分配是动态的,可以根据实际的
需求进行灵活的扩展和收缩,相较于数组有着更好的插入和删除操作
性能。

链表由多个节点组成,每个节点包含两部分:一个是数据部分,
用来存储实际的元素值;另一个是指针部分,用来指向下一个节点。

在C++中,通过结构体或类定义节点,使用指针来连接节点之间的关系。

一、单链表
单链表是最简单的链表形式,每个节点只有一个指针指向下一个
节点,最后一个节点的指针指向空。

单链表的头节点为链表的入口,
通过遍历操作可以访问到链表中的每一个节点。

1.定义节点结构体
```cpp
struct Node{
int data;
Node* next;
};
```
节点结构体包含一个整型数据成员data,用来存储元素值;一个指向下一个节点的指针成员next。

2.创建链表
创建链表需要分配内存,并将指针进行连接。

```cpp
Node* createLinkedList(int size){
Node* head = nullptr; //头节点指针
Node* tail = nullptr; //尾节点指针
for(int i=0; i<size; i++){
Node* newNode = new Node;
cout << "请输入第" << i+1 << "个节点的值:";
cin >> newNode->data;
newNode->next = nullptr; //新节点的next指针置为空
if(head == nullptr){ //如果是第一个节点
head = newNode; //头节点指针指向第一个节点
tail = newNode; //尾节点指针指向第一个节点
}
else{ //如果不是第一个节点
tail->next = newNode; //将尾节点的next指针指向新节点tail = newNode; //尾节点指针指向新节点
}
}
return head; //返回头节点指针
}
```
函数createLinkedList接受一个参数size,表示链表的长度,返回一个头节点的指针。

3.遍历链表
遍历链表即通过指针依次访问链表的每个节点,并打印节点的数据。

```cpp
void traverseLinkedList(Node* head){
Node* p = head;
while(p != nullptr){
cout << p->data << " ";
p = p->next; //指针指向下一个节点
}
}
```
函数traverseLinkedList接受一个参数head,表示链表的头节点指针,通过循环遍历链表的每一个节点。

4.插入节点
在链表中插入节点即在指定位置上插入一个新的节点,需要修改指针的指向,使得新节点正确链接到链表中。

```cpp
void insertNode(Node* head, int pos, int value){
Node* newNode = new Node;
newNode->data = value;
Node* p = head;
int count = 0;
while(p != nullptr && count < pos-1){
p = p->next; //指针指向下一个节点
count++;
}
if(p == nullptr || count > pos-1){
cout << "插入位置无效!" << endl;
return;
}
newNode->next = p->next;
p->next = newNode;
}
```
函数insertNode接受三个参数,head表示链表的头节点指针,pos表示要在链表中插入节点的位置,value表示要插入的节点的值。

5.删除节点
删除链表中的节点即断开所需删除节点的指针,并释放其内存空间。

```cpp
void deleteNode(Node* head, int pos){
Node* p = head;
int count = 0;
while(p != nullptr && count < pos-1){
p = p->next; //指针指向下一个节点
count++;
}
if(p == nullptr || p->next == nullptr || count > pos-1){ cout << "删除位置无效!" << endl;
return;
}
Node* temp = p->next;
p->next = temp->next;
delete temp;
}
```
函数deleteNode接受两个参数,head表示链表的头节点指针,pos表示要删除的节点的位置。

二、双向链表
双向链表的节点包含两个指针,分别指向上一个节点和下一个节点。

相较于单链表,双向链表可以通过反向的指针关系快速地访问到前一个节点。

1.定义节点结构体
```cpp
struct Node{
int data;
Node* prev;
Node* next;
};
```
节点结构体包含一个整型数据成员data,用来存储元素值;一个指向上一个节点的指针成员prev;一个指向下一个节点的指针成员next。

2.创建链表
创建双向链表与创建单链表类似,需要分配内存,并将指针进行连接。

```cpp
Node* createDLinkedList(int size){
Node* head = nullptr; //头节点指针
Node* tail = nullptr; //尾节点指针
for(int i=0; i<size; i++){
Node* newNode = new Node;
cout << "请输入第" << i+1 << "个节点的值:";
cin >> newNode->data;
newNode->prev = nullptr; //新节点的prev指针置为空
newNode->next = nullptr; //新节点的next指针置为空if(head == nullptr){ //如果是第一个节点
head = newNode; //头节点指针指向第一个节点tail = newNode; //尾节点指针指向第一个节点
}
else{ //如果不是第一个节点newNode->prev = tail; //新节点的prev指针指向尾节点tail->next = newNode; //尾节点的next指针指向新节点tail = newNode; //尾节点指针指向新节点
}
}
return head; //返回头节点指针
}
```
返回一个头节点的指针。

3.遍历链表
遍历双向链表即通过指针依次访问链表的每个节点,并打印节点的数据。

```cpp
void traverseDLinkedList(Node* head){
Node* p = head;
while(p != nullptr){
cout << p->data << " ";
p = p->next; //指针指向下一个节点
}
}
```
点指针,通过循环遍历链表的每一个节点。

4.插入节点
在双向链表中插入节点需要修改前一个节点和后一个节点的指针指向,使得新节点正确链接到链表中。

```cpp
void insertDNode(Node* head, int pos, int value){
Node* newNode = new Node;
newNode->data = value;
Node* p = head;
int count = 0;
while(p != nullptr && count < pos-1){
p = p->next; //指针指向下一个节点
count++;
}
if(p == nullptr || count > pos-1){
cout << "插入位置无效!" << endl;
return;
}
newNode->prev = p;
newNode->next = p->next;
p->next->prev = newNode;
p->next = newNode;
}
```
函数insertDNode接受三个参数,head表示链表的头节点指针,pos表示要在链表中插入节点的位置,value表示要插入的节点的值。

5.删除节点
删除双向链表中的节点需要修改前一个节点和后一个节点的指针指向,断开所需删除节点的指针,并释放其内存空间。

```cpp
void deleteDNode(Node* head, int pos){
Node* p = head;
int count = 0;
while(p != nullptr && count < pos-1){
p = p->next; //指针指向下一个节点
count++;
}
if(p == nullptr || p->next == nullptr || count > pos-1){ cout << "删除位置无效!" << endl;
return;
}
Node* temp = p->next;
p->next = temp->next;
temp->next->prev = p;
delete temp;
}
```
函数deleteDNode接受两个参数,head表示链表的头节点指针,pos表示要删除的节点的位置。

三、应用场景
链表具有以下特点,适用于以下应用场景:
1.需要经常进行插入和删除操作的情况,链表的插入和删除操作时间复杂度为O(1),相较于数组的O(n)有着更好的性能。

2.需要灵活扩展和收缩大小的情况,链表的内存分配是动态的,可以根据实际需求进行自由调整。

3.需要支持高效的逆序遍历操作的情况,双向链表通过反向的指针关系可以快速地访问到前一个节点。

4.对内存空间要求较高的情况,链表的内存分配是动态的,仅使用实际需要的内存空间。

总结:
链表是一种常见的数据结构,通过指针将多个节点有序地连接起来。

单链表通过节点之间的next指针连接,双向链表通过prev和next指针连接。

链表适用于需要频繁插入和删除操作的情况,具有动态内存分配、逆序遍历等优点。

相关文档
最新文档