目录
3.4.2 顺序表的取值(根据位置i 获取相应位置数据元素的内容)
3.4 顺序表的顺序存储表示
3.4.1 两种分配方式
静态分配
#define MAXSIZE 20 /*存储空间初始分配量 */
typedef int ElemType; /*ElemType类型根据实际情况决定,这里定义为int*/
typedef struct
{
ElemType data[MAXSIZE]; /*数组,存储数据元素*/
int length; /*线性表当前长度*/
}SqList;
动态分配
typedef int ElemType; /*ElemType类型根据实际情况决定,这里定义为int*/
typedef struct
{
ElemType *data;
int length; /*线性表当前长度*/
}SqList;
L.data=(ElemType*)malloc(sizeof(ElemType)*MaxSize);//C语言的动态分配
顺序表示意图:
补充:操作算法中用到的预定义常量和类型
//函数结果状态代码
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
//Status是函数的类型,其值是函数结果状态代码
typedef int Status;
typedef char ElemType;
补充:’&‘’作引用和取地址符的区别和作用
引用:指的是某一变量(目标)的一个别名,对引用的操作与对变量直接操作完全一样。&作为引用的时候,必须在定义时候就进行初始化,若不进行初始化则会编译报错。
int a;
int &A=a;
//相当于小a被大A取代,对大A操作即对小a进行操作。
取地址:&作为取地址使用时,要跟指针(存放地址)联系在一起。
int N=1002;
int *n;
n=&N;//n存放着N的地址
注:和类型在一起时是引用,和变量在一起时是取址。
补充:C语言中 “ . ”和“->”的区别
A->a 表示A是指向结构体的指针
A.a 表示A是结构体
A->a等效于(*A).a//这里*表示解引用
typedef struct A{
int a;
int sum;
}A;
void test(A* n)//这里的形参类型是一个结构体指针类型
{
node->a=1;
node->sum=2;
}
void test1(A a)//结构体类型
{
node.a=1;
node.sum=2;
}
3.4 顺序表基本操作的实现
3.4.1 线性表L的初始化(参数用引用)
Status lnitList_Sq(SqList &L)
{
L.data = (ElemType*)malloc(sizeof(ElemType) * MAXSIZE);
if (!L.data)exit(OVERFLOW); //表示内存分配失败
L.length = 0; //给线性表的长度初始化
return OK;
}
销毁线性表L
void DestroyList(SqList& L)
{
if (L.data) delete L.data;//释放空间,C++
//或
free(L.data);//释放空间,C语言
}
清空线性表L
void ClearList(SqList &L)
{
L.length=0; //将线性表的长度置为0
}
求线性表L的长度
int GetLength(SqList &L)
{
return(L.length);
}
判断线性表L是否为空
int IsEmpty(SqList L)
{
if (L.length == 0)
{
return OK;
}
else
return ERROR;
}
3.4.2 顺序表的取值(根据位置i 获取相应位置数据元素的内容)
int GetElem(SqList L,int i,ElemType &e)
{
if (L.length==0||i<1 || i>L.length)
//线性表长度为0的话,表示里面没有元素,i不能小于1和不能大于顺序表的长度
return ERROR;
e = L.data[i - 1];//第i-1的单元存储这第i个数据
return OK;
}
3.4.3 顺序表的查找
int LocateElem(SqList L, ElemType e)
{
//在线性表L中查找值为e的数据元素,返回其序号(第几个元素)
for (int i = 0; i < L.length; i++)
{
if (L.data[i] == e)
return i + 1;//查找成功,返回序号
}
return 0;//查找失败
}
顺序表查找算法分析:
基本操作:L.elem[i]==e
比较次数:e=a,1次,e=b,2次,... ,e=g,7次;
平均查找次数:(1+2+3+4+5+6+7)/7=4;//每个值出现的概率为。
对于含有n个记录的表,查找成功时:
3.4.3 顺序表的插入
算法思想:①判断插入位置i是否合法。
②判断顺序表的存储空间是否已满,若已满返回ERROR。
③将第n至第i位的元素依次向后移动一个位置,空出第i个位置。
④将要插入的新元素e放入第i个位置。
⑤表长加1,插入成功返回OK。
顺序表的插入算法的平均时间复杂度为O(n).
Status Listlnsert_Sq(SqList L,int i,ElemType e)
{
if (i<1 || i>L.length + 1)
return ERROR;//i的值不合法
if (L.length == MAXSIZE)
return ERROR;//当前存储空间已满
for (int j = L.length - 1; j >= i-1; j++)//j是指下标的位置 加入要插入的i为2,那i要插入的下
标就为1 ,线性表的长度为4 (0 1 2 3)
{
L.data[j + 1] = L.data[j];//插入位置及之后的元素后移 4<-3 3<-2 2<-1
}
L.data[i - 1] = e;//将e放入第i个位置
L.length++;//表长+1
return OK;
}
3.4.4 顺序表的删除
算法思想:①判断删除位置i是否合法(合法值为1≤isn) 。
②将欲删除的元素保留在e中
③将第i+1至第n位的元素依次向前移动一个位置。
④表长减1,删除成功返回OK。
偶读
顺序表的删除算法的平均时间复杂度为O(n).
Status ListDelete_sq(SqList L, int i)
{
if (i<1 || i>L.length )
return ERROR;//i的值不合法
for (int j = i; j <= L.length - 1; j++)
{
L.data[j - 1] = L.data[j];//被删除元素之后的元素向移动
}
L.length--;//表长减1
return OK;
}
3.5 顺序存储结构的优缺点
优点:①无须为表示表中元素之间的逻辑关系而增加额外的存储空间。
②可以快速的存取表中任一位置。
缺点:①插入和删除操作需要移动大量元素。
②线性表长度变换大时,难以预估存储空间的容量。
③容易浪费存储空间
3.6 代码详情
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include <corecrt_math.h>
#define MAXSIZE 100
#define OK 1
#define ERROR 0
typedef int Status;//int类型用Status表示
typedef int ElemType;
//静态分配内存
//typedef struct {
// ElemType data[MAXSIZE];//数组,存储数据元素
// int length;//线性表当前的长度
//}SqList;
//动态分配内存
typedef struct {
ElemType* data;//动态
int length;
}SqList;
//线性表的初始化
Status lnitList_Sq(SqList& L)//形参的是一个结构体指针
{
//(*L)==L,就可以直接调用SqList结构体里面的变量,假如不用解引用的话,则使用L->data
L.data = (ElemType*)malloc(sizeof(ElemType) * MAXSIZE);
if (!L.data)exit(OVERFLOW);//表示内存分配失败
L.length = 0;//给线性表的长度初始化
return OK;
}
//销毁一个线性表
void DestroyList(SqList& L)
{
if (L.data)
//delete L.data;//释放空间,C++
free(L.data);//释放空间,C语言
}
//清空线性表
void ClearList(SqList& L)
{
L.length = 0;//将线性表的长度置为0
}
//求线性表的长度
int GetLength(SqList& L)
{
return (L.length);
}
//判断线性表L是否为空
int IsEmpty(SqList L)
{
if (L.length == 0)
{
return OK;
}
else
return ERROR;
}
//获取元素操作(根据位置i获取相应位置数据元素的内容)
int GetElem(SqList L, int i, ElemType& e)
{
if (L.length==0||i<1 || i>L.length)//线性表长度为0的话,表示里面没有元素,i不能小于1和不能大于链表的长度
return ERROR;
(e) = L.data[i - 1];//返回i-1里存的元素
return OK;
}
//顺序表基本操作的实现
int LocateElem(SqList L, ElemType e)
{
//在线性表L中查找值为e的数据元素,返回其序号(第几个元素)
for (int i = 0; i < L.length; i++)
{
if (L.data[i] == e)
return i + 1;//查找成功,返回序号
}
return 0;//查找失败
}
//顺序表的插入
Status Listlnsert_Sq(SqList &L,int i,ElemType e)
{
if (i<1 || i>L.length + 1)
return ERROR;//i的值不合法
if (L.length == MAXSIZE)
return ERROR;//当前存储空间已满
int j=0;
for ( j = L.length - 1; j >= i-1; j--)//j是指下标的位置 加入要插入的i为2,那i要插入的下标就为1 ,线性表的长度为4 (0 1 2 3)
{
L.data[j + 1] = L.data[j];//插入位置及之后的元素后移 4<-3 3<-2 2<-1
}
L.data[i - 1] = e;//将e放入第i个位置
L.length++;//表长+1
return OK;
}
//删除元素
Status ListDelete_sq(SqList &L, int i)
{
if (i<1 || i>L.length )
return ERROR;//i的值不合法
for (int j = i; j <= L.length - 1; j++)
{
L.data[j - 1] = L.data[j];//被删除元素之后的元素向移动
}
L.length--;//表长减1
return OK;
}
//遍历顺序表
void Listdisplay(SqList L)
{
int i = 0;
for ( i = 0; i < L.length; i++)
{
printf("%d", L.data[i]);
printf(" ");
}
}
//添加表元素
void WriteList(SqList& L)//把元素放入顺序表
{
printf("请输入你要创建的顺序表的长度:");
scanf("%d", &L.length);
printf("请输入%d个你要放入顺序表里的元素:", L.length);
for (int i = 0; i < L.length; i++)
{
scanf("%d", &L.data[i]);
}
}
int main()
{
int e = 0;
SqList L;
lnitList_Sq(L);
WriteList(L);
Listdisplay(L);
printf("\n表的长度为:%d\n",GetLength(L));
ListDelete_sq(L, 2);
Listdisplay(L);
printf("\n表的长度为:%d\n", GetLength(L));
Listlnsert_Sq(L, 2, 10);
Listdisplay(L);
printf("\n表的长度为:%d\n", GetLength(L));
GetElem(L, 2, e);
printf("%d", e);
}