数据结构与算法-线性表

一、线性表-动态扩容数组

  优点:可按数据元素的序号随机存储,也即可按照索引快速查找某元素。
  缺点:插入和删除操作耗时。
  动态扩容原理
     1) 若arr->size >= arr->capacity, 则开辟比capacity更大的空间;
     2) 将原空间中的元素拷贝至新的空间;
     3) 释放旧空间后,链表中的数据指针指向新开辟的空间。

1.1 仅存放整型元素的动态数组

  实现功能
     1) 初始化动态数组-DynamicArray* Init_DynamicArray();
     2) 向动态数组中插入整型元素-void InsertValue_DynamicArray(DynamicArray arr, int data);
     3) 删除指定位置的元素/删除特定值的元素- void RemoveValueByValue_DynamicArray(DynamicArray
arr, int pos);/void RemoveValueByValue_DynamicArray(DynamicArray* arr, int data);
     4) 返回动态数组的元素个数和容量 int Size_DynamicArray(DynamicArray* arr);/int Capacity_DynamicArray(DynamicArray* arr);
     5) 释放动态数组- void FreeSpace_DynamicArray(DynamicArray* arr);

   1.1.1 存放整型元素的动态数组存储结构

  仅存放整型元素的动态数组存储结构如下图所示,用链表维护动态数组的相关属性,如动态数组中的元素个数(DynamicArray.size)和动态数组的容量(DynamicArray.capacity)。
在这里插入图片描述

   1.1.2 代码
// 头文件DynamicArray.h
#ifndef DYNAMICARRAY_H
#define DYNAMICARRAY_H
#include<stdlib.h>
#include<stdio.h>

// 用链表维护动态扩容数组的相关参数
typedef struct DYNAMICARRAY {
	// 用指针数组存放数据的地址
	int* addr;
	// 元素的个数
	int size;
	// 动态数组的容量
	int capacity;
}DynamicArray;

// 动态数据组初始化 
DynamicArray* Init_DynamicArray();

// 插入数据
void InsertValue_DynamicArray(DynamicArray *arr, int data);

// 删除指定位置的数据
void RemoveValueByPos_DynamicArray(DynamicArray* arr, int pos);

// 根据值删除元素
void RemoveValueByValue_DynamicArray(DynamicArray* arr, int data);

// 返回数组的容量和尺寸
int Size_DynamicArray(DynamicArray* arr);

// 返回数组的容量
int Capacity_DynamicArray(DynamicArray* arr);

// 打印数组
void Print_DynamicArray(DynamicArray* arr);

// 清空数组
void Clear_DynamicArray(DynamicArray* arr);

// 释放数组内存
void FreeSpace_DynamicArray(DynamicArray* arr);

#endif // !DYNAMICARRAY_H
// DynamicArray.c
// DynamicArray.c为头文件DynamicArray.h中所申明函数的实现。
#include"DynamicArray.h"
// 动态数据组初始化 
DynamicArray* Init_DynamicArray() {
	// 初始化动态数组
	DynamicArray* arr = (DynamicArray*)malloc(sizeof(DynamicArray));
	if (arr == NULL) {
		printf("内存分配失败!");
		return NULL;
	}
	else {
		arr->size = 0;
		arr->capacity = 10;
		arr->addr = (int*)malloc(sizeof(int) * arr->capacity);
		return arr;
	}
}

// 插入数据
void InsertValue_DynamicArray(DynamicArray* arr, int data) {
	// 判断边界情况
	if (arr == NULL) {
		printf("数组arr为空,请初始化动态数组: arr\n");
		return;
	}
	// 如果当前元素个数超出动态数组的容量
	if (arr->size >= arr->capacity) {
		// 更新动态数组的容量
		arr->capacity = arr->capacity * 2;
		// 开辟新空间
		int* temp = (int*)malloc(sizeof(int) * arr->capacity);
		// 将旧空间的元素拷贝至新开辟的空间中
		for (int i = 0; i < arr->size; i++) {
			temp[i] = arr->addr[i];
		}
		// 销毁旧空间
		free(arr->addr);
		arr->addr = temp;
	}
	// 插入新的元素
	arr->addr[arr->size] = data;
	arr->size++;
}

