数据结构day08---动态数组和单项链表

1.数据结构概念

在这里插入图片描述
在这里插入图片描述

2.动态数组

2.1 线性表基本概念
在这里插入图片描述
2.2 线性表的顺序存储(动态数组)
在这里插入图片描述
在这里插入图片描述

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stddef.h>//可计算偏移量

//1.先定义所需要的数据信息结构
struct dynamicArray {
	//数组存储元素的空间的首地址
	void** addr;//4个字节
	//存储数据的内存中最大能容纳多少元素
	int capacity;//容量
	//当前存储数据的内存中有多少个元素
	int size;
};

//初始化数组
struct dynamicArray* init_dynamicArray(int capacity) {
	if (capacity <= 0)
		return NULL;
	struct dynamicArray* arr = malloc(sizeof(struct dynamicArray));
	if (NULL == arr)
		return NULL;
	arr->capacity = capacity;
	arr->addr = malloc(sizeof(void*) * arr->capacity);
	arr->size = 0;
	return arr;
}

//插入元素
void* insert_dynamicArray(struct dynamicArray* arr, int pos, void* data) {
	//存储数据的地址data
	if (NULL == arr)
		return;
	if (NULL == data)
		return;
	if (pos<0 || pos>arr->size)
		pos = arr->size;
	//判断空间是否足够
	if (arr->size >= arr->capacity) {
		//申请一块更大的内存空间
		int newCapacity = arr->capacity * 2;
		void** newSpace = malloc(sizeof(void*) * newCapacity);
		//将原来空间的数据拷贝到新空间
		memcpy(newSpace, arr->addr, sizeof(void*) * arr->capacity);
		//释放原来空间的内存
		free(arr->addr);
		//更新addr的指向
		arr->addr = newSpace;
		arr->capacity = newCapacity;
	}
	//移动元素,空出pos位置
	for (int i = arr->size - 1; i >= pos; --i) {
		arr->addr[i + 1] = arr->addr[i];
	}
	//将新元素插入到pos位置
	arr->addr[pos] = data;
	arr->size++;
}

//遍历
void forEach_dynamicArray(struct dynamicArray* arr, void(*_callback(void*))) {
	if (NULL == arr)
		return;
	if (NULL == _callback)
		return;
	for (int i = 0; i < arr->size; ++i) {
		_callback(arr->addr[i]);
	}
}

//位置删除
void remove_dynamicArray(struct dynamicArray* arr, int pos) {
	if (NULL == arr)
		return;
	if (pos<0 || pos>arr->size - 1)
		return;
	for (int i = pos; i < arr->size - 1; ++i) {
		arr->addr[i] = arr->addr[i + 1];
	}
	arr->size--;
}

//按值删除
void removeValue_dynamicArray(struct dynamicArray* arr, void* data, int(*compare)(void*, void*)) {
	//如果只有前两个地址形参,无法比较类型
	if (NULL == arr)
		return;
	if (NULL == data)
		return;
	if (NULL == compare)
		return;
	for (int i = 0; i < arr->size; ++i) {
		if (compare(arr->addr[i], data)) {
			//如果比较后两个元素相同,则删除该位置的元素
			remove_dynamicArray(arr, i);
			break;
		}
	}
}

//销毁数组,初始化中开辟的空间
void destroy_dynamicArray(struct dynamicArray* arr) {
	if (NULL == arr)
		return;
	if (arr->addr != NULL) {
		free(arr->addr);
		arr->addr = NULL;
	}
	free(arr);
	arr = NULL;
}

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

void myPrint(void* data) {
	struct Person* person = (struct Person*)data;
	printf("Name:%s Age:%d\n", person->name, person->age);
}

void myCompare(void* d1, void* d2) {
	struct Person* p1 = (struct Peson*)d1;
	struct Person* p2 = (struct Peson*)d2;
	return strcmp(p1->name, p2->name) == 0 && p1->age == p2->age;
}

void test(){
	//创建动态数组
	struct dynamicArray* da = init_dynamicArray(5);
	//数组添加元素
	struct Person p1 = { "aaa",10 };
	struct Person p2 = { "bbb",20 };
	struct Person p3 = { "ccc",30 };
	struct Person p4 = { "ddd",40 };
	struct Person p5 = { "eee",50 };
	struct Person p6 = { "fff",60 };
	insert_dynamicArray(da, 0, &p1);
	insert_dynamicArray(da, 0, &p2);
	insert_dynamicArray(da, 0, &p3);
	insert_dynamicArray(da, 1, &p4);
	insert_dynamicArray(da, 1, &p5);

	printf("capacity:%d\n", da->capacity);
	insert_dynamicArray(da, 100, &p6);//3 5 4 2 1 6
	printf("capacity:%d\n", da->capacity);

	forEach_dynamicArray(da, myPrint);

	printf("-----------------------------\n");
	remove_dynamicArray(da, 2);//3 5 2 1 6
	forEach_dynamicArray(da, myPrint);
	printf("-----------------------------\n");
	struct Person pDel = { "aaa",10 };
	removeValue_dynamicArray(da, &pDel, myCompare);
	forEach_dynamicArray(da, myPrint);

	//销毁
	destroy_dynamicArray(da);
}

