#include<algorithm>
#include<iostream>
#include<vector>
using namespace std;
struct ListNode // 定义链表节点
{
int data; // 存放节点数据
ListNode* next; // 存放下一个节点的地址,以此连接各个节点,最后一个节点的next指针为NULL
};
void Listprintf(ListNode* phead) // 定义链表输出函数 参数为*phead
{
ListNode* cur=phead; // *cur指向头节点phead
while (cur != NULL) // 当前节点非空
{
cout << cur->data << "->"; // 输出当前节点值和箭头符号
cur = cur->next; // 当前节点指向下一节点
}
cout << "NULL" << endl; // 输出NULL表示链表结束
}
void Listpushback(ListNode** pphead, int x) // 尾部插入节点函数 二级指针(指向一个指针的指针)
{
ListNode* newnode = new ListNode{ x, NULL }; // 创建新节点
if (*pphead == NULL) // 如果链表为空,则将新节点赋给pphead指针
{
*pphead = newnode;
}
else // 如果*pphead指针指向非空,那么*tail = *pphead
{
ListNode* tail = *pphead; // 定义指针tail指向链表头
while(tail->next != NULL) // // 找到尾部节点,当tail的next属性值为非空时,循环继续
{
tail = tail->next; // tail的值== tail -> next 指向next
}
tail->next = newnode; // 此时的tail已经是尾部节点 在尾部节点后插入新节点
// 意思是 *a = *p; a = b; b = c
}
}
void Listpushfront(ListNode** pphead, int x) // 头节点插入函数
{
ListNode* newnode = new ListNode{ x, NULL }; // 创建新节点
newnode->next = *pphead; // 新节点的next指向当前头节点
*pphead = newnode; // 更新头节点为新节点
}
//尾删
void Listpopback(ListNode** pphead) // 尾节点删除函数
{
if (*pphead == NULL) // 如果链表为空,则直接返回
{
return;
}
if ((*pphead)->next == NULL) // 如果链表只有一个节点
{
delete(*pphead); // 删除头节点
*pphead = NULL; // 将头节点置为空
}
else // 非空
{
ListNode* tail = *pphead; // 定义指针tail指向链表头
ListNode* prev = NULL;
while (tail->next) // 当tail的下一个值非空时
{ // 找到尾部节点和尾部节点的前一个节点
prev = tail; // prev = tail 当前的地址 用于记录当前值的地址
tail = tail->next; // tail指向下一个值的地址
}
delete(tail); // 删除尾部节点 删除tail也就是删除了*pphead
tail = NULL; // 将尾部节点置为空
prev->next = NULL; // 更新尾部节点的前一个节点的next指针为NULL
}
}
//头删
void Listpopfront(ListNode** pphead)
{
if (*pphead == NULL) // 如果链表为空,则直接返回
{
return;
}
else
{
ListNode* newnode = (*pphead)->next; // // 定义指针newnode指向头节点的下一个节点
delete(*pphead); // 删除头节点
*pphead = newnode; // 更新头节点为下一个节点
}
}
//查找元素,返回值是地址
ListNode* Listfind(ListNode* phead, int x)
{
ListNode* cur = phead; // 定义指针cur指向链表头
while (cur) // 遍历链表
{
if (cur->data == x) // 找到指定元素
{
return cur; // 返回当前节点地址
}
else
{
cur = cur->next; // 继续遍历下一个节点
}
}
return NULL; // 若未找到指定元素,则返回NULL
}
//插入元素,在pos的前一个位置插入
//配合Listfind使用,具体使用见test_insert函数
void Listinsert(ListNode** phead, ListNode* pos, int x)
{
ListNode* newnode = new ListNode{ x,NULL }; // 创建新节点
if (*phead == pos) // 如果pos是头节点
{
newnode->next = (*phead); // 将新节点插入到头部
*phead = newnode;
}
else // 否则,找到pos的前一个节点posprev
{
ListNode* posprev = *phead;
while (posprev->next != pos)
{
posprev = posprev->next;
}
// 修改指针使得新节点插入到posprev和pos之间
posprev->next = newnode;
newnode->next = pos;
}
}
//单链表并不适合在前一个位置插入,因为运算较麻烦,会损失效率
//包括c++中为单链表提供的库函数也只有一个insert_after而没有前一个位置插入
//在后一个位置插入相对简单
void Listinsert_after(ListNode** phead, ListNode* pos, int x)
{
ListNode* newnode = new ListNode{ x,NULL }; // 创建新节点
newnode->next = pos->next; // 修改指针使得新节点插入到pos的后面
pos->next = newnode;
}
//删除指定位置的节点
void Listerase(ListNode** pphead, ListNode* pos) // 需要给定链表头指针和目标节点pos
{
if (*pphead == pos) // 如果要删除的是头节点
{
*pphead = pos->next; // 更新头指针为头节点的下一个节点
delete(pos); // 释放节点内存
}
else
{ // 否则,找到目标节点的前一个节点prev
ListNode* prev = *pphead;
while (prev->next!=pos)
{
prev = prev->next;
}
// 修改指针使得prev指向pos的下一个节点,然后释放pos节点的内存
prev->next = pos->next;
delete(pos);
}
}
// 释放链表占用的内存
void Listdestory(ListNode** pphead) // 需要给定链表头指针
{
ListNode* cur = *pphead;
while(cur) // 遍历链表,释放每个节点的内存
{
ListNode* next = cur->next;
delete(cur);
cur = next;
}// 将头指针置为空
*pphead = NULL;
}
void test_insert()
{
ListNode* phead = NULL;
Listpushback(&phead, 1);
Listpushback(&phead, 2);
Listpushback(&phead, 3);
Listprintf(phead);
ListNode* pos = Listfind(phead, 2);
if (pos != NULL)
{
Listinsert(&phead, pos, 20);
}
Listprintf(phead);
pos = Listfind(phead, 2);
if (pos != NULL)
{
Listinsert_after(&phead, pos, 20);
}
Listprintf(phead);
Listdestory(&phead);
}
void test_find()
{
ListNode* phead = NULL;
Listpushback(&phead, 1);
Listpushback(&phead, 2);
Listpushback(&phead, 3);
Listprintf(phead);
ListNode* pos = Listfind(phead, 2);
if (pos != NULL)
{
pos->data = 20;//Listfind不仅能查找,也能借此修改,这也是函数返回地址的原因
}
Listprintf(phead);
Listdestory(&phead);
}
void test_erase()
{
ListNode* phead = NULL;
Listpushback(&phead, 1);
Listpushback(&phead, 2);
Listpushback(&phead, 3);
Listprintf(phead);
ListNode* pos = Listfind(phead, 2);
if (pos != NULL)
{
Listerase(&phead, pos);
}
Listprintf(phead);
Listdestory(&phead);
}
void test_pop_and_push()
{
ListNode* phead = NULL;
Listpushback(&phead, 1);
Listpushback(&phead, 2);
Listpushback(&phead, 3);
Listprintf(phead);
Listpushfront(&phead, 1);
Listpushfront(&phead, 2);
Listpushfront(&phead, 3);
Listprintf(phead);
Listpopback(&phead);
Listpopfront(&phead);
Listprintf(phead);
Listdestory(&phead);
}
int main()
{
test_pop_and_push();cout<< "------------" << endl;
test_find();cout<< "------------" << endl;
test_insert();cout<< "------------" << endl;
test_erase();cout<< "------------" << endl;
return 0;
}
链表(C++版)
最新推荐文章于 2024-08-09 10:25:03 发布
![](https://img-home.csdnimg.cn/images/20240711042549.png)