// 删除指定位置的数据
void RemoveValueByPos_DynamicArray(DynamicArray* arr, int pos) {
	// 判断数组arr,和位置pos是否合法
	if (arr == NULL || pos >= arr->size || pos < 0) {
		// 传入参数有误
		printf("传入参数有误,请检查参数\n");
		return;
	}
	// 将pos位置后的元素往前移动
	for (int i = pos; i < arr->size - 1; i++) {
		arr->addr[i] = arr->addr[i + 1];
	}
	// arr->size--
	arr->size--;
}

// 根据传入的值删除数据
void RemoveValueByValue_DynamicArray(DynamicArray* arr, int data) {
	// 判断数组arr,和位置pos是否合法
	if (arr == NULL) {
		// 传入参数有误
		printf("传入参数有误,请检查参数\n");
		return;
	}

	// 找到arr中第一个元素为data的位置
	for (int i = 0; i < arr->size; i++) {
		if (arr->addr[i] == data) {
			if (i == arr->size - 1) {
				arr->size--;
				return;
			}
			else {
				for (int j = i; j < arr->size - 1; j++) {
					arr->addr[j] = arr->addr[j + 1];
				}
				arr->size--;
				return;
			}
		}
	}
	// arr->size--
}

// 返回数组的容量和尺寸
int Size_DynamicArray(DynamicArray* arr) {
	// 判断边界情况
	if (arr == NULL) {
		printf("数组为空,请初始化数组\n");
		return -1;
	}
	return arr->size;
}

// 返回数组的容量
int Capacity_DynamicArray(DynamicArray* arr) {
	// 判断边界情况
	if (arr == NULL) {
		printf("数组为空,请初始化数组\n");
		return -1;
	}
	return arr->capacity;
}

// 打印数组
void Print_DynamicArray(DynamicArray* arr) {
	if (arr == NULL) return;
	for (int i = 0; i < arr->size; i++) {
		printf("%d ", arr->addr[i]);
	}
	printf("\n");
}

// 清空数组
void Clear_DynamicArray(DynamicArray* arr) {
	if (arr == NULL) return;
	arr->size = 0;
}

// 释放数组内存
void FreeSpace_DynamicArray(DynamicArray* arr) {
	if (arr == NULL) return;
	// 由内往外释放
	if (arr->addr) free(arr->addr);
	free(arr);
}
// main.c 完成对动态数组中相关功能的测试。
#include"DynamicArray.h"
#include <time.h>

#define MAX_NUM 10

void GenRandomData(DynamicArray *arr, int len) {
	if (arr == NULL || len < 0) return;
	srand((unsigned int)time(NULL));
	for (int i = 0; i < len; i++) {
		InsertValue_DynamicArray(arr, rand() % len);
	}
}

int main() {
	// 初始化数组
	DynamicArray* arr = Init_DynamicArray();

	// 向动态数组中插入元素
	/*for (int i = 0; i < 20; i++) {
		InsertValue_DynamicArray(arr, i);
	}*/
	// 随机插入元素
	GenRandomData(arr, MAX_NUM);

	// 删除前的数组
	printf("根据位置删除前的数组:\n");
	Print_DynamicArray(arr);
	// 根据位置删除元素
	RemoveValueByPos_DynamicArray(arr, 8);
	// 删除后的数组
	printf("根据位置删除后的数组:\n");
	Print_DynamicArray(arr);

	// 根据值删除数组
	RemoveValueByValue_DynamicArray(arr, 0);
	printf("根据元素删除后的数组:\n");
	Print_DynamicArray(arr);
	printf("\n=====================\n");
	// 数组大小
	printf("数组元素个数:%d\n", Size_DynamicArray(arr));
	// 数组容量
	printf("数组容量:%d\n", Capacity_DynamicArray(arr));
	
	// 清空数组
	Clear_DynamicArray(arr);
	printf("\n清空后的动态数组:");
	// 数组大小
	printf("数组元素个数:%d\n", Size_DynamicArray(arr));
	// 数组容量
	printf("数组容量:%d\n", Capacity_DynamicArray(arr));

	// 释放空间
	FreeSpace_DynamicArray(arr);
	return 0;
}
   1.1.3 运行结果

     运行结果如下所示,
动态数组测试结果

