目录
前言
1.学习数据结构需要的知识点
记录下线性表的顺序结构的表示和实现
。学习数据结构需要具备一些C++的一些知识,这样学习起来会更快一点,这里知识简单的罗列下,想要更深入的学习,请自行百度之。
1.结构体
简单的来说,结构提就是一种自定义的类型,把需要使用到的不同类型的数据元素组合在一起。
结构体的定义格式如下:
struct 结构体名称{
结构体所包含的变量;
}
例如我们使用结构体定义一个学生相关的数据类型。这个结构体中包含了学生姓名、年龄、学号信息。
#include <string>
using namespace::std;
struct Student{
string studentName;//学生姓名
int age;//学生年龄
int studentNO;// 学号
};
C++中的结构体也支持使用构造函数初始化,这里就不写构造函数的代码了,个人习惯不同,我们一般在类中使用构造函数。
使用的时候先实例化一下,代码如下:
#include <iostream>
#include <string>
using namespace::std;
struct Student{
string studentName;//学生姓名
int age;//学生年龄
int studentNO;// 学号
};
int main(int argc, const char * argv[]) {
Student stu = {"张三",20,111};
cout<<"学生姓名:"<<stu.studentName<<"\t学生年龄:"<<stu.age<<"\t学生学号:"<<stu.studentNO<<endl;
return 0;
}
2.typedef关键字
C++中我们可以使用typedef给关键字起别名。
最简单的例子就是给基本数据类型起别名,类似如下代码:
我们给int类型起了一个新的名字,ElementType,在代码中就可以使用ElementType代替Int。
typedef int ElementType;
当然typedef也可以和struct一起使用。例如在上面的例子中,我们可以给结构体Student起一个别名Stu,在代码中,我们可以使用Stu代替Student来使用。
typedef struct Student{
string studentName;//学生姓名
int age;//学生年龄
int studentNO;// 学号
Student(){
studentName = "";
age = 0;
studentNO = 0000000000;
}
}Stu;
3.指针
指针就是地址,指向内存中的一块存储空间。C++中使用&表示取地址符。例如在下面的代码中,我们使用&取地址符就可以打印出variable变量在内存中的地址。
int variable = 12;
std::cout<<"variable在内存中的地址为:"<<&variable<<endl;
C++中,我们使用*声明一个指针变量,它的值为另一个变量在内存中的地址。
例如在下面的例子中:指针变量p存储了variable的地址,我们在控制台打印p和&variable会发现这两个值是相同的。
int variable = 12;
int * p = &variable;
函数中指针可以作为参数传递,但我们在函数中传递指针的时候,使用&获取指针的地址。
指针使用完成之后,要记得调用free函数释放。
4.一些常用的函数
在数据结构的学习中,我们动态分配存储空间的时候,需要使用malloc和sizeof函数。
malloc的全称是memory allocation。中文名称动态内存分配,用于申请一块连续的指定大小的内存区域,返回值为分配的内存区域地址。
sizeof用来计算我们自定义的数据类型占用的内存空间的大小。
2.什么是顺序表
1.数据结构的概念
数据结构是计算机科学中的基础概念之一,用于组织和管理数据。数据指的是在计算机科学中用来表示信息的基本单位。数据结构是在计算机中用于组织和存储数据的方式。
2.数据结构分类
数据结构的分类可以根据多种维度。以下是常见的分类方式:
1.逻辑结构
逻辑结构是从逻辑关系上描述数据的,它与数据的存储无关,是独立于计算机的。逻辑结构可以分为以下四种基本类型:
- 集合结构:数据元素之间除了“同属于一个集合”的关系外,没有其他关系。
- 线性结构:数据元素之间存在一对一的关系。常见的线性结构有数组、链表、栈和队列等。
- 树形结构:数据元素之间存在一对多的关系。常见的树形结构有普通树、二叉树等。
- 网状结构:数据元素之间存在多对多的关系。
2.物理结构(存储结构)
物理结构或存储结构是指数据的逻辑结构在计算机中的表示(又称映像)。它包括数据元素的表示和关系的表示。物理结构主要有两种:
- 顺序存储结构:把数据元素存放在地址连续的存储单元里,其数据间的逻辑关系和物理关系是一致的。例如,数组就是顺序存储结构。
- 链式存储结构:把数据元素存放在任意的存储单元里,这组存储单元可以是连续的,也可以是不连续的。数据元素的存储关系并不能反映其逻辑关系,因此需要用一个指针存放数据元素的地址,这样通过地址就可以找到相关联的数据元素。链表是典型的链式存储结构。
3.其他分类
除了上述两种主要的分类方式,数据结构还可以根据其他特性进行分类,如:
- 静态数据结构:在程序执行过程中,结构中的元素个数和元素间的关系保持不变的数据结构。
- 动态数据结构:在程序执行过程中,结构中的元素个数或元素间的关系可按有关操作进行改变的数据结构。
- 线性数据结构:数据元素之间存在一对一关系的数据结构,如前所述的线性表、栈、队列、双队列、数组、串等。
- 非线性数据结构:数据元素之间存在一对多或多对多关系的数据结构,如前所述的树(二叉树等)、图等。
3.顺序表的概念
顺序表是用一段地址连续的存储单元依次存储线性表的数据元素。在顺序表中,数据元素之间的逻辑关系由元素的存储位置(下标)来决定,即其逻辑上相邻的数据元素在物理位置上也是相邻的。简单来说,顺序表就是线性表的顺序存储结构。
顺序表一般具有以下特点:
-
元素存储地址连续:顺序表中的元素在内存中是连续存放的,因此可以通过计算元素的下标来直接定位元素的存储位置。
-
随机访问特性:由于顺序表元素存储地址连续,所以可以通过下标快速访问任意位置的元素,这种特性使得顺序表在查找操作中具有很高的效率。
-
存储空间预分配:创建顺序表时,通常需要预先分配一段连续的存储空间。如果表的大小是静态的,即不经常变动,那么可以预先分配固定大小的数组来存储元素。如果表的大小是动态的,则需要动态地分配和释放存储空间。
-
插入和删除操作可能需要移动元素:在顺序表中插入或删除元素时,可能需要移动元素以保证存储空间的连续性。特别是在表的中间或前面插入元素时,需要移动较多的元素,因此这些操作的时间复杂度较高。
-
存储空间利用率可能不高:如果顺序表的大小设置得过大,而实际存储的元素较少,那么会造成存储空间的浪费。反之,如果顺序表的大小设置得过小,又可能导致频繁地重新分配和移动元素,降低效率。
顺序表在内存中使用一段连续的存储空间来存储数据元素,因此它适合于存储规模不大且数据元素变动不频繁的线性表。当线性表的长度变化不大而且事先知道其大小时,采用顺序表作为存储结构可以节约存储空间。然而,当线性表长度变化较大或者频繁进行插入和删除操作时,链式存储结构可能更为合适。
2.顺序表的表示和实现
线性表的顺序存储结构指的是使用内存中一块连续的存储空间来存储顺序表。顺序表的存储结构示意图如下:
图1.线性表的顺序存储结构
C++中我们可以使用数组来存储顺序表中数据元素。由于数组有静态数组和动态数组,依次顺序表的表示和实现也有两种,我们可以使用静态数组来存储线性表中的数据元素,也可以使用动态数组来动态的给数据元素分配存储空间。
1.线性表的静态分配顺序存储结构
这里我分别使用C++和C语言实现了顺序表的动态存储。
1.C语言实现
C语言的实现看这篇文章。
2.C++实现
C++的实现看这篇文章。
2.顺序表的动态分配顺序存储结构
这里我分别使用C++和C语言实现了顺序表的动态存储。
1.C语言实现
C语言的实现看这篇文章。
2.C++实现
C++的实现看这篇文章。
3.线性链表
线性表的链式存储结构的特点是用一组任意的存储单元存储线性表的数据元素(这组存储单元可以是连续的,也可以是不连续的)。线性链表的数据元素除了存储本身存储的信息之外,还保存下一个数据元素的地址。其中存储数据元素信息的域称为数据域,存储直接后继存储位置的域称为指针域名。
线性链表的逻辑状态如下所示:
1.单链表
线性表的链式存储结构的特点是用一组任意的存储单元存储线性表的数据元素(这组存储单元可以是连续的,也可以是不连续的)。线性链表的数据元素除了存储本身存储的信息之外,还保存下一个数据元素的地址。其中存储数据元素信息的域称为数据域,存储直接后继存储位置的域称为指针域名。
单链表的逻辑结构如下:
单链表是一种非随机存取的存储结构。
1.C语言实现
C语言的实现看这篇文章。
2.C++实现
C++的实现看这篇文章。
2.双向链表
以上讨论的链式存储结构的结点中只有一个指示直接后继的指针域,由此,从某个结点出发只能顺指针往后寻查其他结点。若要寻查结点的直接前趋,则需从表头指针出发。换句话说,在单链表中,NextElem 的执行时间为 O(1),而 PriorElem 的执行时间为O(n)。为克服单链表这种单向性的缺点,可利用双向链表(double linked list)。
顾名思义,在双向链表的结点中有两个指针域,其一指向直接后继,另一指向直接前趋,在C语言中可描述如下:
// 定义双向链表
typedef struct DNode {
int data; // 数据域
struct DNode * next; // 直接后继
struct DNode * prior;// 直接前驱
}DoubleNode,*DoubleLinkList;
对于双向链表和单链链表的区别在于删除和插入的时候指针修改情况。
1.C语言实现
C语言的实现看这篇文章。
2.C++实现
C语言的实现看这篇文章。
3.循链表
循环链表(circular linked list)是另一种形式的链式存储结构。它的特点是表中最后一个结点的指针域指向头结点,整个链表形成一个环。由此,从表中任一结点出发均可找到表中其他结点,如图 2.12所示为单链的循环链表。类似地,还可以有多重链的循环链表。
1.C语言实现
C语言的实现看这篇文章。
2.C++实现
C++的实现看这篇文章。