什么是线性表:
由n个数据特性相同的元素构成的有限有序序列称为线性表
表中元素的个数成为线性表的长度,n=0时为空表
表起始位置:表头
表结束位置:表尾
除第一个之外,结构中每个数据元素只有一个前驱
除最后一个之外,结构中每个数据元素均只有一个后继
线性表的抽象数据类型描述:
类型名称:线性表(List)
基本操作:
建空表
销毁表
清空表
判断表是否为空
返回表的长度
求线性表中的某个元素
在线性表中查找某元素X第一次出现的位置
删除指定位序i的元素
在位序i前插入一个新元素X
本程序代码均采用两种方式。
线性表的顺序存储实现
//指针
typedef struct LNode*List;//结构体指针
struct LNode{
ElementType Data[MAXSIZE];
int last;
};
struct LNode L;
List PtrL;
//结构体 以图书为例
#define MAXSIZE 100
typedef struct{
float price;
char name[20];
}book;
typedef struct {
book *elem;//存储空间基地址,类型为定义的结构体类型
int length;
}SqList;
SqList L;//在上述定义之后,可以通过该变量定义语句
**线性表的顺序存储结构:**一组地址连续的存储单元依次存储线性表的数据元素
**起始地址/基地址:**线性表中第一个数据元素的位置
**随机存取:**只要确定了存储线性表的位置,线性表中任意数据元素都可随机存取。
主要操作实现
1.初始化(建立空的顺序表)
//指针
List MakeEmpty(){
List PtrL;
PtrL=(List)malloc(sizeof(struct LNode));
PtrL->last=-1;
return PtrL;
}
//结构体
//1.为顺序表L动态分配一个预定大小的数组空间,使elem指向这段空间的基地址
//2.将当前表的长度设为0
Status InitList(SqList &L){
L.elem=new ElemType[MAXSIZE];
//因为在顺序表存储结构的时候这个elem是个指针。
if(!L.elem)exit(OVERFLOW);//OVERFLOW在实际程序编写运行的时候需要提前宏定义,如果L.elem为0,则存储分配失败退出。
L.length=0;//空表当前长度为0;
return OK;//OK也要宏定义
}
2.查找
int find(ElementType X,List PtrL){
int i=0;
while(i<=PtrL->last&&PtrL->Data[i]!=X)
i++;
if(i>PtrL->last)return -1;
else return i;//返回实际的数组元素的位置
}
查找成功的平均比较次数为(n+1)/2
运气好第一次就找到,运气不好最后一次找到
时间复杂度:O(n) 一个循环
根据指定的要查找的元素的值e,查找顺序表中第一个与e相等的元素。若查找成功,则返回该元素在表中的位置序号;若查找失败,则返回0;
用for循环
int find(ElementType X,List PtrL){
for(int i=0;i<PtrL->last;i++)
if(Ptrl->Data[i]==X)
return i+1;//考虑数组的位置和实际所确定的位置相差1
return 0;
}
3.插入
1.判断插入位置i是否合法 1<=i<=n+1
2.判断顺序表的存储空间是否已满,若已满就返回ERROR
3将第n个至第i个位置的元素依次向后移动一个位置,空出第i个位置(i=n+1时无需移动)
4.将要插入的新元素e放入第i个位置(赋值)
5.表长+1
void Insert(ElementType X,int i,List PtrL) {
int j;
if(PtrL->last==MAXSIZE-1){
printf("表满");
return;
}
if(i<1||i>PtrL->last+2){//实际输入从1开始算起,可以在末尾插入
printf("位置不合法");
return;
}
for(j=PtrL->last;j>=i-1;j--){
PtrL->Data[j+1]=PtrL->Data[j];
}
PtrL->Data[i-1]=X;
PtrL->last++;
return;
}
Status ListInsert(SqList &L.int i,ElemType e){
if(i<1||i>L.length+1)return ERROR;
if(L.length==MAXSIZE)return ERROR;
for(int j=L.length-1;j>=i-1;j--){
L.elem[j+1]=L.elem[j];
}
L.elem[i-1]=e;
++L.length;
return OK;
}
删除操作:
void Delete(int i,List PtrL){
if(i<1||i>PtrL->last+1)
return;
for(int j=i;j<=PtrL->last;j++)
PtrL->Data[j-1]=PtrL->Data[j];
PtrL->last--;
return;
}
另一种写法
Status ListDelete(SqList &L,int i){
if((i<1)||i>L.length)return ERROR;
for(int j=i;j<=L.length-1;j++)
L.elem[j-1]=L.elem[j];
L.length--;
return OK;
}
部分操作的运行程序
转载链接感谢这位大佬的程序,让我终于明白了书上的代码如何实现运行。
//顺序表的初始化
#include
#include //exit 所在头文件
// exit(1)表示异常退出.这个1是返回给操作系统的
//exit(x)(x不为0)都表示异常退出
// exit(0)表示正常退出
#define OK 1;//ok在程序中是要有规定的。
#define OVERFLOW -2
#define MAXSIZE 100//顺序表可能达到的最大长度
typedef int Status;//Status是函数的类型,其值是函数结果状态代码,如OK等
typedef int ElemType;//ElemType是线性表中数据元素的类型,此处用int
//若有时数据类型不一致,就在函数里直接把elemtype改成相应的数据类型,
typedef struct
{
ElemType *elem;//存储空间的基地址
int length;//当前长度
int listsize;//当前分配的存储容量
}SqList;
Status InitList_Sq(SqList &L)//构造一个空的顺序表
{
L.elem=new ElemType[MAXSIZE];//为顺序表分配一个大小为MAXSIZE的数组空间
if(!L.elem) exit(OVERFLOW);//存储失败
L.length=0;//空表长度为零
L.listsize=MAXSIZE;
return OK;
}
Status ListTraverse(SqList L)// 初始条件:顺序线性表L已存在
{
ElemType *p;
p=L.elem;
int i;
printf("线性表当前容量为:%d\n",L.listsize);
if(L.length>0)
{
printf("当前线性表有%d个元素,分别是\n",L.length);
for(i=1;i<=L.length;i++)
{
printf("%d ",*p++);
}
}
else
{
printf("目前还是空线性表.\n");
}
}
int main()
{
SqList la;
InitList_Sq(la);
ListTraverse(la);
}
exit与return的区别:exit和系统有关系,干脆利落直接退出进程。
return一级一级的返回,返回到最初一级,退出进程。
这就是为什么在main函数之外,用exit的缘故
第一种写法的运行实例
#include
#include
using namespace std;
#define MAXSIZE 100
typedef int ElementType;
struct LNode{
ElementType Data[MAXSIZE];
int last;
};
typedef struct LNode*List;//结构体指针
List MakeEmpty(){
List PtrL;
PtrL=(List)malloc(sizeof(struct LNode));
PtrL->last=-1;
return PtrL;
}
void Delete(int i,List PtrL){
if(i<1||i>PtrL->last+1)
return;
for(int j=i;j<=PtrL->last;j++)
PtrL->Data[j-1]=PtrL->Data[j];
PtrL->last--;
return;
}
int find(ElementType X,List PtrL){
int i=0;
while(i<=PtrL->last&&PtrL->Data[i]!=X)
i++;
if(i>PtrL->last)return -1;
else return i;//返回实际的数组元素的位置
}
void Insert(ElementType X,int i,List PtrL) {
int j;
if(PtrL->last==MAXSIZE-1){
printf("表满");
return;
}
if(i<1||i>PtrL->last+2){//实际输入从1开始算起,可以在末尾插入
printf("位置不合法");
return;
}
for(j=PtrL->last;j>=i-1;j--){
PtrL->Data[j+1]=PtrL->Data[j];
}
PtrL->Data[i-1]=X;
PtrL->last++;
printf("添加成功\n");
return;
}
int main(){
List A=MakeEmpty();
int a=10,b=3,c=6;
Insert(a,1,A);
cout<<A->Data[0];
return 0;
}
通过二次学习数据结构,感觉懂得了很多。。。真高兴!!!