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;
}