Day24.C提高(数据结构01)
001.动态数组简单实现
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
//1.先把所需要的数据信息结构定义下来
struct DynamicArray
{
//数组存储元素的空间的首地址
void** addr;
//存储数据的内存中最大能够容纳多少元素
int capacity;//容量
//当前存储数据的内存中有多少个元素
int size;
};
//初始化数组
int Init_DynamicArray(int capacity, struct DynamicArray** arr)
{
if (capacity == NULL)
{
return -1;
}
if (arr == NULL)
{
return -1;
}
struct DynamicArray* buf = malloc(sizeof(struct DynamicArray));
buf->capacity = capacity;
buf->addr = malloc(sizeof(void*) * buf->capacity);
buf->size = 0;
*arr = buf;
}
//插入元素
void Insert_DynamicArray(struct DynamicArray* arr, int pos, void* data)
{
if (NULL == arr)
{
return;
}
if (NULL == data)
{
return;
}
if (pos > arr->size || pos < 0)
{
pos = arr->size;
}
//判断空间是否足够
if (arr->size >= arr->capacity)
{
//1.申请一块更大的内存空间
int newcapacity = arr->capacity * 2;
void** newspace = malloc(sizeof(void*) * newcapacity);
//2.将原来空间的数据拷贝到新空间
memcpy(newspace, arr->addr, sizeof(void*) * arr->capacity);
//3.释放原来的内存空间
if (NULL != arr->addr)
{
free(arr->addr);
arr->addr = NULL;
}
//4.更新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 RemoveByPos_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 RemoveByValue_DynamicArray(struct DynamicArray* arr, void* data,int(*MYCOMPARE)(void*,void*))
{
if (NULL == arr)
{
return;
}
if (NULL == data)
{
return;
}
if (NULL == MYCOMPARE)
{
return;
}
for (int i = 0; i < arr->size; ++i)
{
if (MYCOMPARE(arr->addr[i], data))
{
//找到了(调用按位置删除)
RemoveByPos_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 myPrintf(void* data)
{
struct Person* person = (struct Person*)data;
printf("Name:%s Age:%d\n", person->name, person->age);
}
void myComepare_1(void* d1, void* d2)
{
struct Person* p1 = (struct Person*)d1;
struct Person* p2 = (struct Person*)d2;
return strcmp(p1->name, p2->name) == 0 && p1->age == p2->age;
}
void test101()
{
//创建动态数组
struct DynamicArray* da;
Init_DynamicArray(5, &da);
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);//3 5 4 2 1
printf("容量:%d\n", da->capacity);
Insert_DynamicArray(da, 100, &p6);//3 5 4 2 1 6
printf("容量:%d\n", da->capacity);
//遍历打印
Foreach_DynamicArray(da, myPrintf);
//按位置删除
RemoveByPos_DynamicArray(da, 2);//3 5 2 1 6
//遍历打印
printf("----------------\n");
Foreach_DynamicArray(da, myPrintf);
//按值删除
struct Person pDel = { "aaa",10 };
RemoveByValue_DynamicArray(da, &pDel, myComepare_1);
//遍历打印
printf("----------------\n");
Foreach_DynamicArray(da, myPrintf);
//销毁
Destroy_DynamicArray(da);
}
int main(void)
{
test101();
system("pause");
return EXIT_SUCCESS;
}
002.单向链表(版本一)
LinkList.h
#pragma once
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#ifdef __cplusplus
extern "C" {
#endif
//链表结点数据类型
struct LinkNode
{
void* data;
struct LinkNode* next;
};
//链表数据类型
struct LList
{
struct LinkNode header;
int size;
};
//函数指针变量
typedef void(*FOREACH)(void*);
typedef int(*COMPARE)(void*, void*);
typedef void* LinkList;
//初始化链表
LinkList Init_LinkList();
//插入结点(按位置插入)
void insert_LinkList(LinkList list, int pos, void* data);
//遍历链表
void Foreach_LinkList(LinkList list, FOREACH myforeach);
//按位置删除
void RemoveByPos_LinkList(LinkList list, int pos);
//按值删除
void RemoveByVal_LinkList(LinkList list, void* data, COMPARE compare);
//清空链表
void Clear_LinkList(LinkList list);
//大小
int Size_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)
{
pos = mylist->size;
}
//查找插入位置
struct LinkNode* pCurrent = &(mylist->header);
for (int i = 0; i < pos; ++i)
{
pCurrent = pCurrent->next;
}
//创建新节点
struct LinkNode* newnode = malloc(sizeof(struct LinkNode));
newnode->data = data;
newnode->next = NULL;
//新节点插入到链表中
newnode->next = pCurrent->next;
pCurrent->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* pCurrent = mylist->header.next;
while (pCurrent != NULL)
{
myforeach(pCurrent->data);
pCurrent = pCurrent->next;
}
}
//按位置删除
void RemoveByPos_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* pCurrent = &(mylist->header);
for (int i = 0; i < pos; ++i)
{
pCurrent = pCurrent->next;
}
//先保存待删除结点
struct LinkNode* pDel = pCurrent->next;
//重新建立待删除结点的前驱和后继节点关系
pCurrent->next = pDel->next;
//释放删除结点内存
free(pDel);
pDel = NULL;
mylist->size--;
}
//按值删除
void RemoveByVal_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* pCurrent = pPrev->next;
while (pCurrent != NULL)
{
if (compare(pCurrent->data, data))
{
//找到待删除结点(重新建立待删除结点的前驱和后继节点关系)
pPrev->next = pCurrent->next;
//释放删除结点内存
free(pCurrent);
pCurrent = NULL;
mylist->size--;
break;
}
pPrev = pCurrent;
pCurrent = pCurrent->next;
}
}
//清空链表
void Clear_LinkList(LinkList list)
{
if (NULL == list)
{
return;
}
struct LList* mylist = (struct LList*)list;
//辅助指针变量
struct LinkNode* pCurrent = mylist->header.next;
while (pCurrent != NULL)
{
//先缓存下一个节点的地址
struct LinkList* pNext = pCurrent->next;
//释放当前节点
free(pCurrent);
pCurrent = pNext;
}
mylist->header.next = NULL;
mylist->size = 0;
}
//大小
int Size_LinkList(LinkList list)
{
if (NULL == list)
{
return;
}
struct LList* mylist = (struct LList*)list;
return mylist->size;
}
//销毁链表
void Destroy_LinkList(LinkList list)
{
if (NULL == list)
{
return;
}
struct LList* mylist = (struct LList*)list;
//辅助指针变量
struct LinkNode* pCurrent = mylist->header.next;
while (pCurrent != NULL)
{
//先缓存下一个节点的地址
struct LinkList* pNext = pCurrent->next;
//释放当前节点
free(pCurrent);
pCurrent = pNext;
}
mylist->header.next = NULL;
mylist->size = 0;
free(list);
list = NULL;
}
单向链表(版本一).c
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include"LinkList.h"
struct Person
{
char name[64];
int age;
};
int myCompare(void* d1, void* d2)
{
struct Person* p1 = (struct Person*)d1;
struct Person* p2 = (struct Person*)d2;
/*if (strcmp(p1->name, p2->name) == 0 && p1->age == p2->age)
{
return 1;
}
return 0;*/
//两者等价
return strcmp(p1->name, p2->name) == 0 && p1->age == p2->age;
}
void myPrint(void* data)
{
struct Person* person = (struct Person*)data;
printf("Name:%s Age:%d\n", person->name, person->age);
}
void test201()
{
//创建链表
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 };
struct Person p7 = { "ggg",70 };
//插入数据
insert_LinkList(list, 0, &p1);//p1
insert_LinkList(list, 0, &p2);//p2 p1
insert_LinkList(list, 1, &p3);// p2 p3 p1
insert_LinkList(list, 2, &p4);// p2 p3 p4 p1
insert_LinkList(list, 20, &p5);// p2 p3 p4 p1 p5
insert_LinkList(list, 3, &p6);// p2 p3 p4 p6 p1 p5
insert_LinkList(list, 6, &p7);// p2 p3 p4 p6 p1 p5 p7
//遍历打印
Foreach_LinkList(list,myPrint);
//打印链表大小
printf("-------------------------\n");
printf("List Size:%d\n", Size_LinkList(list));
//按位置删除
RemoveByPos_LinkList(list, 3);// p2 p3 p4 p1 p5 p7
//遍历打印
printf("-------------------------\n");
Foreach_LinkList(list, myPrint);
//按值删除
struct Person pDelPerson = { "ggg",70 };
RemoveByVal_LinkList(list, &pDelPerson, myCompare);// p2 p3 p4 p1 p5
//遍历打印
printf("-------------------------\n");
Foreach_LinkList(list, myPrint);
//清空链表
Clear_LinkList(list);
//打印链表大小
printf("-------------------------\n");
printf("List Size:%d\n", Size_LinkList(list));
//销毁链表
Destroy_LinkList(list);
}
int main(void)
{
test201();
system("pause");
return EXIT_SUCCESS;
}
003.单向链表(版本二)思路
版本一的单向链表的缺陷:每次添加和删除元素时都需要开辟堆空间和释放堆空间
版本二思路(代码简单实现)
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
struct LinkNode
{
struct LinkNode* next;
};
struct Person
{
struct LinkNode node;
char name[64];
int age;
};
//版本二简单思路,下次实现完整代码
void test301()
{
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 };
struct LinkNode* pp1 = (struct LinkNode*)&p1;
struct LinkNode* pp2 = (struct LinkNode*)&p2;
struct LinkNode* pp3 = (struct LinkNode*)&p3;
struct LinkNode* pp4 = (struct LinkNode*)&p4;
struct LinkNode* pp5 = (struct LinkNode*)&p5;
pp1->next = pp2;
pp2->next = pp3;
pp3->next = pp4;
pp4->next = pp5;
pp5->next = NULL;
struct LinkNode* pCurrent = pp1;
while (pCurrent != NULL)
{
struct Person* person = (struct Person*)pCurrent;
printf("Name:%s Age:%d\n", person->name, person->age);
pCurrent = pCurrent->next;
}
}
int main(void)
{
test301();
system("pause");
return EXIT_SUCCESS;
}