int main(){
	test();
	return 0;
}

在这里插入图片描述

3.单向链表

版本一
在这里插入图片描述

//linkList.h
#pragma once
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>//可计算偏移量
#include <stdbool.h>

//为了在C++中能调用C写的函数
#ifdef __cplusplus
extern "C" {
#endif
	//链表节点数据类型
	struct linkNode {
		void* data;//数据域
		struct linkNode* next;
	};

	//链表数据类型
	struct LList {
		struct linkNode header;
		int size;
	};

	typedef void* linkList;//定义类型
	typedef void(*FOREACH)(void*);
	typedef int(*COMPARE)(void*, void*);//回调函数
	//初始化链表
	linkList* init_linkList();
	//插入节点
	void insert_linkList(linkList list, int pos, void* data);
	//遍历链表
	void forEach_linkList(linkList list, FOREACH myForEach);
	//按位置删除
	void remove_linkList(linkList list, int pos);
	//按值删除
	void removeValue_linkList(linkList list, void* data, COMPARE compare);
	//清空链表
	void clear_linkList(linkList list);
	//大小
	int getSize_linkList(linkList list);
	//销毁链表
	void destroy_linkList(linkList list);
#ifdef __cplusplus
}
#endif
//linkList.c
#include "linkList.h"

//初始化链表
linkList* init_linkList() {
	struct LList* list = malloc(sizeof(struct LList));
	if (NULL == list)
		return NULL;
	list->header.data = NULL;
	list->header.next = NULL;
	list->size = 0;
	return list;
}

//插入节点
void insert_linkList(linkList list, int pos, void* data) {
	if (NULL == list)
		return;
	if (NULL == data)
		return;
	struct LList* myList = (struct LList*)list;
	if (pos<0 || pos>myList->size - 1) {
		pos = myList->size;
	}
	//查找插入位置
	struct linkNode* pCur = &(myList->header);//指向头结点
	for (int i = 0; i < pos; ++i) {
		pCur = pCur->next;
	}

	//创建新节点
	struct linkNode* newNode = malloc(sizeof(struct linkNode));
	newNode->data = data;
	newNode->next = NULL;
	//新节点插入到链表中
	newNode->next = pCur->next;
	pCur->next = newNode;
	myList->size++;
}

//遍历链表
void forEach_linkList(linkList list, FOREACH myForEach) {
	if (NULL == list)
		return;
	if (NULL == myForEach)
		return;
	struct LList* myList = (struct LList*)list;
	struct linkNode* pCur = myList->header.next;
	while (pCur != NULL)
	{
		myForEach(pCur->data);
		pCur = pCur->next;
	}
}

//按位置删除
void remove_linkList(linkList list, int pos) {
	if (NULL == list)
		return;
	struct LList* myList = (struct LList*)list;
	if (pos <0 || pos>myList->size - 1)
		return;
	//找位置
	struct linkNode* pCur = &(myList->header);
	for (int i = 0; i < pos; ++i) {
		pCur = pCur->next;
	}
	//先保存待删除节点
	struct linkNode* pDel = pCur->next;
	//重新建立待删除节点的前驱和后继节点关系
	pCur->next = pDel->next;
	//释放删除节点内存
	free(pDel);
	pDel = NULL;
	myList->size--;
}

//按值删除
void removeValue_linkList(linkList list, void* data, COMPARE compare) {
	if (NULL == list)
		return;
	if (NULL == data)
		return;
	if (NULL == compare)
		return;
	struct LList* myList = (struct LList*)list;
	//辅助指针变量
	struct linkNode* pPrev = &(myList->header);
	struct linkNode* pCur = pPrev->next;
	while (pCur != NULL)
	{
		if (compare(pCur->data, data)) {
			//返回真则找到了
			pPrev->next = pCur->next;
			//释放删除节点内存
			free(pCur);
			pCur = NULL;
			myList->size--;
			break;
		}
		pPrev = pCur;
		pCur = pCur->next;
	}
}

//清空链表
void clear_linkList(linkList list) {
	if (NULL == list)
		return;
	//辅助指针变量
	struct LList* myList = (struct LList*)list;
	struct linkNode* pCur = myList->header.next;
	while (pCur != NULL) {
		//缓存下一节点的地址
		struct linkNode* pNext = pCur->next;
		//释放当前节点内存
		free(pCur);
		pCur = pNext;
	}
	myList->header.next = NULL;
	myList->size = 0;
}

//大小
int getSize_linkList(linkList list) {
	if (NULL == list)
		return -1;
	struct LList* myList = (struct LList*)list;
	return myList->size;
}

//销毁链表
void destroy_linkList(linkList list) {
	if (NULL == list)
		return;
	//清空链表
	clear_linkList(list);
	free(list);
	list = NULL;
}
//main.c
#include"linkList.h"
struct Person {
	char name[64];
	int age;
};

void myPrint(void* data) {
	struct Person* person = (struct Person*)data;
	printf("Name:%s Age:%d\n", person->name, person->age);
}

