算法的特性:输入、输出、有穷性、确定性和可行性
输入输出:算法具有零个或多个输入、至少有一个或多个输出。
有穷性:指算法在执行有限的步骤之后,自动结束而不会出现无限循环,并且每一个步骤在可接受的时间内完成。
确定性:算法的每一步骤都有确定的含义,不会出现二义性。
可行性:算法的每一步都必须是可行的,也就是说,每一步都能通过执行有限次数完成。
数据结构的分类:逻辑结构、物理结构
逻辑结构
集合结构
通常不去探讨。
线性结构
线性结构和数组元素之间是一对一的关系。除了第一个元素没有前驱,最后一个元素没有后继,其他的元素都有唯一的前驱和后继,这样一种一对一的关系。链表和数组都是线性结构。
树形结构
树形数据结构的数据元素一对多的关系,唯一的前驱对应多个后继。
图形结构
图形数据结构的数据元素是多对多的关系。
物理结构
顺序存储
连续的空间存储。
链式存储
存储单元可以是连续的也可以是不连续的。
线性表
动态数组、链表、栈、队列都属于线性结构。
线性表-动态数组

设计
struct dynamicArray
属性:
void ** pAddr 维护真实在堆区创建的数组的指针
int m_capacity; 数组容量
int m_size; 数组大小
动态数组初始化
struct dynamicArray * init_DynamicArray(int capacity)
插入数组

void insert_DynamicArray(struct dynamicArray * array , int pos , void * data)
遍历数组
void foreach_DynamicArray(struct dynamicArray * array, void(*myPrint)(void*))
删除数组
按照位置删除
void removeByPos_DynamicArray(struct dynamicArray * array , int pos)
按照值删除
void removeByValue_DynamicArray(struct dynamicArray * array , void * data , int (* myCompare)(void * ,void *))
销毁数组
void destroy_DynamicArray(struct dynamicArray* array)
示例
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <Windows.h>
struct dynamicArray
{
void** pAddr;
int mCapacity;
int mSize;
};
struct dynamicArray* initDynamicArray(int capacity)
{
if (capacity <= 0)
{
return NULL;
}
struct dynamicArray *array = malloc(sizeof(struct dynamicArray));
if (array == NULL)
{
return NULL;
}
array->pAddr = malloc(sizeof(void*) * capacity);
array->mCapacity = capacity;
array->mSize = 0;
return array;
}
void insertDynamicArray(struct dynamicArray* array, int pos, void * data)
{
if (array == NULL)
{
return;
}
if (data == NULL)
{
return;
}
if (pos <0 || pos >array->mSize)
{
pos = array->mSize;
}
if (array->mSize == array->mCapacity)
{
int newCapacity = array->mCapacity * 2;
void** newSpace = malloc(sizeof(void*) * newCapacity);
memcpy(newSpace, array->pAddr, sizeof(void *)*array->mCapacity);
free(array->pAddr);
array->pAddr = newSpace;
array->mCapacity = newCapacity;
}
for (int i = array->mSize-1; i>=pos;i--)
{
array->pAddr[i + 1] = array->pAddr[i];
}
array->pAddr[pos] = data;
array->mSize++;
}
void foreachDynamicArray(struct dynamicArray* array,void (*myPrint)(void *))
{
if (array == NULL)
{
return;
}
if (myPrint == NULL)
{
return;
}
for (size_t i = 0; i < array->mSize; i++)
{
myPrint(array->pAddr[i]);
}
}
void removeByPosDynamicArray(struct dynamicArray* array, int pos)
{
if (NULL == array)
{
return;
}
if (pos <0 || pos > array->mSize - 1)
{
return;
}
for (size_t i = pos; i < array->mSize-1; i++)
{
array->pAddr[i] = array->pAddr[i + 1];
}
array->mSize--;
}
void removeByValueDynamicArray(struct dynamicArray* array, void *data,int (* myCompare)(void *,void*))
{
if (array ==NULL)
{
return;
}
if (data == NULL)
{
return;
}for (size_t i = 0; i < array->mSize-1; i++)
{
if (myCompare(array->pAddr[i], data))
{
removeByPosDynamicArray(array, i);
break;
}
}
}
void destroyDynamicArray(struct dynamicArray* array)
{
if (array == NULL)
{
return;
}
if (array->pAddr != NULL)
{
free(array->pAddr);
array->pAddr = NULL;
}
free(array);
array = NULL;
}
struct Person
{
char name[64];
int age;
};
void myPrintPerson(void* data)
{
struct Person* p = data;
printf("name = %s age = %d \n", p->name, p->age);
}
int myComparePerson(void* data1, void* data2)
{
struct Person* p1 = data1;
struct Person* p2 = data2;
return strcmp(p1->name, p2->name) == 0 && p1->age == p2->age;
}
int main(void)
{
struct dynamicArray *array = initDynamicArray(5);
printf("插入数据前capacity = %d, size = %d\n", array->mCapacity, array->mSize);
struct Person p1 = { "Andy",18 };
struct Person p2 = { "Judy",28 };
struct Person p3 = { "Tony",19 };
struct Person p4 = { "Cady",25 };
struct Person p5 = { "Fudy",24 };
struct Person p6 = { "Mary",21 };
insertDynamicArray(array, 0, &p1);
insertDynamicArray(array, 0, &p2);
insertDynamicArray(array, 1, &p3);
insertDynamicArray(array, 0, &p4);
insertDynamicArray(array, -1, &p5);
insertDynamicArray(array, 0, &p6);
foreachDynamicArray(array, myPrintPerson);
printf("插入数据后capacity = %d, size = %d\n", array->mCapacity, array->mSize);
removeByPosDynamicArray(array, 2);
printf("------------------\n");
foreachDynamicArray(array, myPrintPerson);
struct Person p = { "Tony",19 };
removeByValueDynamicArray(array, &p,myComparePerson);
printf("------------------\n");
foreachDynamicArray(array, myPrintPerson);
destroyDynamicArray(array);
array = NULL;
system("pause");
return EXIT_SUCCESS;
}
实现分文件编写
头文件里声明,c文件里做实现,复用的话到时候把这两个拷走就行了
线性表-单向链表(动态数组是顺序存储,链表是链式存储)
设计