1.2 存放任意类型数据的动态数组

   1.2.1 存放任意类型数据的动态数组存储结构

  在1.1小节上进行扩展实现线性存储任意类型的数据的动态数组,其存储的数据结构如下图所示,ArrayNode结点的viod*data可以指向任意类型的数据。
在这里插入图片描述

   1.2.2 代码
// 头文件DynamicArray.h
#ifndef DYNAMICARRAY_H
#define DYNAMICARRAY_H
#include<stdlib.h>
#include<stdio.h>


// 打印函数-由用户自己提供打印的接口,
typedef void (*PRINT)(void*);
// 比较函数
typedef int (*COMPARE)(void*, void*);

typedef struct ARRAYNODE {
	void* data;
}ArrayNode;
// 用链表维护动态扩容数组的相关参数
typedef struct DYNAMICARRAY {
	// 用指针数组存放数据的地址
	ArrayNode* arrNode;
	//void* data;
	// 元素的个数
	int size;
	// 动态数组的容量
	int capacity;
}DynamicArray;

// 动态数据组初始化 
DynamicArray* Init_DynamicArray();

// 插入数据
void InsertData_DynamicArray(DynamicArray* arr, void* data);

// 删除指定位置的数据
void RemoveValueByPos_DynamicArray(DynamicArray* arr, int pos);

// 根据值删除元素
void RemoveValueByValue_DynamicArray(DynamicArray* arr, void* data, COMPARE compare);

// 返回数组的容量和尺寸
int Size_DynamicArray(DynamicArray* arr);

// 返回数组的容量
int Capacity_DynamicArray(DynamicArray* arr);

// 打印数组
void Print_DynamicArray(DynamicArray* arr, PRINT print);

// 清空数组
void Clear_DynamicArray(DynamicArray* arr);

// 释放数组内存
void FreeSpace_DynamicArray(DynamicArray* arr);

#endif // !DYNAMICARRAY_H
// DynamicArray.c
#include"DynamicArray.h"

// 动态数据组初始化 
DynamicArray* Init_DynamicArray() {
	// 初始化动态数组
	DynamicArray* arr = (DynamicArray*)malloc(sizeof(DynamicArray));
	if (arr == NULL) {
		printf("内存分配失败!\n");
		return NULL;
	}
	else {
		arr->size = 0;
		arr->capacity = 3;
		arr->arrNode = (ArrayNode*)malloc(sizeof(ArrayNode) * arr->capacity);
		return arr;
	}
}

// 插入数据
void InsertData_DynamicArray(DynamicArray* arr, void* data) {
	// 判断边界情况
	if (arr == NULL) {
		printf("数组arr为空,请初始化动态数组: arr\n");
		return;
	}
	// 如果当前元素个数超出动态数组的容量
	if (arr->size >= arr->capacity) {
		// 更新容量
		arr->capacity = arr->capacity * 2;
		// 开辟新空间
		ArrayNode* NewArrayNode = (ArrayNode*)malloc(sizeof(ArrayNode) * arr->capacity );
		// 将旧空间的元素拷贝至新开辟的空间中
		for (int i = 0; i < arr->size; i++) {
			NewArrayNode[i].data = arr->arrNode[i].data;
		}
		// 销毁旧空间
		free(arr->arrNode);
		arr->arrNode = NewArrayNode;
	}
	// 插入新的元素
	arr->arrNode[arr->size].data = data;
	arr->size++;
}

// 删除指定位置的数据
void RemoveValueByPos_DynamicArray(DynamicArray* arr, int pos) {
	// 判断数组arr,和位置pos是否合法
	if (arr == NULL || pos >= arr->size || pos < 0) {
		// 传入参数有误
		printf("传入参数有误,请检查参数\n");
		return;
	}
	// 将pos位置后的元素往前移动
	for (int i = pos; i < arr->size - 1; i++) {
		arr->arrNode[i].data = arr->arrNode[i + 1].data;
	}
	// arr->size--
	arr->size--;
}

