本质上,就是火车。火车的每一节直接连接到下一节,然后每一节火车车厢里,存储着它的货物(数据)。它有着一个车头(基地址),车头后车厢的长度(也就是整个顺序表的长度)。
对于这辆火车(顺序表),我们要有几个基本的功能:
初始化(创造一辆火车)取值(找到第i号车厢存储的数据)查找(我们输入一个e,从前往后找到第一个和我们输入的e值相同的车厢)插入(在第i节车厢的位置加入一个新的车厢,存入我们输入的数据e)删除(把第i节车厢炸了,之后的车厢连接上前面的车厢)当然除此之外还有很多方法,这里仅介绍以上五种。
————————————分割————————————
注:本代码没有包含main函数(我在其中加入了一些很具体的注释来帮助理解,如果喜欢读代码的朋友可以直接看) 注2:如果你不想纯粹读代码,该代码所有的具体解释请下移
//数据结构-c语言-线性表-顺序表 #include<iostream> #include<fstream> #include<string> #include<iomanip> 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和typedef,由于使用的是c++,我在这里将OK和ERROR宏定义为1和0用于返回结果,同样OVERFLOW用于exit()函数在主函数之外强行结束。(这玩意下面会解释)
typedef:之前使用c的朋友可能不太理解什么意思,其实就是给其后面的类型起一个新的名字,本质上没有区别。比如typedef int Status;,就是指,给int起一个新名字叫Status,之后使用的时候,如果遇到Status,它本质上仍然是int。
这里我们写一个结构叫做player,它包含id,name和四个属性。当然这并不重要,你无论如何称呼这个结构,给它设内容都不会有任何关系。重点在于下面的我们称作Sqlist的结构。
就像上面我们说的火车头,其实就是这个Sqlist了,它储存着顺序表的基地址(火车头的位置)和长度。
你们可能会在主函数这样来创造一个Sqlist:
SqList L;但我们发现一个问题,就是这样创建完之后,它并不能使用。为什么?因为你并咩有给它分配任何一点内存,它就相当于只是一个火车头的图纸,我们虽然有图纸,但是火车还不存在。
因此,我们的第一步,是将这个图纸,变成火车。
如果你是第一次接触数据结构/c++语言,可能会不知道exit();函数,我在这里做一个简单的解释:
exit();函数通常用于在主函数之外直接停止程序。(通常我们在主函数中会使用return;)。它通常有两种参数:
exit(0);//正常退出 exit(1);//非正常退出不过事实上,参数除了0以外,都是非正常退出,比如exit(10086)或者本文的exit(-2)(exit(OVERFLOW))。
从火车头开始一个一个找,找到第i个车厢,并且将其中的数据返回到pl上。
&:取地址符,为了让我们函数中形参的改变可以直接同步到实参上,我们可以在参数前加一个&。如果你听不懂我在说什么,你只要知道:加了这个之后,你函数内该量的改变,会导致函数外该量同时改变。
至于这里为什么用i-1……你应该懂,这里的i表示的是一般人认知中的第几个(正常人认知数是从第1个开始的),而我们的数组是从0开始的。
当然,如果你将其改成能够直接用i表示的,我会更开心。
从火车头开始一个一个找,找到第1个和e值数据相同的位置,并且将其编号返回。
在这里我使用的是player的pow的值,根据情况你也可以使用其他。
本函数非常简单,就是一个循环,一个一个找嘛,不寒颤。
找到那个对应等于e的值,然后返回i+1。(至于为什么是i+1,看刚刚的解释。)
把pl插入到顺序表中的第i个位置。(注意,这里的i也是我们常人理解中从1开始的i)
思路也很简单,就是从目前有的最后一个车厢开始,每个车厢向后移一格,一直到第i个。
把我们的pl(数据名)存入这个位置,然后长度+1。 L.elem[i-1] =pl; ++L.length;删掉顺序表中的第i个值。
我建议你再尝试自己实现以下几个功能:
清空顺序表销毁顺序表并重新定义长度输入e,查询线性表中该值出现过几次输入e,i,返回顺序表中第i次出现e是在哪个位置拿走,请。
#include<iostream> #include<fstream> #include<string> #include<iomanip> 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; }