🚀 写在最前:在前面两篇文章中,了解了数据结构到底在学什么以及知道了程序=数据结构+算法这个思想,了解了如何评价算法的五大特性,如何评价一个算法的好坏,以及两个评价指标的计算,而今天我们开始学习第一个数据结构。
🚀 :点个关注吧😀,让我们一起探索计算机的奥秘!
目录
🍟线性表的定义和基本操作
首先先来看下在第一章中了解的一些数据结构的知识,逻辑结构面向我们人自己设计出来的抽象结构,物理结构面向计算机的存储系统,是逻辑结构实际存储在计算里的结构。
线性表属于逻辑结构,先来了解这个逻辑结构是什么样,这个逻辑结构具体在计算中的存储,在后面会学习到线性表的顺序存储(顺序表)、线性表的链式存储(链表)。
🍟线性表的定义
🚀🚀线性表的官方定义:线性表是具有相同数据类型的n个数据元素的有限序列,其中n为表长,若n为0,则此时线性表称为空表。简单理解就是把有限个相同类型的数据串成一个串就是线线性表,如下图所示,4个相同类型的数据串成一串成为一个线性表,对于线性表来说,除第一个元素外,每一个元素都有直接后继,除最后一个元素外,每一个元素都有直接前驱。
🍟线性表的操作
定义好了一个数据类型——线性表,就必须为这种数据类型匹配上相关的操作。常见的就是以下几种操作
-
InitList(&L); //初始化链表
-
DestoryList(&L); //销毁列表
-
ListInsert(&L,i,e): //插入操作,在列表第i位置上插入
-
ListDelete(&L,i,e): //删除操作,在列表第i位置上删除
-
GetElem(L,i); //按位查找,获取第i个位置上的元素
-
LocateElem(L,e); //按值查找,获取元素e
-
Length(L); //获取线性表的长度
-
PrintList(L); //打印列表
-
Empty(L); //判断线性表是否为空
🚀🚀至此,给出了线性表这个数据结构,以及这个数据结构的相关操作,接下去我们就得依次在计算机中来实现这些操作,需要注意的是,由于线性表这个数据结构是我们人为定义的逻辑结构,而这些逻辑具体在计算中存储方式的不同就会造成存储结构不同,从而对于数据结构的操作具体实现也会不同,下面看线性表在计算机中采用顺序存储,即简称顺序表它的一些操作实现。
🍗🍗线性表的顺序存储(顺序表)
如下图所示,就是一个线性表在计算机中的顺序存储,逻辑相邻,实际物理地址也相邻。
🍗文件结构
以下操作,都以静态分配内存为例
🍗线性表的顺序存储——初始化
InitList(&L); //初始化链表
LinerList.h中的内容,在这里实际定义数据结构以及数据结构的操作。
#pragma once
#include<stdio.h>
#include<stdlib.h>
#define maxsize 100
typedef int ElementType; //重定义元素类型为ElementType
//定义线性表类型,使用静态分配内存
typedef struct StaticLinerList {
ElementType data[maxsize]; //线性表的大小
int length; //记录线性表的长度
}SLinerList;
//线性表的操作
//初始化线性表
void InitList(SLinerList &L);
LinerList.c中的内容,在这里实际实现数据结构的操作
#include "LinerList.h"
//初始化线性表
void InitList(SLinerList& L) {
L.length = 0; //将线性表的长度置为空
}
test.c中的内容,测试实现的数据结构是否好用
#include"LinerList.h"
int main() {
SLinerList SL1; //定义一个线性表SL1
//将线性表SL1进行初始化操作
InitList(SL1);
printf("现在线性表的长度为%d", SL1.length);
return 0;
}
测试结果:
现在线性表的长度为0
D:\C_WorkSpace\LinerList\x64\Debug\LinerList.exe (进程 20920)已退出,代码为 0。
要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口. . .
🍗线性表的顺序存储——销毁
DestoryList(&L); //销毁列表
LinerList.h中的内容
#pragma once
#include<stdio.h>
#include<stdlib.h>
#define maxsize 100
typedef int ElementType; //重定义元素类型为ElementType
//定义线性表类型,使用静态分配内存
typedef struct StaticLinerList {
ElementType data[maxsize]; //线性表的大小
int length; //记录线性表的长度
}SLinerList;
//线性表的操作
//初始化线性表
void InitList(SLinerList &L);
//线性表的销毁
void DestroyList(SLinerList &L);
LinerList.c中的内容
#include "LinerList.h"
//初始化线性表
void InitList(SLinerList &L) {
L.length = 0; //将线性表的长度置为空
}
//销毁线性表
void DestroyList(SLinerList &L)
{
L.length = 0; //将线性表的长度置为空,即就是销毁了线性表
}
test.c中的内容
#include"LinerList.h"
int main() {
SLinerList SL1; //定义一个线性表SL1
InitList(SL1); //将线性表SL1进行初始化操作
SL1.length = 3;
printf("线性表销毁前长度为%d\n", SL1.length);
DestroyList(SL1); //将线性表SL1进行销毁操作
printf("线性表销毁前长度为%d\n", SL1.length);
return 0;
}
运行结果:
线性表销毁前长度为3
线性表销毁前长度为0
D:\C_WorkSpace\LinerList\x64\Debug\LinerList.exe (进程 20528)已退出,代码为 0。
要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口. . .
🍗线性表的顺序存储——求表长
Length(L); //获取线性表的长度
LinerList.h中的内容
//获取表长
int Length(SLinerList L);
LinerList.c中的内容
//获取表长
int Length(SLinerList L) {
return L.length;
}
test.c中的内容
#include"LinerList.h"
int main() {
SLinerList SL1; //定义一个线性表SL1
InitList(SL1); //将线性表SL1进行初始化操作
SL1.length = 3;
printf("线性表销毁前长度为%d\n", SL1.length);
DestroyList(SL1); //将线性表SL1进行销毁操作
printf("线性表销毁前长度为%d\n", SL1.length);
int SL1_length = Length(SL1); //获取表长
printf("线性表当前长度为%d\n", SL1.length);
return 0;
}
运行结果:
线性表销毁前长度为3
线性表销毁前长度为0
线性表当前长度为0
D:\C_WorkSpace\LinerList\x64\Debug\LinerList.exe (进程 9764)已退出,代码为 0。
要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口. . .
🍗 线性表的顺序存储——判空
Empty(L); //判断线性表是否为空
LinerList.h中的内容
//判断表是否为空
bool Empty(SLinerList L);
LinerList.c中的内容
//判空
bool Empty(SLinerList L)
{
if (L.length == 0) {
return true;
}
else
{
return false;
}
}
test.c中的内容
#include"LinerList.h"
int main() {
SLinerList SL1; //定义一个线性表SL1
InitList(SL1); //将线性表SL1进行初始化操作
SL1.length = 3;
printf("线性表销毁前长度为%d\n", SL1.length);
DestroyList(SL1); //将线性表SL1进行销毁操作
printf("线性表销毁前长度为%d\n", SL1.length);
int SL1_length = Length(SL1); //获取表长
printf("线性表当前长度为%d\n", SL1.length);
if (Empty(SL1)) { //判空
printf("线性表为空\n");
}
else {
printf("线性表不为空\n");
}
return 0;
}
运行结果:
线性表销毁前长度为3
线性表销毁前长度为0
线性表当前长度为0
线性表为空
D:\C_WorkSpace\LinerList\x64\Debug\LinerList.exe (进程 16848)已退出,代码为 0。
要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口. . .
🍗线性表的顺序存储——插入
ListInsert(&L,i,e): //插入操作,在列表第i位置上插入
LinerList.h中的内容
//插入操作,在列表第i位置上插入元素e
bool ListInsert(SLinerList &L, int i, ElementType e);
LinerList.c中的内容
//插入操作,在列表第i位置上插入元素e
bool ListInsert(SLinerList& L, int i, ElementType e)
{
//判断插入位置的合法性
if (i<1 || i>L.length + 1) {
printf("插入位置不合法\n");
return false;
}
//判断空间是否足够
else if (L.length >= maxsize) {
printf("线性表空间不够\n");
return false;
}
else {
//将i位置之后的元素全部后移一位
for (int j = L.length; j > i - 1; j--) {
L.data[j] = L.data[j - 1];
}
//空出i位置,插入元素
L.data[i - 1] = e;
//线性表长度++
L.length++;
return true;
}
}
test.c中的内容
#include"LinerList.h"
int main() {
SLinerList SL1; //定义一个线性表SL1
InitList(SL1); //将线性表SL1进行初始化操作
SL1.length = 3;
printf("线性表销毁前长度为%d\n", SL1.length);
DestroyList(SL1); //将线性表SL1进行销毁操作
printf("线性表销毁前长度为%d\n", SL1.length);
int SL1_length = Length(SL1); //获取表长
printf("线性表当前长度为%d\n", SL1.length);
if (Empty(SL1)==true) { //判空
printf("线性表为空\n");
}
else {
printf("线性表不为空\n");
}
ElementType e = 2;
if (ListInsert(SL1, 1, e) == true) { //按位置插入元素
printf("插入成功\n");
}
else {
printf("插入失败\n");
}
return 0;
}
运行结果:
线性表销毁前长度为3
线性表销毁前长度为0
线性表当前长度为0
线性表为空
插入成功
D:\C_WorkSpace\LinerList\x64\Debug\LinerList.exe (进程 12568)已退出,代码为 0。
要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口. . .
🍗线性表的顺序存储——删除
ListDelete(&L,i,&e): //删除操作,在列表第i位置上删除
LinerList.h中的内容
//删除操作,在列表第i位置上删除
bool ListDelete(SLinerList& L, int i, ElementType &e);
LinerList.c中的内容
//删除操作,在列表第i位置上删除
bool ListDelete(SLinerList& L, int i, ElementType &e)
{
//判断删除位置是否合法
if (i<1 || i>L.length) {
printf("删除位置不合法\n");
return false;
}
else {
e = L.data[i - 1]; //返回被删除元素
//将i位置处的后面元素都前移动
for (int j = i - 1; j < L.length - 1; j++) {
L.data[j] = L.data[j+1];
}
//线性表长度--
L.length--;
return true;
}
}
test.c中的内容
#include"LinerList.h"
int main() {
SLinerList SL1; //定义一个线性表SL1
InitList(SL1); //将线性表SL1进行初始化操作
SL1.length = 3;
printf("线性表销毁前长度为%d\n", SL1.length);
DestroyList(SL1); //将线性表SL1进行销毁操作
printf("线性表销毁前长度为%d\n", SL1.length);
int SL1_length = Length(SL1); //获取表长
printf("线性表当前长度为%d\n", SL1.length);
if (Empty(SL1)==true) { //判空
printf("线性表为空\n");
}
else {
printf("线性表不为空\n");
}
ElementType e = 2;
if (ListInsert(SL1, 1, e) == true) { //按位置插入元素
printf("插入成功,插入的元素为%d\n", e);
}
else {
printf("插入失败\n");
}
ElementType delete_ele;
if (ListDelete(SL1, 1, delete_ele)==true) {
printf("删除成功,删除的元素为%d\n", delete_ele);
}
else {
printf("删除失败!\n");
}
return 0;
}
运行结果:
线性表销毁前长度为3
线性表销毁前长度为0
线性表当前长度为0
线性表为空
插入成功,插入的元素为2
删除成功,删除的元素为2
D:\C_WorkSpace\LinerList\x64\Debug\LinerList.exe (进程 20704)已退出,代码为 0。
要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口. . .
🍗线性表的顺序存储——按值查找
LocateElem(L,e); //按值查找,获取元素e
LinerList.h中的内容
//按值查找,并返回其位序
int LocateElem(SLinerList L, ElementType e);
LinerList.c中的内容
//按值查找,并返回其位序
int LocateElem(SLinerList L, ElementType e)
{
for (int j = 0; j < L.length; j++) {
if (L.data[j] == e) {
return j + 1; //返回位序
}
}
return -1; //没找到
}
test.c中的内容
#include"LinerList.h"
int main() {
SLinerList SL1; //定义一个线性表SL1
InitList(SL1); //将线性表SL1进行初始化操作
SL1.length = 3;
printf("线性表销毁前长度为%d\n", SL1.length);
DestroyList(SL1); //将线性表SL1进行销毁操作
printf("线性表销毁前长度为%d\n", SL1.length);
int SL1_length = Length(SL1); //获取表长
printf("线性表当前长度为%d\n", SL1.length);
if (Empty(SL1)==true) { //判空
printf("线性表为空\n");
}
else {
printf("线性表不为空\n");
}
ElementType e = 2;
if (ListInsert(SL1, 1, e) == true) { //按位置插入元素
printf("插入成功,插入的元素为%d\n", e);
}
else {
printf("插入失败\n");
}
ElementType delete_ele;
if (ListDelete(SL1, 1, delete_ele)==true) {
printf("删除成功,删除的元素为%d\n", delete_ele);
}
else {
printf("删除失败!\n");
}
//先插入三个数据
ListInsert(SL1, 1, 3); //插3
ListInsert(SL1, 1, 2); //插2
ListInsert(SL1, 1, 7); //插7
ElementType v = 7;
int location = LocateElem(SL1, v); //查找7
if (location != -1) {
printf("找到了,%d在线性表的第%d位上\n", v,location);
}
else {
printf("线性表中无%d元素\n",v);
}
return 0;
}
运行结果:
线性表销毁前长度为3
线性表销毁前长度为0
线性表当前长度为0
线性表为空
插入成功,插入的元素为2
删除成功,删除的元素为2
找到了,7在线性表的第1位上
D:\C_WorkSpace\LinerList\x64\Debug\LinerList.exe (进程 19592)已退出,代码为 0。
要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口. . .
🍗线性表的顺序存储——按位查找
GetElem(L,i); //按位查找,获取第i个位置上的元素
LinerList.h中的内容
//按位查找,获取第i个位置上的元素的值
ElementType GetElem(SLinerList L, int i);
LinerList.c中的内容
//按位查找,获取第i个位置上的元素的值
ElementType GetElem(SLinerList L, int i) {
ElementType value = 0;
if (i<1 || i>L.length) {
printf("查找位置不合法\n");
exit;
}
else {
value = L.data[i - 1];
return value;
}
}
test.c中的内容
#include"LinerList.h"
int main() {
SLinerList SL1; //定义一个线性表SL1
InitList(SL1); //将线性表SL1进行初始化操作
SL1.length = 3;
printf("线性表销毁前长度为%d\n", SL1.length);
DestroyList(SL1); //将线性表SL1进行销毁操作
printf("线性表销毁前长度为%d\n", SL1.length);
int SL1_length = Length(SL1); //获取表长
printf("线性表当前长度为%d\n", SL1.length);
if (Empty(SL1)==true) { //判空
printf("线性表为空\n");
}
else {
printf("线性表不为空\n");
}
ElementType e = 2;
if (ListInsert(SL1, 1, e) == true) { //按位置插入元素
printf("插入成功,插入的元素为%d\n", e);
}
else {
printf("插入失败\n");
}
ElementType delete_ele;
if (ListDelete(SL1, 1, delete_ele)==true) {
printf("删除成功,删除的元素为%d\n", delete_ele);
}
else {
printf("删除失败!\n");
}
//先插入三个数据
ListInsert(SL1, 1, 3); //插3
ListInsert(SL1, 1, 2); //插2
ListInsert(SL1, 1, 7); //插7
ElementType v = 7;
int location = LocateElem(SL1, v); //查找7
if (location != -1) {
printf("找到了,%d在线性表的第%d位上\n", v,location);
}
else {
printf("线性表中无%d元素\n",v);
}
int loc = 1;
printf("线性表中第%d的元素为%d\n",loc, GetElem(SL1, loc));//得到位序上的值
return 0;
}
运行结果:
线性表销毁前长度为3
线性表销毁前长度为0
线性表当前长度为0
线性表为空
插入成功,插入的元素为2
删除成功,删除的元素为2
找到了,7在线性表的第1位上
线性表中第1的元素为7
D:\C_WorkSpace\LinerList\x64\Debug\LinerList.exe (进程 1372)已退出,代码为 0。
要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口. . .
🍗线性表的顺序存储——打印列表
PrintList(L); //打印列表
LinerList.h中的内容
//打印列表
void PrintList(SLinerList L);
LinerList.c中的内容
//打印列表
void PrintList(SLinerList L) {
if (L.length == 0) {
printf("链表为空!");
}
else {
for (int j = 0; j < L.length; j++) {
printf("%d-->", L.data[j]);
}
printf("\n");
}
}
test.c中的内容
#include"LinerList.h"
int main() {
SLinerList SL1; //定义一个线性表SL1
InitList(SL1); //将线性表SL1进行初始化操作
SL1.length = 3;
printf("线性表销毁前长度为%d\n", SL1.length);
DestroyList(SL1); //将线性表SL1进行销毁操作
printf("线性表销毁前长度为%d\n", SL1.length);
int SL1_length = Length(SL1); //获取表长
printf("线性表当前长度为%d\n", SL1.length);
if (Empty(SL1)==true) { //判空
printf("线性表为空\n");
}
else {
printf("线性表不为空\n");
}
ElementType e = 2;
if (ListInsert(SL1, 1, e) == true) { //按位置插入元素
printf("插入成功,插入的元素为%d\n", e);
}
else {
printf("插入失败\n");
}
ElementType delete_ele;
if (ListDelete(SL1, 1, delete_ele)==true) {
printf("删除成功,删除的元素为%d\n", delete_ele);
}
else {
printf("删除失败!\n");
}
//先插入三个数据
ListInsert(SL1, 1, 3); //插3
PrintList(SL1);
ListInsert(SL1, 1, 2); //插2
PrintList(SL1);
ListInsert(SL1, 1, 7); //插7
PrintList(SL1);
ElementType v = 7;
int location = LocateElem(SL1, v); //查找7
if (location != -1) {
printf("找到了,%d在线性表的第%d位上\n", v,location);
}
else {
printf("线性表中无%d元素\n",v);
}
int loc = 1;
printf("线性表中第%d的元素为%d\n",loc, GetElem(SL1, loc));//得到位序上的值
PrintList(SL1);
return 0;
}
运行结果:
线性表销毁前长度为3
线性表销毁前长度为0
线性表当前长度为0
线性表为空
插入成功,插入的元素为2
删除成功,删除的元素为2
3-->
2-->3-->
7-->2-->3-->
找到了,7在线性表的第1位上
线性表中第1的元素为7
7-->2-->3-->
D:\C_WorkSpace\LinerList\x64\Debug\LinerList.exe (进程 8276)已退出,代码为 0。
要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口. . .