本质上,就是火车。火车的每一节直接连接到下一节,然后每一节火车车厢里,存储着它的货物(数据)。它有着一个车头(基地址),车头后车厢的长度(也就是整个顺序表的长度)。
对于这辆火车(顺序表),我们要有几个基本的功能:
当然除此之外还有很多方法,这里仅介绍以上五种。
————————————分割————————————
注:本代码没有包含main函数(我在其中加入了一些很具体的注释来帮助理解,如果喜欢读代码的朋友可以直接看)
注2:如果你不想纯粹读代码,该代码所有的具体解释请下移
//数据结构-c语言-线性表-顺序表
#include
#include
#include
#include
using namespace std;
#define OK 1
#define ERROR 0
#define OVERFLOW -2
typedef int Status;
typedef int ElemType;
#define MAXSIZE 100
struct player
{
int id;
string name;
char pow,def,spe,nok;
};
typedef struct
{
player *elem;//基地址
int length;//长度
}Sqlist;
Status InitList_Sq(Sqlist &L)//【顺序表初始化】目的是创造一个空的线性表L
//创建一个空表L,此处&L表示形参与实参绑定,对形参的操作可以等价到实参上
//这里使用的是sqlist,而并非player
{
L.elem = new player[MAXSIZE];
//为L的基地址,也就是第一个player后,分配大小为MAXSIZE的数组空间
//L.elem指向player,new创造了一个长度为100的player数组,并为其分配空间
if(!L.elem)exit(OVERFLOW);
//!L.elem 非运算符,当L.elem创造失败时,返回1,则视作分配失败,返回OVERFLOW
//exit函数,表示在main函数之外强制结束程序
//此部分是为了如果产生错误,及时退出避免更多错误
L.length =0;
//如果分配内存成功,则设定该顺序表目前长度为0
return OK;
//返回成功
}
Status GetElem(Sqlist L,int i,palyer &pl)//【顺序表取值】目的是用pl返回顺序表中的第i个数据
{
if(i<1 || i>L.length)//此处i代表的是正常认识中的第几个,而不是计算机中的第几个
return ERROR;//如果查询i范围超出正常范围,则返回error
pl = L.elem[i-1];
//由于i代表的是正常认识中的位数,因此其值储存在L.elem[i-1]中
//这一步将其内容赋值给形参(由于有&指向地址,所以实际是给予实参pl),以供进一步调用
return OK;//如果正常执行查询,则返回OK
}
Status LocateElem_Sq(Sqlist L,double e)//【顺序表查询】目的是返回L中第一个值与pl相同的元素位置
{
for(itn i=0;i<L.length;i++)
{
if(L.elem[i].pow == e)
{
return i+1;//由于我们查找的返回目标是正常情况下的第i个,而for中循环的是计算机中的第i个,所以使用i+1
}
}
}
Status ListInsert_Sq(Sqlist &L,int i,player pl)
{
if(i<1 || (i>L.length + 1))
{
return ERROR;
//这里最大区域修改为了length+1,原因是本操作的目的是插入,我们同样可以插入到 length之后一位
}
if(L.length == MAXSIZE)
{
return ERROR;
//如果目前长度等于我们设定的最大长度,代表它已经满了,不能再插入了,所以失败
}
for(int j=L.length-1;j>=i;j--)
{
L.elem[j+1]=L.elem[j];//从最后一位开始往前移,每次移一位,从j+1位移到j位
}
L.elem[i-1] =pl;//这里的i依然是我们正常认识时的i,而不是计算机中的i
++L.length;//表长增加
return OK;
}
Status ListDelete_Sq(SqList &L, int i)//【顺序表的删除】在顺序表中删除第i个
{
//i值的合法范围是1<=i<=L.length
if ((i < 1) || (i > L.length))
return ERROR; //如果i处于范围外,则失败。
for (int j = i; j <= L.length; j++)
L.elem[j - 1] = L.elem[j]; //被删除元素之后的元素前移
--L.length; //表长减1
return OK;
}
int main()
{
return 0;
}
#define OK 1
#define ERROR 0
#define OVERFLOW -2
typedef int Status;
typedef int ElemType;
#define MAXSIZE 100
宏定义:define和typedef,由于使用的是c++,我在这里将OK和ERROR宏定义为1和0用于返回结果,同样OVERFLOW用于exit()
函数在主函数之外强行结束。(这玩意下面会解释)
typedef:之前使用c的朋友可能不太理解什么意思,其实就是给其后面的类型起一个新的名字,本质上没有区别。比如typedef int Status;
,就是指,给int起一个新名字叫Status,之后使用的时候,如果遇到Status,它本质上仍然是int。
struct player
{
int id;
string name;
char pow,def,spe,nok;
};
typedef struct
{
player *elem;//基地址
int length;//长度
}Sqlist;
这里我们写一个结构叫做player,它包含id,name和四个属性。当然这并不重要,你无论如何称呼这个结构,给它设内容都不会有任何关系。重点在于下面的我们称作Sqlist的结构。
就像上面我们说的火车头,其实就是这个Sqlist了,它储存着顺序表的基地址(火车头的位置)和长度。
Status InitList_Sq(Sqlist &L)
{
L.elem = new player[MAXSIZE];
if(!L.elem)exit(OVERFLOW);
L.length =0;
return OK;
}
你们可能会在主函数这样来创造一个Sqlist:
SqList L;
但我们发现一个问题,就是这样创建完之后,它并不能使用。为什么?因为你并咩有给它分配任何一点内存,它就相当于只是一个火车头的图纸,我们虽然有图纸,但是火车还不存在。
因此,我们的第一步,是将这个图纸,变成火车。
L.elem = new player[MAXSIZE];
长度为100个player的长度(结构体的长度不会请先学习结构体)if(!L.elem)exit(OVERFLOW);
L.length =0;
如果你是第一次接触数据结构/c++语言,可能会不知道exit();
函数,我在这里做一个简单的解释:
exit();
函数通常用于在主函数之外直接停止程序。(通常我们在主函数中会使用return;)。它通常有两种参数:
exit(0);//正常退出
exit(1);//非正常退出
不过事实上,参数除了0以外,都是非正常退出,比如exit(10086)
或者本文的exit(-2)
(exit(OVERFLOW)
)。
Status GetElem(Sqlist L,int i,palyer &pl)
{
if(i<1 || i>L.length)
return ERROR;
pl = L.elem[i-1];
return OK;
}
从火车头开始一个一个找,找到第i个车厢,并且将其中的数据返回到pl上。
&:取地址符,为了让我们函数中形参的改变可以直接同步到实参上,我们可以在参数前加一个&。如果你听不懂我在说什么,你只要知道:加了这个之后,你函数内该量的改变,会导致函数外该量同时改变。
if(i<1 || i>L.length)return ERROR;
如果我们的车厢并没有i那么长(i小于1,或者大于我们当前的最长长度),那我们找你马呢。(直接结束程序,气死老子了,不找了)pl = L.elem[i-1];
至于这里为什么用i-1……你应该懂,这里的i表示的是一般人认知中的第几个(正常人认知数是从第1个开始的),而我们的数组是从0开始的。
当然,如果你将其改成能够直接用i表示的,我会更开心。
Status LocateElem_Sq(Sqlist L,double e)
{
for(itn i=0;i<L.length;i++)
{
if(L.elem[i].pow == e)
{
return i+1;
}
}
}
从火车头开始一个一个找,找到第1个和e值数据相同的位置,并且将其编号返回。
在这里我使用的是player的pow的值,根据情况你也可以使用其他。
本函数非常简单,就是一个循环,一个一个找嘛,不寒颤。
找到那个对应等于e的值,然后返回i+1。(至于为什么是i+1,看刚刚的解释。)
Status ListInsert_Sq(Sqlist &L,int i,player pl)
{
if(i<1 || (i>L.length + 1))return ERROR;
if(L.length == MAXSIZE)return ERROR;
for(int j=L.length-1;j>=i;j--)
{
L.elem[j+1]=L.elem[j];
}
L.elem[i-1] =pl;
++L.length;
return OK;
}
把pl插入到顺序表中的第i个位置。(注意,这里的i也是我们常人理解中从1开始的i)
if(i<1 || (i>L.length + 1))return ERROR;
if(L.length == MAXSIZE)return ERROR;
for(int j=L.length-1;j>=i;j--)
{
L.elem[j+1]=L.elem[j];
}
思路也很简单,就是从目前有的最后一个车厢开始,每个车厢向后移一格,一直到第i个。
L.elem[i-1] =pl;
++L.length;
Status ListDelete_Sq(SqList &L, int i)
{
if ((i < 1) || (i > L.length))return ERROR;
for (int j = i; j <= L.length; j++)
L.elem[j - 1] = L.elem[j];
--L.length;
return OK;
}
删掉顺序表中的第i个值。
if ((i < 1) || (i > L.length))return ERROR;
for (int j = i; j <= L.length; j++)
L.elem[j - 1] = L.elem[j];
--L.length;
我建议你再尝试自己实现以下几个功能:
拿走,请。
#include
#include
#include
#include
using namespace std;
#define OK 1
#define ERROR 0
#define OVERFLOW -2
typedef int Status;
typedef int ElemType;
#define MAXSIZE 100
struct player
{
int id;
string name;
char pow,def,spe,nok;
};
typedef struct
{
player *elem;
int length;
}Sqlist;
Status InitList_Sq(Sqlist &L)
{
L.elem = new player[MAXSIZE];
if(!L.elem)exit(OVERFLOW);
L.length =0;
return OK;
}
Status GetElem(Sqlist L,int i,palyer &pl)
{
if(i<1 || i>L.length)
return ERROR;
pl = L.elem[i-1];
return OK;
}
Status LocateElem_Sq(Sqlist L,double e)
{
for(itn i=0;i<L.length;i++)
{
if(L.elem[i].pow == e)
{
return i+1;
}
}
}
Status ListInsert_Sq(Sqlist &L,int i,player pl)
{
if(i<1 || (i>L.length + 1))
{
return ERROR;
}
if(L.length == MAXSIZE)
{
return ERROR;
}
for(int j=L.length-1;j>=i;j--)
{
L.elem[j+1]=L.elem[j];/
}
L.elem[i-1] =pl;
++L.length;
return OK;
}
Status ListDelete_Sq(SqList &L, int i)
{
if ((i < 1) || (i > L.length))
return ERROR;
for (int j = i; j <= L.length; j++)
L.elem[j - 1] = L.elem[j];
--L.length;
return OK;
}
int main()
{
return 0;
}