链表
链表是一种线性表,是数据结构中的一种。在内存中是一种非连续性的存储结构,数据元素的逻辑是依靠指针来实现链接。所以,链表不支持随机访问,和另一种数据结构数组时不同的。但是比数组好的一点是她在插入删除中会非常高效。数组在这方面不如链表理想。

链表包括数据域和指针
初始化头结点
在C++的构造函数里面对头指针进行初始化:
Link::Link()
{
head = new Node;
head->_val = -1;
head->_next = NULL;
}
插入节点
需要先new一个新节点cur出来,然后将cur的next指针指向head->next的地址,最后再将head->next指向cur。

删除节点
先遍历到指定节点的前一个节点,然后将next指针指向被删除的节点的next。然后delete那个悬空节点。

修改节点的值
先遍历找到节点,然后将data修改就可以了。

查找节点
通过遍历节点找到相应的节点。
链表反转
需要创建三个指针,分别指向第一个第二个第三个节点,将第一个结点的指针指向NULL,然后把第二个结点指向第一个结点,用第三个节点进行遍历,依次修改节点的next指针。

完整代码:
#include <iostream>
using namespace std;
class Node
{
public:
int _val;
Node* _next;
};
class Link
{
private:
Node* head;
public:
Link(); //构造函数
~Link(); //析构函数
int CreateLink(int n); // 创建链表
int getLength(); //获取链表长度
bool isEmpty(); //判断是否为空表
void insert(const int& data); // 尾部插入元素
void insertAthead(const int& data); // 头部插入元素
void insert_pos(const int& pos, const int& data); // 按位置插入元素
void erase(const int& data); //删除指定数据
void eraseAthead(); //删除头结点
void eraseAtEnd(); //删除尾结点
int update(const int& n, const int& data); //修改指定位置的数据
void reverse(); //反转链表
void print(); //打印链表
int find_pos(const int& data); //查找数据下标
int find(const int& n); //查找第n个元素是什么
void destory(); //销毁链表
};
Link::Link()
{
head = new Node;
head->_val = -1;
head->_next = NULL;
}
Link::~Link()
{
cout << "下次再见!" << endl;
}
// 创建链表
int Link::CreateLink(int n) {
if (n < 0) return -1;
Node* ptr, * tmp;
ptr = head;
for (int i = 0; i < n; ++i) {
cout << "请输入链表第" << i + 1 << "的值" << endl;
tmp = new Node;
cin >> tmp->_val;
ptr->_next = tmp;
tmp->_next = NULL;
ptr = tmp;
}
return 0;
}
//销毁链表
void Link::destory() {
if (head == NULL || head->_next == NULL) {
cout << "链表为空!" << endl;
return;
}
else {
// 从头结点的下一个开始销毁
Node* ptr = head->_next;
while (ptr->_next != NULL) {
Node* tmp = ptr->_next;
delete ptr;
ptr = tmp;
}
}
}
//获取链表长度
int Link::getLength() {
if (head == NULL) return 0;
Node* ptr = head->_next;
// 从头结点的下一个开始计算
int sum = 0;
while (ptr != NULL) {
ptr = ptr->_next;
++sum;
}
return sum;
}
//判断是否为空表,空表返回false,非空返回true
bool Link::isEmpty() {
if (head->_next == NULL) return false;
return true;
}
// 尾部插入元素
void Link::insert(const int& data) {
if (head == NULL || head->_next == NULL) {
cout << "链表为空!" << endl;
return;
}
// 创建结点将值赋给新节点
Node* ptr = new Node;
ptr->_next = NULL;
ptr->_val = data;
Node* p = head;
while (p->_next != NULL) {
p = p->_next;
}
p->_next = ptr;
}
// 头部插入元素
void Link::insertAthead(const int& data) {
if (head == NULL || head->_next == NULL) {
cout << "链表为空!" << endl;
return;
}
else {
Node* ptr = head;
Node* p = new Node;
p->_val = data;
p->_next = ptr->_next;
ptr->_next = p;
cout << "插入成功!" << endl;
}
}
// 按位置插入
void Link::insert_pos(const int& pos, const int& data) {
if (pos < 1 || getLength() < pos) {
cout << "插入位置有误!" << endl;
return;
}
Node* ptr = head;
int i = 0;
while (i < pos && ptr->_next != NULL) {
ptr = ptr->_next;
++i;
}
Node* tmp = new Node;
tmp->_val = data;
Node* cur = ptr->_next;
tmp->_next = cur;
ptr->_next = tmp;
cout << "插入成功!" << endl;
}
//删除指定数据
void Link::erase(const int& data) {
if (!isEmpty()) {
cout << "链表为空!无法删除!" << endl;
return;
}
else {
Node* ptr = head->_next,*cur;
while (ptr->_next != NULL) {
if (ptr->_next->_val == data) {
cur = ptr->_next->_next;
ptr->_next = cur;
}
else {
ptr = ptr->_next;
}
}
if (ptr->_val == data) {
eraseAtEnd();
}
}
}
//删除头结点
void Link::eraseAthead() {
if (head == NULL || head->_next == NULL) {
cout << "链表为空!" << endl;
}
else {
Node* ptr = head->_next;
Node* p = head->_next->_next;
delete ptr;
head->_next = p;
}
}
//删除尾结点
void Link::eraseAtEnd() {
if (head == NULL || head->_next == NULL)
{
cout << "链表为空!" << endl;
}
else {
Node* ptr = head;
Node* cur = NULL;
while (ptr->_next != NULL) {
cur = ptr;
ptr = ptr->_next;
}
delete ptr;
ptr = NULL;
cur->_next = NULL;
}
}
//修改指定位置的数据
int Link::update(const int& n, const int& data) {
if (!isEmpty()) {
cout << "链表为空,无法修改" << endl;
return -1;
}
//长度不到n无法修改
else if(n < 0 || n > getLength()){
cout << "该位置没有元素,无法修改!" << endl;
return -1;
}
else {
int i = 1;
Node* ptr = head;
while (i <= n) {
ptr = ptr->_next;
i++;
}
ptr->_val = data;
}
return 0;
}
//反转链表
void Link::reverse() {
if (head == NULL || head->_next == NULL) {
cout << "链表为空!" << endl;
return;
}
// 头结点后的是哪个结点为了进行反转
Node* ptr = head->_next;
Node* cur = head->_next->_next;
Node* tmp = head->_next->_next->_next;
// 第二个指针指向第一个结点,然后结点互相换位置
ptr->_next = NULL;
while (tmp != NULL) {
cur->_next = ptr;
ptr = cur;
cur = tmp;
tmp = tmp->_next;
}
// 将尾结点指向倒数第二个结点
cur->_next = ptr;
// 修改头结点位置
head->_next = cur;
}
//打印链表
void Link::print() {
if (!isEmpty()) {
cout << "链表为空!" << endl;
return;
}
else {
Node* ptr = head;
while (ptr->_next != NULL) {
cout << ptr->_val << "->";
ptr = ptr->_next;
}
cout << ptr->_val << endl;
}
}
//查找数据下标
int Link::find_pos(const int& data) {
Node* ptr = head;
if (!isEmpty()) {
cout << "链表为空!" << endl;
return 0;
}
else {
int i = 0;
//
while (ptr != NULL) {
if (ptr->_val == data) {
return i;
}
ptr = ptr->_next;
++i;
}
}
return 0;
}
//查找第n个元素是什么
int Link::find(const int& n) {
if (n < 1 || n > getLength()) {
return -1;
}
Node* ptr = head;
int i = 1;
while (i <= n) {
ptr = ptr->_next;
++i;
}
return ptr->_val;
}
void menu() {
cout << "*********************链表菜单*********************" << endl;
cout << "1、创建链表 2、尾部插入数据 " << endl;
cout << "3、头部插入 4、任意插入数据 " << endl;
cout << "5、删除头结点 6、删除尾结点 " << endl;
cout << "7、任意删除元素 8、销毁链表 " << endl;
cout << "9、查找位置 10、查找元素 " << endl;
cout << "11、链表长度 12、链表是否为空" << endl;
cout << "13、修改元素 14、反转链表 " << endl;
cout << "0、退出 " << endl;
cout << "**************************************************" << endl;
}
int main(void) {
Link l;
while (1) {
//system("cls"); //这个会清空显示的屏幕,可选择性使用。
menu();
int data;
int n;
cout << "请输入选项:";
cin >> n;
if (n == 0) {
break;
}
switch (n)
{
//创建链表
case(1):
cout << "请输入需要创建链表的长度:";
int a;
cin >> a;
l.CreateLink(a);
l.print();
break;
//尾部插入元素
case(2):
cout << "请输入需要添加的元素:";
cin >> data;
l.insert(data);
l.print();
break;
//头部插入
case(3):
cout << "请输入需要添加的元素:";
cin >> data;
l.insertAthead(data);
l.print();
break;
//任意位置插入元素
case(4):
cout << "请输入需要添加的元素:";
cin >> data;
cout << "请输入需要插入的位置:";
cin >> n;
l.insert_pos(n, data);
l.print();
break;
//删除头结点
case(5):
cout << "原链表为:";
l.print();
cout << "删除头结点之后链表为:";
l.eraseAthead();
l.print();
break;
//删除尾结点
case(6):
cout << "原链表为:";
l.print();
cout << "删除尾结点之后链表为:";
l.eraseAtEnd();
l.print();
break;
//任意位置删除
case(7):
cout << "原链表为:";
l.print();
cout << "请输入需要删除的元素:";
cin >> data;
cout << "删除元素之后链表为:";
l.erase(data);
l.print();
break;
//销毁链表
case(8):
l.destory();
cout << "销毁链表!程序结束!" << endl;
system("pause");
return 0;
//查找位置
case(9):
cout << "请输入需要查找的位置:";
cin >> n;
if (l.find(n) != -1) {
cout << "第" << n << "个位置元素为:" << l.find(n) << "!" << endl;
}
else {
cout << "该位置没有元素!" << endl;
}
break;
//查找元素
case(10):
cout << "请输入需要查找的元素:";
cin >> data;
if (l.find_pos(data) > 0) {
cout << "元素" << data << "在第" << l.find_pos(data) << "个位置!" << endl;
}
else {
cout << "该元素不在链表里面!" << endl;
}
break;
//链表长度
case(11):
cout << "链表长度为:" << l.getLength() << endl;
break;
//链表是否为空
case(12):
if (l.isEmpty()) {
cout << "链表不为空!" << endl;
l.print();
}
else {
cout << "链表为空!" << endl;
}
break;
//修改元素
case(13):
cout << "原链表为:";
l.print();
cout << "请输入需要修改的链表位置:";
cin >> n;
cout << "请输入需要修改的链表元素元素:";
cin >> data;
if (l.update(n, data) != 0) {
break;
}
cout << "修改成功!修改之后的链表为:";
l.print();
break;
case(14):
cout << "原链表为:";
l.print();
cout << "反转链表之后:";
l.reverse();
l.print();
break;
default:
cout << "输入有误!" << endl;
break;
}
}
system("pause");
return 0;
}
本文介绍了链表的基本概念,强调了链表作为数据结构在内存中的非连续性存储特性,并对比了与数组的区别。文章详细阐述了在C++中如何初始化头结点、插入节点、删除节点、修改节点值、查找节点以及反转链表的操作,并提供了完整的代码示例。
5393

被折叠的 条评论
为什么被折叠?