// 根据传入的值删除数据
void RemoveValueByValue_DynamicArray(DynamicArray* arr, void* data, COMPARE compare) {
	// 判断数组arr,和位置pos是否合法
	if (arr == NULL) {
		// 传入参数有误
		printf("传入参数有误,请检查参数\n");
		return;
	}

	// 找到arr中第一个元素为data的位置
	for (int i = 0; i < arr->size; i++) {
		if (compare(arr->arrNode[i].data, data) == 1) {
			if (i == arr->size - 1) {
				arr->size--;
				return;
			}
			else {
				for (int j = i; j < arr->size-1; j++) {
					arr->arrNode[j].data = arr->arrNode[j + 1].data;
				}
				// 元素个数减1
				arr->size--;
				return;
			}
		}
	}
}

// 返回数组的容量和尺寸
int Size_DynamicArray(DynamicArray* arr) {
	// 判断边界情况
	if (arr == NULL) {
		printf("数组为空,请初始化数组\n");
		return -1;
	}
	return arr->size;
}

// 返回数组的容量
int Capacity_DynamicArray(DynamicArray* arr) {
	// 判断边界情况
	if (arr == NULL) {
		printf("数组为空,请初始化数组\n");
		return -1;
	}
	return arr->capacity;
}

// 打印数组
void Print_DynamicArray(DynamicArray* arr, PRINT print) {
	if (arr == NULL) return;
	for (int i = 0; i < arr->size; i++) {
		print(arr->arrNode[i].data);
	}
	printf("\n");
}

// 清空数组
void Clear_DynamicArray(DynamicArray* arr) {
	if (arr == NULL) return;
	arr->size = 0;
}

// 释放数组内存
void FreeSpace_DynamicArray(DynamicArray* arr) {
	if (arr == NULL) return;
	// 由内往外释放
	if (arr->arrNode) free(arr->arrNode);
	free(arr);
}
// main.c
#include"DynamicArray.h"
#include<string.h>
#include <time.h>

#define MAX_NUM 10

typedef struct PERSON {
	char name[64];
	int age;
}Person;


// 打印函数
void myPrint(void* data) {
	Person* p = (Person*)data;
	printf("姓名:%s,年龄:%d\n", p->name, p->age);
}

// 比较函数, data1为动态数组中的元素,data2为用户传入的数据
int compare(void* data1, void* data2) {
	Person* p1 = (Person*)data1;
	Person* p2 = (Person*)data2;
	// 如果姓名和年龄均相等,则判定data1与data2相等
	if (!strcmp(p1->name, p2->name) && p1->age == p2->age) return 1;
	return -1;
}

int main() {
	// 初始化结构体
	Person p1 = { "aaa", 20 }, p2 = { "bbb", 30 }, p3 = { "ccc", 40 }, p4 = {"ddd", 50};

	// 初始化数组
	DynamicArray* arr = Init_DynamicArray();

	// 插入结构体数据
	InsertData_DynamicArray(arr, &p1);
	InsertData_DynamicArray(arr, &p2);
	InsertData_DynamicArray(arr, &p3);
	InsertData_DynamicArray(arr, &p4);

	// 删除前的数组
	printf("删除前的数组:\n");
	Print_DynamicArray(arr, myPrint);

	// 根据位置删除元素
	//RemoveValueByPos_DynamicArray(arr, 0);
	// 删除后的数组
	printf("根据位置删除后的数组:\n");
	Print_DynamicArray(arr, myPrint);

	// 根据值删除数组
	Person p5 = {"ddd", 50};
	RemoveValueByValue_DynamicArray(arr, &p5, compare);
	printf("根据元素删除后的数组:\n");
	Print_DynamicArray(arr, myPrint);


	printf("\n=====================\n");
	// 数组大小
	printf("数组元素个数:%d\n", Size_DynamicArray(arr));
	// 数组容量
	printf("数组容量:%d\n", Capacity_DynamicArray(arr));
	Clear_DynamicArray(arr);
	printf("\n清空后的动态数组:");
	// 数组大小
	printf("数组元素个数:%d\n", Size_DynamicArray(arr));
	// 数组容量
	printf("数组容量:%d\n", Capacity_DynamicArray(arr));


	// 释放空间
	FreeSpace_DynamicArray(arr);

	return 0;
}
   1.2.3 运行结果

     向动态数组中插入结构体数据,运行结果如下所示,
在这里插入图片描述

二、参考链接

   1、数据结构与算法知识点总结
   2、C++教程

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值