一、说明
预定义常量及类型:
//函数结果以及状态码
#define OK 1
#define ERROR 0
#define OVERFLOW -2
//Status 为int类型(函数返回值),值为状态码。
tpyedef int Status;
函数类型函数名(函数参数表)
{
//算法说明
语句序列
}/ /函数名
内存动态分配与释放
使用
new
和
delete
动态分配和释放内存空间:
分配空间 指针变扯
=new
数据类型;
释放空间
delete
指针变扯;
输入输出语句使用 C++流式输入输出的形式:
输入语句:
cin>>
变拭
l>>
…
>>变扯
n;
输出语句:
cout<<
表达式
l<<
…
<<表达式
n;
线性表的操作类型:
ADT List{
数据对象:
D={ai
I
aiEElemSet, i=l, 2,
…,
n, n;;,,Q}
数据关系: R={<ai-1,ai>|ai-1,a
1,aiED, i=2, …, n}
基本操作:
Ini tList (&L)
操作结果:构造一个空的线性表L。
DestroyList(&L)
初始条件:线性表L已存在。
操作结果:销毁线性表L。
ClearList (&L)
初始条件:线性表L已存在。
操作结果:将L重置为空表。
初始条件:线性表L已存在。
操作结果:若L为空表, 则返回true, 否则返回false。
ListLength(L)
初始条件:线性表L已存在。
操作结果:返回L中数据元素个数。
GetElem(L,i,&e)
初始条件:线性表L巳存在,且1:,s;i:os;ListLength(L)。
操作结果:用e返回L中第1个数据元素的值。
LocateElem(L,e)
初始条件:线性表L已存在。
操作结果:返回L中第1个 值与e相同的元素在 L中的位置 。若这样的数据元素不存在 , 则返回值为0。
PriorElem(r,,cur_e,&pre_e)
初始条件:线性表L已存在。
操作结果:若cur_e是L的数据元素,且不是第一个,则用pre_e返回其前驱,否则操作失败,pre_e无定义。
NextElem(L,cur_e,&next_e)
初始条件:线性表L已存在。
操作结果:若cur_e是L的数据元素,且不是最后一个,则用next_e返回其后继,否则操作失败,next_e无定义。
Listinsert(&L,i,e)
初始条件:线性表L已存在,且1:,s;i:os;ListLength (L) +l。
操作结果:在 L中第1个位置之前插入新的数据元素 e, L的长度加1。
ListDelete(&L,i)
初始条件:线性表L已存在且非空 ,且l:os;i:os;ListLength(L)。
操作结果:删除L的第1个数据元素,L的长度减1。
TraverseList(L)
初始条件:线性表L已存在。
操作结果:对线性表L进行遍历,在遍历过程中对 L的每个结点访问一次。
)
ADT List
假设线性表的每个元素需占用l个存储单元, 并以所占的第一个单元的存储地址作为数据元
素的存储起始位置。则线性表中第i+ 1个数据元素的存储位置LOC(ai+
1
)和第i个数据元素的存
储位置LOC(a;)之间满足下列关系:
一般来说, 线性表的第l个数据元素a;的存储位置为:
LOC(ai) = LOC(a
1
)
+
(i - I) x l
式中,LOC(a
1
)是线性表的第一个数据元素a
1
的存储
位置,
·
通常称作线性表的起始位置或基地址, 表中相
邻的元素a; 和a; +
I
的存储位置LOC(a;)和LOC(a;+ 1)
是相邻的。
顺序表存储结构(通常采用数组来描述数据结构中的顺序存储结构)
1.定义结构体
严蔚敏书中代码
#define MAXSIZE 100 //顺序表可能达到的最大长度,数组空间大小
typedef int ElemTpye; //为int起个别名为ElemType
typedef struct
{
ElemType *elem; //存储空间的基地址
int length; //当前的长度
}SqList; //顺序表的结构类型为SqList
常规代码 1
#define MAXSIZE 100
typedef struct{
ElemType *elem; //存储空间的基地址
int MAXSIZE //容量
int length; //当前长度
}SqList
常规代码 2
typedef struct {
int *elem;
int MaxSize,length;
}SqList;
常规代码 3
#define MAX_SIZE 100 //数组最大长度
typedef int ElemType //数据类型的别名
typedef struct sqlist //定义结构体
{
Elemtype data[MAX_SIZE]; //线性表存储元素的数组
int length; //记录线性表长度
}SqList; //线性表名称
2.初始化
补充:代码中有几个点需要说明
数组静态分配
typedef struct
{
ElemType data[MAXSIZE];
int length;
}SqList;
数组动态分配
typedef struct
{
ElemType *data;
int length;
}SqList;
C语言的内存动态分配
SqList L;
L.data=(ElemType *)malloc(sizeof(Elemtype)*MAXSIZE);
malloc(m):开辟m字节长度地址空间,并返回空间首地址。
sizeof(x):计算变量x的长度。
free(p):释放指针P所指变量的存储空间,彻底删除。
难理解的等价的写法:
*是根据地址找变量,比如*a表示获取地址为a的变量。注意,这里的a是一个地址。
&是根据变量找地址,比如&a表示获取变量a的地址。而这里的a就表示变量本身。
但初始化时要注意
int *a=b 这是指针初始化操作,是把b赋值给a,因为a表示一个地址,所以b必须是一个地址。
int &a=b 这是引用的初始化操作,是将b赋值给a,因为a是一个变量,所以b必须是一个变量。
int b=10;
int *a=&b; //*a=20,则b=20
//为顺序表分配空间
注意&L与*L的用法:(*L).elem = L->elem;
语法规定:
int b=10;
int *a=&b //将
#define MAXSIZE 10 //数组长度为10
typedef struct
{
int *elem; //存储空间的基地址
int MAXSIZE //容量
}SqList
int InitList(SqList &L)
{
L.elem=(int*)malloc(MAXSIZE*sizeof(int));
}
#define MAX_SIZE 10 //数组长度为10
typedef struct
{
int* elem; //基地址,动态方式
int data[MAX_SIZE]; //静态方式
} SqList;
写法1:
int InitList(SqList* L)
{
int* temp = (int*)malloc(MAX_SIZE*sizeof(int)); //temp为临时变量,赋值给data
}
L->elem=temp;
写法2:
int InitList(SqList* L)
{
SqList*L->data=(int*)malloc(sizeof(int)*MAX_SIZE);
}
写法3:
int InitList(SqList* L)
{
(*L).elem =(int *)malloc(sizeof(int)*MAX_SIZE); //写法等价(*L).elem = L->elem;
}
//结构体指针和结构体变量
例:指针P表示结点。如描述指针P(并非是说指针域,而是指代P所指向的节点)
如果使用结点q,那么访问数据域和指针域的代码为q.data,q.next。
如果使用指针p,那么访问数据域和指针域的代码为p->data,p->next。
C++代码
Status InitList(SqList &L)
{ //构造一个空的顺序表L并初始化
L.elem= new ElemType[MAXSIZE]; //为顺序表分配一个大小为MAXSIZE的数组空间
if (!L. elem){
exit (OVERFLOW); //存储分配失败退出
L.length=O; //空表长度为
}
return OK;
}
常规代码 1
int InitList(SqList &L)
{
//构造一个空顺序表L
L.elem=(int*)malloc(MAXSIZE*sizeof(int));//分配int类型指针数组空间,成功返回首地址,失败返回NULL,为顺序表分配大小MAX_SIZE的数组空间
if(!L.elem)
exit(-1); //exit除0外的其它值为异常退出
L.length=0; //空表长度为0
return Ok; //#define OK 1
}
常规代码 2
int InitList(SqList *L) //结构体指针变量作为形参
{
(*L).elem =(ElemType *)malloc(sizeof(ElemType)*MAXSIZE); //为顺序表分配空间
if(!L->elem) exit(OVERFLOW); //异常处理,存储分配失败
L->length=0; //空表长度为0
return OK;
}
常规代码 3
SqList*L->data=(int*)malloc(sizeof(int)*MAX_SIZE); //为顺序表分配MAX_SIZE个空间
3.取值
C++代码
Status GetElem(SqList L,int i,ElemType &e)
{
if (i<1 || i>L.length) return ERROR; //判断l. 值是否合理,若不合理, 返回 ERROR
e=L.elem[i-1]; //elem[i-1] 单元存储第 i 个数据元素 a(i)对应数组为i-1
return OK;
}
常规代码 1
【算法步骤】
心判断指定的位置序号 i 值是否合理 (1<=i<=L.length), 若不合理,则返回ERROR。
若 i 值合理,则将第 i 个数据元素 L.elem[i-1]赋给参数 e, 通过 e返回第 1 个数据元素的
传值。
int GetElem(SqList L, int i, int& e)
{
if (i < 1 || i > L.length) //判断i的值是否合理(是否为负数或是否超出表长),不合理返回ERROR
{
printf("获取值失败!");
exit(0);
}
e = L.elem[i - 1]; // elem[i - 1]单元存储第i个数据元素
return e;
}
4.查找
【算法步骤】
心从第一个元素起,依次和 e相比较,若找到与 e相等的元素 L.elem[i], 则查找成功,返回
该元素的序号 i+l。
@若查遍整个顺序表都没有找到,则查找失败, 返回0。
【算法描述】
int LocateELem(SqList L,ElemType e)
{//在顺序表1中查找值为e的数据元素, 返回其序号
for(i=O;i< L.length;i++)
if(L.elem[i)==e) //查找成功, 返回序号 i+l
return i+l; //顺序表中位置比数组+1
return O; //查找失败, 返回 0
}
5.插入
[算法步骤]
判断插入位置l是否合法(i 值的合法范围是1<=i<=n+1), 若不合法则返回 ERROR。
判断顺序表的存储空间是否已满,若满返回 ERROR。
将第n个至第l个位置的元素依次向后移动一个位置,空出第l个位置(i=n+1时无需
移动)。
将要插入的新元素e放入第i个位置。
表长加l。
【算法描述】
Status Listinsert(SqList &L,int i ,ElemType e)
{
//在顺序表L中第i个位置之前插入新的元素e, i值的合法范围是 1<=i<=L.length+l
if((i<l)||(i>L.length+l)) //i值不合法
return ERROR;
if(L.length==MAXSIZE) //当前存储空间已满
return ERROR;
for (j=L. length-1; j>=i-1; j--)
L.elem[j+l]=L.elem[j]; //插入位置及之后的元素后移
L.elem[i-l]=e; //将新元素e放入第l个位置
++L.length; //表长+1
return OK;
常规代码1
方法一:数组法
Status Insert(SqList &L, int i, ElemType e)
{
//因为可以插在最后,所以i值的合法范围是 1~L.length+1
if ((i < 1) || (i > L.length + 1))
return ERROR;
if (L.length >= L.listsize) //存储空间已满
{
ElemType *data;
data =(ElemType*)realloc(L.elem,(L.listsize+LISTINCREMENT)*sizeof(ElemType));
if(!data) return;
L.elem = data;
L.listsize += LISTINCREMENT;
}
for (j = L.length-1; j >= i-1; j--) //j=L.length-1表示从顺序表最后一个元素开始
L.elem[j + 1] = L.elem[j]; //插入位置及之后的元素后移
L.elem[i - 1] = e; //将新元素e放入第l个位置
L.length ++;
return OK;
}
方法二:指针法
ElemType *p = &(L.elem[i-1]); //指针p指向第i个元素
ElemType *q = &(L.elem[L.length-1]); //指针q指向最后一个元素
for(q ;q>=p;q--)
*(q+1) = *q;
*p = e;
L.length++;
6.删除
删除第i(1<=i<=n) 个元素时需将第i+1个至第n 个元素(共 n-i 个元素) 依次向前移动一个位置
(i = n 时无需移动)
判断删除位置 i是否合法(合法值为1<=i<=n), 若不合法则返回 ERROR。
将第i+l个至第n个的元素依次向前移动一个位置 (i=n时无需移动)。
表长减1.
Status ListDelete(SqList &L,int i)
{
//在顺序表L中删除第i个元素,i值的合法范围是 1<=i<=L.length
if((i<l)||(i>L.length)) return ERROR; //i值不合法
for (j=i;j<=L.length-1;j ++)
L.elem[j-1]=1.elem[j]; //被删除元素之后的元素前移
--l.length; //表长减1
return OK;