int myCompare(void* d1, void* d2) {
	struct Person* p1 = (struct Person*)d1;
	struct Person* p2 = (struct Person*)d2;
	return strcmp(p1, p2) == 0 && p1->age == p2->age;
}

void test() {
	//创建链表
	linkList list = init_linkList();
	//创建数据
	struct Person p1 = { "aaa",10 };
	struct Person p2 = { "bbb",20 };
	struct Person p3 = { "ccc",30 };
	struct Person p4 = { "ddd",40 };
	struct Person p5 = { "eee",50 };
	struct Person p6 = { "fff",60 };
	
	//插入数据
	insert_linkList(list, 0, &p1);
	insert_linkList(list, 0, &p2);//2 3 1
	insert_linkList(list, 1, &p3);
	insert_linkList(list, 2, &p4);//2 3 4 1
	insert_linkList(list, 20, &p5);//2 3 4 1 5
	insert_linkList(list, 3, &p6);//2 3 4 6 1 5

	//打印数据
	forEach_linkList(list, myPrint);
	printf("------------------------------\n");
	printf("List Size:%d\n", getSize_linkList(list));
	remove_linkList(list, 3);
	printf("------------------------------\n");
	forEach_linkList(list, myPrint);

	struct Person pDel = { "eee",50 };
	removeValue_linkList(list, &pDel, myCompare);
	printf("------------------------------\n");
	forEach_linkList(list, myPrint);

	//清空链表
	clear_linkList(list);
	printf("------------------------------\n");
	printf("List Size:%d\n", getSize_linkList(list));

	//销毁链表
	destroy_linkList(list);
}

int  main()
{
	test();
	return 0;
}

在这里插入图片描述
版本二
在这里插入图片描述

#pragma once
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>//可计算偏移量
#include <stdbool.h>

//链表节点数据结构
struct linkNode {
	struct linkNode* next;//每一个节点预留四个字节的指针
};

//链表结构体
struct LList {
	struct linkNode header;
	int size;
};

typedef void* linkList;

//初始化链表
linkList init_linkList() {
	struct LList* list = malloc(sizeof(struct LList));
	if (NULL == list)
		return NULL;
	list->header.next = NULL;
	list->size = 0;
	return list;
}

void insert_linkList(linkList list, int pos, void* data) {
	if (NULL == list)
		return;
	if (NULL == data)
		return;
	struct LList* myList = (struct LList*)list;
	struct linkNode* myNode = (struct linkNode*)data;
	if (pos<0 || pos>myList->size)
		pos = myList->size;
	//找位置,找到pos位置的前一个位置
	struct linkNode* pCur = &(myList->header);
	for (int i = 0; i < pos; ++i) {
		pCur = pCur->next;
	}
	//数据插入链表
	myNode->next = pCur->next;
	pCur->next = myNode;
	myList->size++;
}

void forEach_linkList(linkList list, void(*myForeach)(void*)) {
	if (NULL == list)
		return;
	if (NULL == myForeach)
		return;
	struct LList* myList = (struct LList*)list;
	struct linkNode* pCur = myList->header.next;
	while (pCur != NULL) {
		myForeach(pCur);
		pCur = pCur->next;
	}
}

//删除节点
void remove_linkList(linkList list, int pos) {
	if (NULL == list)
		return;
	struct LList* myList = (struct LList*)list;
	if (pos<0 || pos>myList->size-1)
		return;
	//辅助指针
	struct linkNode* pCur = &(myList->header);
	for (int i = 0; i < pos; ++i) {
		pCur = pCur->next;
	}
	//缓存待删除节点
	struct linkNode* pDel = pCur->next;
	//重新建立待删除节点的前驱和后继节点关系
	pCur->next = pDel->next;
	myList->size--;
}

void destroy_linkList(linkList list) {
	if (NULL == list)
		return;
	free(list);
	list = NULL;
}

struct Person {
	//这里若改为*node,则变成了4个字节,当为双向链表8个字节时,会改变用户数据
	struct linkNode node;
	char name[64];
	int age;
};

void myPrint(void* data) {
	struct Person* person = (struct Person*)data;
	printf("Name:%s Age:%d\n", person->name, person->age);
}

void test() {
	//初始化链表
	linkList list = init_linkList();

	//创建数据
	struct Person p1 = { NULL,"aaa",10 };
	struct Person p2 = { NULL,"bbb",20 };
	struct Person p3 = { NULL,"ccc",30 };
	struct Person p4 = { NULL,"ddd",40 };
	struct Person p5 = { NULL,"eee",50 };

	//插入数据
	insert_linkList(list, 0, &p1);
	insert_linkList(list, 0, &p2);
	insert_linkList(list, 0, &p3);
	insert_linkList(list, 0, &p4);
	insert_linkList(list, 0, &p5);

	//遍历
	forEach_linkList(list, myPrint);

	//删除
	remove_linkList(list, 3);

	printf("----------------------\n");
	forEach_linkList(list, myPrint);

	//销毁
	destroy_linkList(list);
}

int main() {
	test();
	return 0;
}

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值