struct LinkNode 节点结构体
struct LList 链表结构体
typedef void * LinkList 给用户使用链表指针
初始化链表
LinkList init_LinkList()
插入链表
void insert_LinkList(LinkList list, int pos, void * data)
遍历链表
void foreach_LinkList(LinkList list, void(*myForeach)(void *))
删除链表
按照位置void removeByPos_LinkList(LinkList list, int pos)
按照值void removeByValue_LinkList(LinkList list , void * data , int(*myCompare)(void * ,void *) )
清空
void clear_LinkList(LinkList list)
返回链表长度
int size_LinkList(LinkList list)
销毁
void destroy_Linklist(LinkList list)
示例
//节点的结构体设计
struct LinkNode
{
//数据域
void* data
//指针域
struct LinkNode* next
}
//链表结构体
struct LList
{
//头节点
struct LinkNode pHeader
//链表长度
int mSize
}
typedef void* LinkList
//初始化链表
LinkList initLinkList()
{
struct LList* myList = malloc(sizeof(struct LList))
if (myList == NULL)
{
return NULL
}
myList->pHeader.data = NULL
myList->pHeader.next = NULL
myList->mSize = 0
return myList
}
//插入链表
void insertLinkList(LinkList list, int pos, void* data)
{
if (list == NULL)
{
return
}
if (data == NULL)
{
return
}
//将list还原成struct LList 数据类型
struct LList* myList = list
if (pos <0 || pos > myList->mSize)
{
//无效位置,强制做尾插
pos = myList->mSize
}
//找到插入节点的前驱节点位置
struct LinkNode* pCurrent = &myList->pHeader
for (int i = 0
{
pCurrent = pCurrent->next
}
//pCurrent是要插入节点的前驱
//创建新节点
struct LinkNode* newNode = malloc(sizeof(struct LinkNode))
newNode->data = data
newNode->next = NULL
//建立节点关系
newNode->next = pCurrent->next
pCurrent->next = newNode
//更新链表长度
myList->mSize++
}
//遍历链表
void foreachLinkList(LinkList list,void(* myForeach)(void*))
{
if (list == NULL)
{
return
}
struct LList* myList = list
struct LinkNode* pCurrent = myList->pHeader.next
for (size_t i = 0
{
myForeach(pCurrent->data)
pCurrent = pCurrent->next
}
}
//删除链表 按位置
void removeLinkListByPos(LinkList list, int pos)
{
if (list == NULL)
{
return
}
struct LList* myList = list
if (pos <0 || pos > myList->mSize-1)
{
//无效位置,强制做尾插
return
}
//找到待删除节点的前驱节点
struct LinkNode* pCurrent = &myList->pHeader
for (size_t i = 0
{
pCurrent = pCurrent->next
}
//记录待删除的节点
struct LinkNode* pDel = pCurrent->next
//重新建立节点关系
pCurrent->next = pDel->next
free(pDel)
pDel = NULL
//更新链表长度
myList->mSize--
}
//删除链表 按照值
void removeLinkListByValue(LinkList list, void* data,int(*myCompare)(void *,void *))
{
if (list == NULL)
{
return
}
if (data == NULL)
{
return
}
struct LList* myList = list
//创建两个辅助指针
struct LinkNode* pPre = &myList->pHeader
struct LinkNode* pCurrent = myList->pHeader.next
for (size_t i = 0
{
//利用回调将两个指针的比较 交给用户
if (myCompare(pCurrent->data, data))
{
pPre->next = pCurrent->next
free(pCurrent)
pCurrent = NULL
myList->mSize--
break
}
//辅助指针后移
pPre = pCurrent
pCurrent = pCurrent->next
}
}
//清空链表
void clearLinkList(LinkList list)
{
if (list ==NULL)
{
return
}
struct LList* myList = list
struct LinkNode* pCurrent = myList->pHeader.next
for (size_t i = 0
{
struct LinkNode* pNext = pCurrent->next
free(pCurrent)
pCurrent = pNext
}
myList->pHeader.next = NULL
myList->mSize = 0
}
//返回链表长度
int sizeLinkList(LinkList list)
{
if (list ==NULL)
{
return -1
}
struct LList* myList = list
return myList->mSize
}
//销毁链表
void destroyLinkList(LinkList list)
{
if (list == NULL)
{
return
}
//清空链表
clearLinkList(list)
free(list)
list = NULL
}
//测试
struct Person
{
char name[64]
int age
}
void myPrintPerson(void* data)
{
struct Person* p = data
printf(" name = %s age = %d\n", p->name, p->age);
}
int myComparePerson(void* data1, void* data2)
{
struct Person* p1 = data1;
struct Person* p2 = data2;
return strcmp(p1->name, p2->name) ==0 && p1->age == p2->age;
}
void test01()
{
//准备数据
struct Person p1 = { "Andy",18 };
struct Person p2 = { "Judy",28 };
struct Person p3 = { "Tony",19 };
struct Person p4 = { "Cady",25 };
struct Person p5 = { "Fudy",24 };
struct Person p6 = { "Mary",21 };
//初始化链表
LinkList myList = initLinkList();
printf("链表长度为:%d\n", sizeLinkList(myList));
//插入数据
insertLinkList(myList, 0, &p1);
insertLinkList(myList, 0, &p2);
insertLinkList(myList, -1, &p3);
insertLinkList(myList, 0, &p4);
insertLinkList(myList, 1, &p5);
insertLinkList(myList, 2, &p6);
//Cady Fudy Mary Judy Andy Tony
//遍历链表
foreachLinkList(myList, myPrintPerson);
printf("链表长度为:%d\n", sizeLinkList(myList));
//测试删除按位置
removeLinkListByPos(myList, 3);
printf("---------------------\n");
foreachLinkList(myList, myPrintPerson);
printf("链表长度为:%d\n", sizeLinkList(myList));
//测试删除按值
struct Person p = { "Tony",19 };
removeLinkListByValue(myList, &p,myComparePerson);
printf("---------------------\n");
foreachLinkList(myList, myPrintPerson);
printf("链表长度为:%d\n", sizeLinkList(myList));
//测试清空链表
clearLinkList(myList);
//返回链表长度
printf("链表长度为:%d\n", sizeLinkList(myList));
//销毁链表
destroyLinkList(myList);
myList = NULL;
}
int main(void)
{
test01();
system("pause");
return EXIT_SUCCESS;
}