【C语言】实现动态顺序表的增删改查等操作

本文介绍了动态顺序表的概念,作为线性结构的一种,动态顺序表使用动态开辟的数组存储数据元素。文章详细讲解了如何用C语言实现动态顺序表的初始化、尾插尾删、头插头删、任意位置插入删除、查找、修改、计数、扩容、判空、清空、销毁及打印等操作,并提供了SeqList.h、SeqList.c和test.c三个文件的代码实现。测试结果显示代码运行正确。
摘要由CSDN通过智能技术生成

在开始之前,我们先来了解一些基本概念:

线性结构
  1. 线性结构是一种广泛使用的数据结构,其特点是数据元素之间存在一对一的对应关系。
  2. 常见的线性结构有数组、线性表、栈、队列、串…
顺序表
  • 顺序表是一种线性表,可见其视为数组,就是用一段物理地址连续的存储单元依次存储数据元素的线性结构。一般可分为静态顺序表和动态顺序表。
    • 静态顺序表:使用定长数组存储。这就导致数组长度N定大了,空间开多了造成浪费;N定小了,空间开小了又不够用。因此它只适用于确定知道需要存多少数据的场景。

    • 动态顺序表:使用动态开辟的数组存储。这样我们就可以根据需要动态的分配空间大小,因此在现实中基本都是使用动态顺序表。

代码实现

接下来,我们就要实现动态顺序表的相关操作,主要包括:

  1. 初始化顺序表
  2. 顺序表尾插、尾删
  3. 顺序表头插、头删
  4. 顺序表任意位置插入、任意位置删除
  5. 顺序表元素查找
  6. 删除顺序表中第一个值为data的元素
  7. 删除顺序表中所有值为data的元素
  8. 修改顺序表中某一元素的数值
  9. 顺序表元素个数、容量查询
  10. 顺序表扩容、判空、清空、销毁及打印
SeqList.h头文件:

在这里完成动态顺序表的结构体定义以及上述相关操作的函数声明。

#pragma once

typedef int DataType;

typedef struct SeqList{
	DataType* _array;
	int _capacity;  //顺序表的总大小
	int _size;      //顺序表中有效元素的个数
}SeqList, *PSeq;

//顺序表的初始化
void SeqListInit(PSeq ps, int capacity);

//在顺序表的尾部插入值为data的元素
void SeqListPushBack(PSeq ps, DataType data);
//删除顺序表最后一个元素
void SeqListPopBack(PSeq ps);

//在顺序表的头部插入值为data的元素
void SeqListPushFront(PSeq ps, DataType data);
//删除顺序表头部的元素
void SeqListPopFront(PSeq ps);

//在顺序表pos位置插入值为data的元素
void SeqListInsert(PSeq ps, int pos, DataType data);
//删除顺序表中pos位置上的元素
void SeqListErase(PSeq ps, int pos);

// 在顺序表中查找值为data的元素,找到返回该元素在顺序表中的下标,否则返回-1 
int SeqListFind(PSeq ps, DataType data);

// 删除顺序表中第一个值为data的元素 
void SeqListRemove(PSeq ps, DataType data);

//删除顺序表中所有值为data的元素
void SeqListRemoveAll(PSeq ps, DataType data);

//修改顺序表pos位置元素的数值
void SeqListModify(PSeq ps, int pos, DataType data);

// 返回顺序表中有效元素的个数 
int SeqListSize(PSeq ps);

// 返回顺序表的容量大小 
int SeqListCapacity(PSeq ps);

// 顺序表的扩容 
void CheckCapacity(PSeq ps);

// 检测顺序表是否为空,如果为空返回非0值,非空返回0 
int SeqListEmpty(PSeq ps);

// 将顺序表中的元素清空 
void SeqListClear(PSeq ps);

// 销毁顺序表 
void SeqListDestroy(PSeq ps); 

//打印顺序表
void SeqListPrint(PSeq ps);

void TestSeqList();

SeqList.c文件:

此为动态顺序表各操作函数的具体代码。

#include"SeqList.h"
#include<malloc.h>
#include<assert.h>
#include<stdio.h>

//顺序表的初始化
void SeqListInit(PSeq ps, int capacity){
	ps->_array = (DataType*)malloc(sizeof(DataType)*capacity);
	//申请空间失败
	if (ps->_array == NULL){
		assert(0);
		return;
	}
	ps->_capacity = capacity;
	ps->_size = 0;
}

//在顺序表的尾部插入值为data的元素
void SeqListPushBack(PSeq ps, DataType data){
	assert(ps);
	//检测是否需要扩容
	CheckCapacity(ps);
	ps->_array[ps->_size] = data;
	ps->_size++;
}

//删除顺序表最后一个元素
void SeqListPopBack(PSeq ps){
	assert(ps);
	//保证顺序表中有元素
	if (SeqListEmpty(ps)){
		return;
	}
	ps->_size--;
}

//在顺序表的头部插入值为data的元素
void SeqListPushFront(PSeq ps, DataType data){
	assert(ps);
	//检测是否需要扩容
	CheckCapacity(ps);
	//将顺序表中所有元素统一向后搬移一个位置(从后往前)
	for (int i = ps->_size - 1; i >= 0; i--){
		ps->_array[i + 1] = ps->_array[i];
	}
	ps->_array[0] = data;
	ps->_size++;
}

//删除顺序表头部的元素
void SeqListPopFront(PSeq ps){
	assert(ps);
	//保证顺序表中有元素
	if (SeqListEmpty(ps)){
		return;
	}
	//将顺序表中的元素统一向前搬移一个位置(从前往后)
	for (int i = 1; i < ps->_size; i++){
		ps->_array[i - 1] = ps->_array[i];
	}
	ps->_size--;
}

