C语言 | 详解线性表之顺序表

线性表之顺序表


定义:线性表是具有 相同数据类型的n个数据元素(int,float,struct…)的有限序列

特点:除第一个元素外,每个元素有且仅有一个直接前驱;除最后一个元素外,每个元素有且仅有一个直接后继

顺序表:用顺序存储的方式实现线性表–(逻辑相邻的元素物理位置相邻


定义结构

#include<stdio.h>
#define MaxSize 10
typedef struct {
	int data[MaxSize];
	int length;
}SqList;

基本操作

  • 初始化(考虑数据元素里所有数据项)

    void InitList(SqList &L) {
    	for (int i = 0; i < MaxSize; i++)
    		L.data[i] = 0;
    	L.length = 0;
    }
    
    /*因为数据项里有length记录了存放了多少数据,操作的一般是存放的数据,而非整个开辟的空间,而存放的时候即给data[i]赋值了,因此对data[i]的初始化其实是可以省略掉的*/
    
    void InitList(SqList &L) {
    	L.length = 0;
    }
    
  • 插入(插入位置之后的元素i~n-1都得后移一位,注意先移动最后的n-1到n,即从后往前移动需要后移的数据元素,否则会发生数据元素覆盖)(提高代码的健壮性:考虑空间不足时无法插入或者空间足够但插入位置不合法)

    //在第i个位置(次序)上插入元素e
    bool ListInsert(SqList &L, int i, int e) {
    	if (L.length >= MaxSize) //存储空间已满
    		return false;
    	if (i<1 || i>L.length + 1) //插入位置不合理
    		return false;
    	for (int j = L.length; j >= i; j--)
    		L.data[j] = L.data[j - 1]; //后移
    	L.data[i - 1] = e; //次序i,即下标i-1
    	L.length++;
    	return true;
    }
    
  • 删除 (删除位置之后的元素i~n-1都得前移一位,直接从前往后依次前移覆盖掉要删除的元素即可)

    //将第i位元素删除,并获取被删除的这个元素
    bool ListDelete(SqList &L, int i, int &e) {
    	if (i<1 || i>L.length)
    		return false;
    	e = L.data[i - 1];
    	for (int j = i; j < L.length; j++) {
    		L.data[j - 1] = L.data[j]; //前移
    	}
    	L.length--;
    	return true;
    }
    
  • 查找

    • 因为存储的是相同数据类型的元素,所有每个元素的大小是相同的,c语言提供**sizeof()**来计算一个数据元素的大小。*假设第一个元素的地址是loc,那么第n个元素的地址是loc+(n-1)sizeof(ElemType)

    • 按位查找

      //查找-按位查找第i个元素(次序)
      int GetElem(SqList L, int i) {
      	return L.data[i - 1];
      }
      
    • 按值查找

      //查找-按值查找元素值为e的第一个出现的元素,返回其次序
      int LocateElem(SqList L, int e) {
      	for (int i = 0; i < L.length; i++) {
      		if (L.data[i] == e)
      			return i + 1; //注意要求是返回次序
      	}
      	return -1; //查找失败,该元素不存在
      }
      

完整代码

//构造数据元素
#define MaxSize 10
typedef struct {
	int data[MaxSize];
	int length;
}SqList;
//数据元素初始化
void InitList(SqList &L) {
	for (int i = 0; i < MaxSize; i++)
		L.data[i] = 0;
	L.length = 0;
}
//在第i个位置(次序)上插入元素e
bool ListInsert(SqList &L, int i, int e) {
	if (L.length >= MaxSize) //存储空间已满
		return false;
	if (i<1 || i>L.length + 1) //插入位置不合理
		return false;
	for (int j = L.length; j >= i; j--)
		L.data[j] = L.data[j - 1]; //后移
	L.data[i - 1] = e; //次序i,即下标i-1
	L.length++;
	return true;
}
//将第i位元素删除,并获取被删除的这个元素
bool ListDelete(SqList &L, int i, int &e) {
	if (i<1 || i>L.length)
		return false;
	e = L.data[i - 1];
	for (int j = i; j < L.length; j++) {
		L.data[j - 1] = L.data[j]; //前移
	}
	L.length--;
	return true;
}
//查找-按位查找第i个元素(次序)
int GetElem(SqList L, int i) {
	return L.data[i - 1];
}
//查找-按值查找元素值为e的第一个出现的元素,返回其次序
int LocateElem(SqList L, int e) {
	for (int i = 0; i < L.length; i++) {
		if (L.data[i] == e)
			return i + 1; //注意要求是返回次序
	}
	return -1; //查找失败,该元素不存在
}

上述用struct定义数据元素的结构中固定开辟(静态分配)了指定大小MaxSize大小的数组来存放data,这么做的弊端:如果MaxSize太大,则会造成开辟了很多不必要的空间,导致空间的浪费;如果MaxSize太小,当数据超过该最大容量时,就无法再使用了,因此,动态分配是对于该问题的优化。

  • c语言提供malloc和free函数(头文件stdlib.h)来动态申请和释放内存空间。(注意要对malloc的返回值强制类型转换)

  • c++提供new和delete运算符来动态申请和释放内存空间。

动态分配实现顺序表

#include<stdlib.h>

#define InitSize 10
typedef struct {
	int* data;
	int maxSize;  //当前最大容量
	int length;  //当前长度
}SqList;

//初始化
void InitList(SqList &L) {
	L.data = (int*)malloc(InitSize * sizeof(int)); //c++可替换使用new:  L.data=new int[InitSize];
	L.length = 0;
	L.maxSize = InitSize;
}

//动态扩容功能(重新开辟一块更大的空间--数据迁移至新空间--销毁原内存)
void IncreaseSize(SqList &L, int len) {
	int* p = L.data;
	L.data = (int*)malloc((L.maxSize + len) * sizeof(int));//重新开辟一块更大的空间
    //c++可替换使用new:  L.data=new int[L.maxSize+len];
	for (int i = 0; i < L.length; i++)
		L.data[i] = p[i];  //数据迁移至新空间
	L.maxSize += len;  //更新最大容量值
	free(p);  //销毁原内存,c++可替换使用delete:  delete p;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

鸭梨大妈

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值