CPP学习之——动态链表(15.4-6)

一 概述

链表结果也可以是动态地分配存储的,即在需要时才开辟结点的存储空间,实现动态链接

二 使用场景

或者说当程序运行起来的时候,假设这个程序时图书管理程序,某个用户点击了创建新书,这时才会创建一个新书结点,而用户点击删除图书的时候,才会删除某个图书结点,这就是动态的创建和删除,那么我们如何实现动态的创建和删除结点呢?

三 动态创建和删除结点

3.1 代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include<iostream>
#include<stdio.h>
#include<stdlib.h>
using namespace std;
struct book
{
int num;
float price;
struct book *next;
};
int main()
{
//方式一
void *p=malloc(sizeof(book));
free(p);
//方式二
book *p1=new book;
delete p1;
return 0;
}

3.2 代码说明

  • 在C语言中用mallc函数来开辟,用free来释放
  • 上面两种方式的区别是:第一种方式是标准库函数,第二种是C++的操作符
  • 由于malloc和free函数产生于C语言时代,因此不可用在C++的对象中,因为对象的产生要调用构造函数,消亡要调用析构函数。malloc和free函数无法满足这两个基本要求
  • 一般来说在C++中由于有了new 和delete,malloc和free函数就不再使用了,所以我们接下来堆动态链表的操作红将只使用new和delete

四 创建动态链表

4.1 概念

建立一个动态链表就是在程序运行时根据用户的输入从无到有依次建立起一个表格。这个表格中的数据都依次保存在各个结点上,每个结点都是用new操作符来动态开辟,结点与结点之间用指针next相关联

4.2 需求

比如说我们要建立一个图书管理表,那么我们首先要声明两个变量——图书编号num和价格price

4.3 代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
#include<iostream>
#include<cstring>
#include<stdio.h>
#include<stdlib.h>
using namespace std;
class book
{
public:
int num;
float price;
book *next;
};
book *head = NULL;
bool check(string str)
{
for (int i = 0; i < str.length(); i++)
{
if ((str[i] > '9' || str[i] < '0') && (str[i] != '.'))
return false;
}
return true;
}
book* create()
{
book *p1, *p2;
p1 = new book;
head = p1;
p2 = p1;
cout << "请输入图书的编号,以0结束" << endl;
string str;
cin >> str;
while (!check(str))
{
cout << "输入的不是数字,请重新输入,按0返回" << endl;
cin >> str;
}
p1->num = atoi(str.c_str());
//cin>>p1->num;
if (p1->num != 0)
{
cout << "请输入图书的价格" << endl;
cin >> str;
while (!check(str))
{
cout << "输入的不是数字,请重新输入,按0返回" << endl;
cin >> str;
}
p1->price = atof(str.c_str());
//cin>>p1->price;
} else
{
delete p1;
p2 = NULL;
p2->next = NULL;
head = NULL;
return head;
}
while (p1->num != 0)
{
p2 = p1;
p1=new book;
cout << "请输入图书的编号,以0结束" << endl;
cin >> str;
while (!check(str))
{
cout << "输入的不是数字,请重新输入,按0返回" << endl;
cin >> str;
}
p1->num = atoi(str.c_str());
//cin >> p1->num;
if (p1->num != 0)
{
cout << "请输入图书的价格" << endl;
cin >> str;
while (!check(str))
{
cout << "输入的不是数字,请重新输入,按0返回" << endl;
cin >> str;
}
p1->price = atof(str.c_str());
//cin >> p1->price;
}
p2->next = p1;
}
delete p1;
p2->next = NULL;
return head;
}
int main()
{
create();
return 0;
}

4.4 输出结果

1
2
3
4
5
6
7
8
9
10
11
12
请输入图书的编号,以0结束
s
输入的不是数字,请重新输入,按0返回
1
请输入图书的价格
11
请输入图书的编号,以0结束
2
请输入图书的价格
22
请输入图书的编号,以0结束
0

4.5 说明

  • book类中声明了指向下一个结点的next指针,声明一个head头指针,并将它初始化为0,目的是避免它成为野指针,然后我们建立一个返回book类指针的create函数,在函数体内我们声明两个指向book类的指针p1和p2,p1作为本节点的指针,p2作为下一个结点的指针
  • 首先我们新建一个结点,用p1和p2来指向该结点,由头指针head来指向它
  • 假如用户输入一个字符,while循环将无法对其判断,从而导致死循环,解决办法就是自己编写一个返回布尔型的函数,该函数用来检测用户输入是不是字符,是则返回假,不是则返回真