实现方式
以动态数组的方式实现,多了扩容的功能
顺序表特点
- 可以随机访问,查找和修改方便
- 添加和删除的开销大,可以会移动大量元素
- 扩充容量的开销大,会拷贝大量元素,增加时间和空间的开销,建议初始化时多申请一些
- 适合频繁查找的场景,不适合频繁增删的场景
设计数据结构
有三个元素
- 指向堆空间的指针
- 当前长度
- 数组容量
typedef struct Array {
int *_pdata;
int _size;
int _capacity;
}Array_t, *pArray_t;
动态数组的相关操作
- 容量(扩容、判空、判满)
- 初始化(申请堆空间)
- 销毁(销毁堆空间)
- 插入(尾部插入、有序插入)
- 删除(按值删除、尾部删除)
- 查找(按值查找)
- 修改(按值修改)
头文件 array.h
#ifndef __ARRAY_H__
#define __ARRAY_H__
typedef struct Array
{
int *_pdata;
int _size;
int _capacity;
}Array_t, *pArray_t;
int arr_empty(pArray_t parr);
int arr_full(pArray_t parr);
//初始化
void arr_init(pArray_t parr, int capacity);
//扩容
void arr_reallocate(pArray_t parr);
//增加
int arr_push_back(pArray_t parr, int val);
int arr_insert(pArray_t parr, int val);
//删除
int arr_erase(pArray_t parr, int val);
int arr_pop_back(pArray_t parr);
//查找
int* arr_find(pArray_t parr, int val);
//修改
int arr_modify(pArray_t parr, int oldval, int newval);
//销毁申请的堆空间
void arr_destory(pArray_t parr);
//展示数组所有元素
void arr_show(pArray_t parr);
#endif
实现文件 array.c
#include "array.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void arr_init(pArray_t parr, int capacity)
{
parr->_pdata = (int*)calloc(capacity, sizeof(int));
parr->_size = 0;
parr->_capacity = capacity;
}
void arr_show(pArray_t parr)
{
if (!arr_empty(parr)) {
printf("arr_data: ");
for (int i = 0; i < parr->_size; ++i) {
printf("%d ", parr->_pdata[i]);
}
printf("\n");
printf("arr_size: %d\n", parr->_size);
printf("arr_capacity: %d\n", parr->_capacity);
}
else {
printf("arr is empty!\n");
}
}
//扩容
void arr_reallocate(pArray_t parr)
{
if (arr_full(parr)) {
//保存旧数据
Array_t tmp = *parr;
//确定新容量
int newcapacity = 2 * tmp._capacity == 0 ? 1 : 2 * tmp._capacity;
//申请新空间
parr->_pdata = (int *)calloc(newcapacity, sizeof(int));
//拷贝数据
memcpy(parr->_pdata, tmp._pdata, tmp._size * sizeof(int));
parr->_capacity = newcapacity;
//释放旧空间
free(tmp._pdata);
tmp._pdata = NULL;
}
}
//增加, 有序
int arr_push_back(pArray_t parr, int val)
{
if (arr_full(parr)) {
arr_reallocate(parr);
}
//插在末尾
parr->_pdata[parr->_size++] = val;
return 0;
}
int arr_insert(pArray_t parr, int val)
{
if (arr_full(parr)) {
arr_reallocate(parr);
}
//空表时直接插入
//非空时,从后往前找到第一个小于等于插入值的,放其后,否则元素后移
//找不到时,放首位
if (arr_empty(parr)) {
parr->_pdata[parr->_size++] = val;
}
else {
int i = parr->_size - 1;
for (; i >= 0; --i) {
if (parr->_pdata[i] > val) {
parr->_pdata[i + 1] = parr->_pdata[i];
}
else {
parr->_pdata[i + 1] = val;
parr->_size++;
break;
}
}
if (val < parr->_pdata[0]) {
parr->_pdata[0] = val;
parr->_size++;
}
}
return 0;
}
//删除
int arr_erase(pArray_t parr, int val)
{
//空表
if (arr_empty(parr)) {
printf("Arr is empty, cannot erase!\n");
return -1;
}
//从头遍历,如果等于val, ++count, --size, 否则 arr[i - count] = arr[i]
int count = 0;
int size = parr->_size;
for (int i = 0; i < parr->_size; ++i) {
if (val == parr->_pdata[i]) {
++count;
--size;
}
else {
parr->_pdata[i - count] = parr->_pdata[i];
}
}
if (0 == count) {
printf("Not found, cannot erase!\n");
return -1;
}
else {
parr->_size = size;
return 0;
}
}
int arr_pop_back(pArray_t parr)
{
if (arr_empty(parr)) {
fprintf(stderr, "array is empty, cannot delete elem!\n");
return -1;
}
parr->_size--;
return 0;
}
//查找
int* arr_find(pArray_t parr, int val)
{
if (!arr_empty(parr)) {
for (int i = 0; i < parr->_size; ++i) {
if (val == parr->_pdata[i]) {
return &parr->_pdata[i];
}
}
}
return NULL;
}
//修改
int arr_modify(pArray_t parr, int oldval, int newval)
{
//空表
if (arr_empty(parr)) {
printf("arr is empty!\n");
return -1;
}
int *ret = arr_find(parr, oldval);
if (NULL == ret) {
printf("Not found, cannot modify!\n");
return -1;
}
else {
*ret = newval;
return 0;
}
}
int arr_empty(pArray_t parr)
{
return parr->_size == 0;
}
int arr_full(pArray_t parr)
{
return parr->_size == parr->_capacity;
}
void arr_destory(pArray_t parr)
{
if (parr->_pdata) {
free(parr->_pdata);
parr->_pdata = NULL;
}
}
测试文件 test_arr.c
#include "array.h"
#include <stdio.h>
#include <stdlib.h>
int main()
{
//申请数组
pArray_t arr = (pArray_t)malloc(sizeof(Array_t));
arr_init(arr, 10);
arr_show(arr);
for (int i = 0; i < 10; ++i) {
arr_push_back(arr, i + 3);
}
arr_show(arr);
printf("\n---------test arr_insert------------\n");
arr_insert(arr, 1);
arr_insert(arr, 10);
arr_show(arr);
printf("\n---------test arr_erase------------\n");
arr_erase(arr, 3);
arr_erase(arr, 10);
arr_show(arr);
printf("\n---------test arr_erase------------\n");
arr_pop_back(arr);
arr_pop_back(arr);
arr_show(arr);
//释放数组
arr_destory(arr);
free(arr);
arr = NULL;
return 0;
}