什么是数据结构
数据结构是计算机的内存中存储和组织数据的⽅式。
数据结构关注如何以最有效的⽅式组织和存储数据,以便于在计算机程序中进⾏操作和处理
为什么需要数据结构
程序中如果不对数据进⾏管理,可能会导致数据丢失、操作数据困难、野指针等情况。
通过数据结构,能够有效将数据组织和管理在⼀起。
按照我们的⽅式任意对数据进⾏增、删、改、查等操作
常⻅的数据结构分类
数据结构⼀般根据组织形式,分为:线性数据结构和⾮线性数据结构。
线性的数据结构有:数组(顺序表)、链表、栈和队列等。
⾮线性的数据结构有:树、散列表、堆、图等。
链表的概念
链表是⼀种线性数据结构,由⼀系列节点组成,每个节点包含数据和指向下⼀个节点的指针。
链表中的元素在内存中不必顺序排列,⽽是通过指针相互连接。
链表的结构
链表的基本结构由节点组成,每个节点包含数据和指向下⼀个节点的指针
//链表节点类型的声明
struct Node
{
int data;
Node* next;
};
链表的分类
链表可以分为单向链表、双向链表和循环链表。
- 单向链表:每个节点只有⼀个指针指向下⼀个节点。
- 双向链表:每个节点有两个指针,分别指向前⼀个节点和后⼀个节点
- 循环链表:尾节点指向头节点。
链表的结构⾮常多样,以下情况组合起来就有8种(2x2x2)链表结构:
动态申请链表节点和链表构建
动态申请节点并初始化
Node* createNode(int data)
{
Node* newNode = new Node;
newNode->data = data;
newNode->next = nullptr;
return newNode;
}
单链表元素的打印
打印链表的所有节点数据
void printList(Node* cur)
{
while (cur != nullptr)
{
cout << cur->data << "-->";
cur = cur->next;
}
cout << "nullptr" << endl;
cout << endl;
}
#include <iostream>
using namespace std;
struct Node
{
int data;
Node* next;
};
Node* createNode(int data)
{
Node* newNode = new Node;
newNode->data = data;
newNode->next = nullptr;
return newNode;
}
void printList(Node* cur)
{
while (cur != nullptr)
{
cout << cur->data << "-->";
cur = cur->next;
}
cout << "nullptr" << endl;
cout << endl;
}
int main()
{
Node* p1 = createNode(1);
Node* p2 = createNode(2);
Node* p3 = createNode(3);
Node* p4 = createNode(4);
p1->next = p2;
p2->next = p3;
p3->next = p4;
printList(p1);
return 0;
}
单链表的头部插⼊元素
在链表的头部插⼊节点
void PushFront(Node*& ph, int data)
{
Node* newNode = createNode(data);
newNode->next = ph;
ph = newNode;
}
#include <iostream>
using namespace std;
struct Node
{
int data;
Node* next;
};
Node* createNode(int data)
{
Node* newNode = new Node;
newNode->data = data;
newNode->next = nullptr;
return newNode;
}
void printList(Node* cur)
{
while (cur != nullptr)
{
cout << cur->data << "-->";
cur = cur->next;
}
cout << "nullptr" << endl;
cout << endl;
}
void PushFront(Node*& ph, int data)
{
Node* newNode = createNode(data);
newNode->next = pn;
ph = newNode;
}
int main()
{
Node* phead = nullptr;
PushFront(phead, 1);
PushFront(phead, 2);
PushFront(phead, 3);
PushFront(phead, 4);
printList(phead);
return 0;
}
单链表的尾部插⼊元素
在链表的尾部插⼊节点
void PushBack(Node*& phead, int x)
{
Node* newnode = createNode(x);
// 1、空链表
// 2、⾮空链表
if (phead == nullptr)
{
phead = newnode;
}
else
{
Node* tail = phead;
while (tail->next != nullptr)
{
tail = tail->next;
}
tail->next = newnode;
}
}
#include <iostream>
using namespace std;
struct Node
{
int data;
Node* next;
};
Node* createNode(int data)
{
Node* newNode = new Node;
newNode->data = data;
newNode->next = nullptr;
return newNode;
}
void printList(Node* cur)
{
while (cur != nullptr)
{
cout << cur->data << "-->";
cur = cur->next;
}
cout << "nullptr" << endl;
cout << endl;
}
void PushBack(Node*& phead, int x)
{
Node* newnode = createNode(x);
// 1、空链表
// 2、⾮空链表
if (phead == nullptr)
{
phead = newnode;
}
else
{
Node* tail = phead;
while (tail->next != nullptr)
{
tail = tail->next;
}
tail->next = newnode;
}
}
int main()
{
Node* phead = nullptr;
PushBack(phead, 1);
PushBack(phead, 2);
PushBack(phead, 3);
PushBack(phead, 4);
printList(phead);
return 0;
}
单链表头部删除元素
void PopFront(Node*& phead)
{
// 空
if (phead == nullptr)
{
cout << "链表为空,没有元素可以删除了" << endl;
return;
}
//⾮空
Node* tmp = phead;
phead = phead->next;
delete tmp;
tmp = nullptr;
}
#include <iostream>
using namespace std;
struct Node
{
int data;
Node* next;
};
Node* createNode(int data)
{
Node* newNode = new Node;
newNode->data = data;
newNode->next = nullptr;
return newNode;
}
void printList(Node* cur)
{
while (cur != nullptr)
{
cout << cur->data << "-->";
cur = cur->next;
}
cout << "nullptr" << endl;
cout << endl;
}
void PushBack(Node*& phead, int x)
{
Node* newnode = createNode(x);
// 1、空链表
// 2、⾮空链表
if (phead == nullptr)
{
phead = newnode;
}
else
{
Node* tail = phead;
while (tail->next != nullptr)
{
tail = tail->next;
}
tail->next = newnode;
}
}
void PopFront(Node*& phead)
{
// 空
if (phead == nullptr)
{
cout << "链表为空,没有元素可以删除了" << endl;
return;
}
//⾮空
Node* tmp = phead;
phead = phead->next;
delete tmp;
tmp = nullptr;
}
int main()
{
Node* phead = nullptr;
PushBack(phead, 1);
PushBack(phead, 2);
PushBack(phead, 3);
PushBack(phead, 4);
printList(phead);
//头部删除并打印
PopFront(phead);
printList(phead);
PopFront(phead);
printList(phead);
PopFront(phead);
printList(phead);
PopFront(phead);
printList(phead);
PopFront(phead);
printList(phead);
return 0;
}
单链表尾部删除元素
void PopBack(Node*& phead)
{
//空链表
if (phead == nullptr)
{
cout << "链表为空,没有元素可以删除了" << endl;
return;
}
// 1、⼀个节点
// 2、⼀个以上节点
if (phead->next == nullptr)
{
free(phead);
phead = nullptr;
}
else
{
// 找尾
Node* tail = phead;
while (tail->next->next != nullptr)
{
tail = tail->next;
}
free(tail->next);
tail->next = nullptr;
}
}
#include <iostream>
using namespace std;
struct Node
{
int data;
Node* next;
};
Node* createNode(int data)
{
Node* newNode = new Node;
newNode->data = data;
newNode->next = nullptr;
return newNode;
}
void printList(Node* cur)
{
while (cur != nullptr)
{
cout << cur->data << "-->";
cur = cur->next;
}
cout << "nullptr" << endl;
cout << endl;
}
void PushBack(Node*& phead, int x)
{
Node* newnode = createNode(x);
// 1、空链表
// 2、⾮空链表
if (phead == nullptr)
{
phead = newnode;
}
else
{
Node* tail = phead;
while (tail->next != nullptr)
{
tail = tail->next;
}
tail->next = newnode;
}
}
void PopBack(Node*& phead)
{
//空链表
if (phead == nullptr)
{
cout << "链表为空,没有元素可以删除了" << endl;
return;
}
// 1、⼀个节点
// 2、⼀个以上节点
if ((phead)->next == nullptr)
{
delete phead;
phead = nullptr;
}
else
{
// 找尾
Node* tail = phead;
while (tail->next->next != nullptr)
{
tail = tail->next;
}
delete tail->next;
tail->next = nullptr;
}
}
int main()
{
Node* phead = nullptr;
PushBack(phead, 1);
PushBack(phead, 2);
PushBack(phead, 3);
PushBack(phead, 4);
printList(phead);
//头部删除并打印
PopBack(phead);
printList(phead);
PopBack(phead);
printList(phead);
PopBack(phead);
printList(phead);
PopBack(phead);
printList(phead);
PopBack(phead);
printList(phead);
return 0;
}
释放链表的所有节点
当链表不再需要的时候,申请的节点资源最好能释放掉,否则可能带来内存泄漏的⻛险。所有我们再提供⼀个函数,释放链表的所有节点。其实这个就很简单了,我们调⽤⼀个删除元素的函数,直到把链表删除为空链表就释放了所有的节点。
void PopFront(Node* & ph)
{
// 空
if (ph == nullptr)
{
cout << "链表为空,没有元素可以删除了" << endl;
return;
}
//⾮空
Node* tmp = ph;
ph = ph->next;
delete tmp;
tmp = nullptr;
}
void DestropList(Node* & ph)
{
while(ph)
{
PopFront(ph);
}
}
#include <iostream>
using namespace std;
struct Node
{
int data;
Node* next;
};
Node* createNode(int data)
{
Node* newNode = new Node;
newNode->data = data;
newNode->next = nullptr;
return newNode;
}
void printList(Node* cur)
{
while (cur != nullptr)
{
cout << cur->data << "-->";
cur = cur->next;
}
cout << "nullptr" << endl;
cout << endl;
}
void PushBack(Node*& phead, int x)
{
Node* newnode = createNode(x);
// 1、空链表
// 2、⾮空链表
if (phead == nullptr)
{
phead = newnode;
}
else
{
Node* tail = phead;
while (tail->next != nullptr)
{
tail = tail->next;
}
tail->next = newnode;
}
}
void PopFront(Node*& ph)
{
// 空
if (ph == nullptr)
{
cout << "链表为空,没有元素可以删除了" << endl;
return;
}
//⾮空
Node* tmp = ph;
ph = ph->next;
delete tmp;
tmp = nullptr;
}
void DestropList(Node*& ph)
{
while(ph)
{
PopFront(ph);
}
}
int main()
{
Node* phead = nullptr;
PushBack(phead, 1);
PushBack(phead, 2);
PushBack(phead, 3);
PushBack(phead, 4);
printList(phead);
//释放链表
DestroyList(phead);
return 0;
}
⾯向对象的⽅式实现链表
#include <iostream>
using namespace std;
//节点类型声明
struct Node
{
int data;
Node* next;
};
struct List
{
//指向头节点的指针
Node* phead;
//成员函数
//构造函数
List()
{
cout << "构造函数调⽤" << endl;
phead = nullptr;
}
//析构函数 - 在结束时释放所有剩余节点
~List()
{
cout << "析构函数" << endl;
while (phead)
{
PopFront();
}
}
//创建节点
Node* createNode(int data)
{
Node* newNode = new Node;
newNode->data = data;
newNode->next = nullptr;
return newNode;
}
//打印链表
void printList()
{
Node* cur = phead;
while (cur != nullptr)
{
cout << cur->data << "-->";
cur = cur->next;
}
cout << "nullptr" << endl;
cout << endl;
}
//头部添加元素
void PushFront(int data)
{
Node* newNode = createNode(data);
newNode->next = phead;
phead = newNode;
}
//头部删除元素
void PopFront()
{
// 空
if (phead == nullptr)
{
cout << "链表为空,没有元素可以删除了" << endl;
return;
}
//⾮空
Node* tmp = phead;
phead = phead->next;
delete tmp;
tmp = nullptr;
}
//尾部添加元素
void PushBack(int x)
{
Node* newnode = createNode(x);
// 1、空链表
// 2、⾮空链表
if (phead == nullptr)
{
phead = newnode;
}
else
{
Node* tail = phead;
while (tail->next != nullptr)
{
tail = tail->next;
}
tail->next = newnode;
}
}
//尾部删除元素
void PopBack()
{
//空链表
if (phead == nullptr)
{
cout << "链表为空,没有元素可以删除了" << endl;
return;
}
// 1、⼀个节点
// 2、⼀个以上节点
if ((phead)->next == nullptr)
{
delete phead;
phead = nullptr;
}
else
{
// 找尾
Node* tail = phead;
while (tail->next->next != nullptr)
{
tail = tail->next;
}
delete tail->next;
tail->next = nullptr;
}
}
void DestropList()
{
while(phead)
{
PopFront();
}
}
};
int main()
{
List list;
list.PushBack(1);
list.PushBack(2);
list.PushBack(3);
list.PushBack(4);
list.printList();
//头部删除并打印
list.PopBack();
list.printList();
list.PopBack();
list.printList();
list.PopBack();
list.printList();
list.PopBack();
list.printList();
list.PopBack();
list.printList();
//头部添加元素
list.PushFront(1);
list.PushFront(2);
list.PushFront(3);
list.PushFront(4);
list.printList();
//头部删除
list.PopFront();
list.printList();
list.PopFront();
list.printList();
return 0;
}