//在顺序表pos位置插入值为data的元素
void SeqListInsert(PSeq ps, int pos, DataType data){
	assert(ps);
	//检测pos是否有效(此处ps->_size可以取到,类似于尾插)
	if (pos<0 || pos>ps->_size){
		return;
	}
	//检测是否需要扩容
	CheckCapacity(ps);
	for (int i = ps->_size - 1; i >= pos; i--){
		ps->_array[i + 1] = ps->_array[i];
	}
	ps->_array[pos] = data;
	ps->_size++;
}

//删除顺序表中pos位置上的元素
void SeqListErase(PSeq ps, int pos){
	assert(ps);
	//检测pos是否有效
	if (pos<0 || pos>=ps->_size){
		return;
	}
	//保证顺序表中有元素
	if (SeqListEmpty(ps)){
		return;
	}
	for (int i = pos + 1; i < ps->_size; i++){
		ps->_array[i - 1] = ps->_array[i];
	}
	ps->_size--;
}

// 在顺序表中查找值为data的元素,找到返回该元素在顺序表中的下标,否则返回-1 
int SeqListFind(PSeq ps, DataType data){
	assert(ps);
	for (int i = 0; i < ps->_size; i++){
		if (ps->_array[i] == data){
			return i;
		}
	}
	return -1;
}

// 删除顺序表中第一个值为data的元素 
void SeqListRemove(PSeq ps, DataType data){
	assert(ps);
	//利用已有函数来实现:SeqListFind函数找到data元素的位置,SeqListErase函数删除该位置的元素
	SeqListErase(ps, SeqListFind(ps, data));
}

//删除顺序表中所有值为data的元素
void SeqListRemoveAll(PSeq ps, DataType data){
	assert(ps);
	int pos = -1;
	//重复调用SeqListFind、SeqListErase函数,找到值为data的元素就进行删除
	while ((pos = SeqListFind(ps, data)) != -1){
		SeqListErase(ps, pos);
	}
}

//修改顺序表pos位置元素的数值
void SeqListModify(PSeq ps, int pos, DataType data){
	assert(ps);
	//检测pos是否有效
	if (pos<0 || pos>ps->_size){
		return;
	}
	//保证顺序表中有元素
	if (SeqListEmpty(ps)){
		return;
	}
	ps->_array[pos] = data;
}

// 返回顺序表中有效元素的个数 
int SeqListSize(PSeq ps){
	assert(ps);
	return ps->_size;
}

// 返回顺序表的容量大小 
int SeqListCapacity(PSeq ps){
	assert(ps);
	return ps->_capacity;
}

// 顺序表的扩容 
void CheckCapacity(PSeq ps){
	assert(ps);
	//顺序表中已没有空间
	if (ps->_size == ps->_capacity){
		int newCapacity = ps->_capacity * 2;
		//申请新空间
		int* pTemp = (DataType*)malloc(sizeof(DataType)*newCapacity);
		//申请新空间失败
		if (pTemp == NULL){
			assert(0);
			return;
		}
		//拷贝元素至新空间
		for (int i = 0; i < ps->_size; i++){
			pTemp[i] = ps->_array[i];
		}
		//释放旧空间
		free(ps->_array);
		//更新
		ps->_size = pTemp;
		ps->_capacity = newCapacity;
	}
}

// 检测顺序表是否为空,如果为空返回非0值,非空返回0 
int SeqListEmpty(PSeq ps){
	assert(ps);
	if (ps->_size == 0){
		return 1;
	}
	return 0;
}

// 将顺序表中的元素清空 
void SeqListClear(PSeq ps){
	assert(ps);
	ps->_size = 0;
}

// 销毁顺序表 
void SeqListDestroy(PSeq ps){
	if (ps->_array){
		free(ps->_array);
		ps->_array = NULL;
		ps->_capacity = 0;
		ps->_size = 0;
	}
}

//打印顺序表
void SeqListPrint(PSeq ps){
	assert(ps);
	for (int i = 0; i < ps->_size; i++){
		printf("%d ", ps->_array[i]);
	}
	printf("\n");
}

void TestSeqList(){
	SeqList s;
	SeqListInit(&s, 10);
	
	SeqListPushBack(&s, 1);
	SeqListPushBack(&s, 2);
	SeqListPushBack(&s, 3);
	SeqListPushBack(&s, 4);
	SeqListPushBack(&s, 5);
	SeqListPrint(&s);
	
	SeqListPopBack(&s, 5);
	SeqListPrint(&s);

	SeqListPushFront(&s, 0);
	SeqListPrint(&s);

	SeqListPopFront(&s, 0);
	SeqListPrint(&s);

	SeqListInsert(&s, 2, 9);
	SeqListPrint(&s);

	int pos = SeqListFind(&s, 9);
	printf("pos = %d\n", pos);

	SeqListModify(&s, pos, 4);
	SeqListPrint(&s);
	
	//SeqListErase(&s, pos);
	//SeqListPrint(&s);

	//SeqListRemove(&s, 4);
	//SeqListPrint(&s);

	SeqListRemoveAll(&s, 4);
	SeqListPrint(&s);

	printf("顺序表中有效元素的个数为%d\n", SeqListSize(&s));
	printf("顺序表的容量大小为%d\n", SeqListCapacity(&s));

	SeqListDestroy(&s);
}

test.c文件:

即主函数文件,完成测试。

#include"SeqList.h"
#include<stdlib.h>

int main(){
	TestSeqList();
	system("pause");
	return 0;
}

在TestSeqList()函数中测试了增删改查等基本操作,代码运行无误,结果如下:
在这里插入图片描述

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值