第三章 顺序存储结构的实现(超详细)

目录

3.4 顺序表的顺序存储表示

3.4.1 两种分配方式

 3.4 顺序表基本操作的实现

3.4.1 线性表L的初始化(参数用引用)

3.4.2 顺序表的取值(根据位置i 获取相应位置数据元素的内容)

3.4.3 顺序表的查找

3.4.3 顺序表的插入

3.4.4 顺序表的删除

 3.5 顺序存储结构的优缺点

3.6 代码详情


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;//每个值出现的概率为\frac{1}{7}

对于含有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);
}

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值