03-数据结构(C语言版)

Day01

笔记

1	数据结构基本理论
	1.1	算法五个特性:
		1.1.1	输入、输出、有穷、确定、可行
	1.2	数据结构分类
		1.2.1	逻辑结构:集合、线性、树形、图形
		1.2.2	物理结构:顺序存储、链式存储
2	动态数组实现
	2.1	设计
		2.1.1	struct dynamicArray
		2.1.2	属性:  
		2.1.3	void ** pAddr 维护真实在堆区创建的数组的指针
		2.1.4	int m_capacity; 数组容量
		2.1.5	int m_size; 数组大小
	2.2	动态数组初始化
		2.2.1	struct dynamicArray * init_DynamicArray(int capacity)
	2.3	插入数组
		2.3.1	void insert_DynamicArray(struct dynamicArray * array , int pos  , void * data)
	2.4	遍历数组
		2.4.1	void foreach_DynamicArray(struct dynamicArray * array, void(*myPrint)(void*))
	2.5	删除数组
		2.5.1	按照位置删除  
		2.5.2	void removeByPos_DynamicArray(struct dynamicArray * array , int pos)
		2.5.3	按照值删除
		2.5.4	void removeByValue_DynamicArray(struct dynamicArray * array , void * data , int (* myCompare)(void * ,void *))
	2.6	销毁数组
		2.6.1	void destroy_DynamicArray(struct dynamicArray* array)
	2.7	实现分文件编写
3	单向链表
	3.1	设计   
		3.1.1	struct LinkNode  节点结构体
		3.1.2	struct LList      链表结构体
		3.1.3	typedef  void *  LinkList  给用户使用链表指针
	3.2	初始化链表
		3.2.1	LinkList init_LinkList()
	3.3	插入链表
		3.3.1	void insert_LinkList(LinkList list, int pos, void * data)
	3.4	遍历链表
		3.4.1	void foreach_LinkList(LinkList list, void(*myForeach)(void *))
	3.5	删除链表
		3.5.1	按照位置void removeByPos_LinkList(LinkList list, int pos)
		3.5.2	按照值void removeByValue_LinkList(LinkList list , void * data ,  int(*myCompare)(void * ,void *) )
	3.6	清空
		3.6.1	void clear_LinkList(LinkList list)
	3.7	返回链表长度
		3.7.1	int  size_LinkList(LinkList list)
	3.8	销毁
		3.8.1	void destroy_Linklist(LinkList list)
4	

Code

动态数组

  • 头文件 -- dynamicArray.h
#pragma  once
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>


//动态数组结构体
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);
  • 源文件--dynamicArray.c
#include "dynamicArray.h"


//初始化数组
struct dynamicArray * init_DynamicArray(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->m_capacity = capacity;
	array->m_size = 0;

	return array;
}

//插入数组
void insert_DynamicArray(struct dynamicArray * array, int pos, void * data)
{
	if (array == NULL)
	{
		return;
	}
	if (data == NULL)
	{
		return;
	}

	//无效位置  尾插
	if (pos < 0 || pos > array->m_size)
	{
		pos = array->m_size;
	}

	//判断是否满了,如果满动态扩展
	if (array->m_size == array->m_capacity)
	{
		//1、计算新空间大小
		int newCapacity = array->m_capacity * 2;

		//2、创建新空间
		void ** newSpace = malloc(sizeof(void *)* newCapacity);

		//3、将原有数据拷贝到新空间下
		memcpy(newSpace, array->pAddr, sizeof(void *)* array->m_capacity);

		//4、释放原有内存空间
		free(array->pAddr);

		//5、更新新空间指向
		array->pAddr = newSpace;

		//6、更新新容量
		array->m_capacity = newCapacity;
	}

	//插入新元素

	//移动元素 进行插入新元素
	for (int i = array->m_size - 1; i >= pos; i--)
	{
		//数据向后移动
		array->pAddr[i + 1] = array->pAddr[i];
	}

	//将新元素 插入到指定位置上
	array->pAddr[pos] = data;
	//更新大小
	array->m_size++;
}


//遍历数组
void foreach_DynamicArray(struct dynamicArray * array, void(*myPrint)(void*))
{
	if (array == NULL)
	{
		return;
	}
	if (myPrint == NULL)
	{
		return;
	}

	for (int i = 0; i < array->m_size; i++)
	{
		myPrint(array->pAddr[i]);
	}
}


//删除数组  按位置删除
void removeByPos_DynamicArray(struct dynamicArray * array, int pos)
{
	if (NULL == array)
	{
		return;
	}

	if (pos < 0 || pos > array->m_size - 1)
	{
		return;
	}

	//数据前移
	for (int i = pos; i < array->m_size - 1; i++)
	{
		array->pAddr[i] = array->pAddr[i + 1];
	}

	//更新数组大小
	array->m_size--;

}

//按值删除数据
void removeByValue_DynamicArray(struct dynamicArray * array, void * data, int(*myCompare)(void *, void *))
{
	if (array == NULL)
	{
		return;
	}
	if (data == NULL)
	{
		return;
	}

	for (int i = 0; i < array->m_size; i++)
	{
		if (myCompare(array->pAddr[i], data))
		{
			//如果找到要删除的数据,i就是要删除的具体位置
			removeByPos_DynamicArray(array, i);
			break;
		}
	}

}

//销毁数组
void destroy_DynamicArray(struct dynamicArray* array)
{
	if (array == NULL)
	{
		return;
	}

	if (array->pAddr != NULL)
	{
		free(array->pAddr);
		array->pAddr = NULL;
	}


	free(array);
	array = NULL;
}
  • 源文件--01 动态数组.c
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>

#include "dynamicArray.h"

////动态数组结构体
//struct dynamicArray
//{
//	void ** pAddr; //维护真实在堆区创建的数组的指针
//
//	int m_capacity;  // 数组容量
//
//	int m_size;   //数组大小
//};
//
//
////初始化数组
//struct dynamicArray * init_DynamicArray(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->m_capacity = capacity;
//	array->m_size = 0;
//	
//	return array;
//}
//
////插入数组
//void insert_DynamicArray(struct dynamicArray * array , int pos  , void * data)
//{
//	if ( array == NULL)
//	{
//		return;
//	}
//	if ( data == NULL)
//	{
//		return;
//	}
//
//	//无效位置  尾插
//	if (pos < 0 || pos > array->m_size)
//	{
//		pos = array->m_size;
//	}
//
//	//判断是否满了,如果满动态扩展
//	if (array->m_size == array->m_capacity)
//	{
//		//1、计算新空间大小
//		int newCapacity = array->m_capacity * 2;
//
//		//2、创建新空间
//		void ** newSpace = malloc(sizeof(void *)* newCapacity);
//
//		//3、将原有数据拷贝到新空间下
//		memcpy(newSpace, array->pAddr, sizeof(void *)* array->m_capacity);
//
//		//4、释放原有内存空间
//		free(array->pAddr);
//
//		//5、更新新空间指向
//		array->pAddr = newSpace;
//
//		//6、更新新容量
//		array->m_capacity = newCapacity;
//	}
//
//	//插入新元素
//
//	//移动元素 进行插入新元素
//	for (int i = array->m_size - 1; i >= pos; i--)
//	{
//		//数据向后移动
//		array->pAddr[i + 1] = array->pAddr[i];
//	}
//
//	//将新元素 插入到指定位置上
//	array->pAddr[pos] = data;
//	//更新大小
//	array->m_size++;
//}
//
//
////遍历数组
//void foreach_DynamicArray(struct dynamicArray * array, void(*myPrint)(void*))
//{
//	if (array == NULL)
//	{
//		return;
//	}
//	if (myPrint == NULL)
//	{
//		return;
//	}
//
//	for (int i = 0; i < array->m_size;i++)
//	{
//		myPrint(array->pAddr[i]);
//	}
//}
//
//
////删除数组  按位置删除
//void removeByPos_DynamicArray(struct dynamicArray * array , int pos)
//{
//	if ( NULL == array)
//	{
//		return;
//	}
//
//	if (pos < 0  || pos > array->m_size - 1)
//	{
//		return;
//	}
//
//	//数据前移
//	for (int i = pos; i < array->m_size - 1;i++)
//	{
//		array->pAddr[i] = array->pAddr[i + 1];
//	}
//
//	//更新数组大小
//	array->m_size--;
//
//}
//
////按值删除数据
//void removeByValue_DynamicArray(struct dynamicArray * array , void * data , int (* myCompare)(void * ,void *))
//{
//	if ( array == NULL)
//	{
//		return;
//	}
//	if ( data == NULL)
//	{
//		return;
//	}
//
//	for (int i = 0; i < array->m_size;i++)
//	{
//		if (myCompare(array->pAddr[i], data))
//		{
//				//如果找到要删除的数据,i就是要删除的具体位置
//			removeByPos_DynamicArray(array, i);
//			break;
//		}
//	}
//
//}
//
////销毁数组
//void destroy_DynamicArray(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("姓名: %s 年龄:%d
", 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(){

	//初始化动态数组
	struct dynamicArray * array = init_DynamicArray(5);

	//准备数据
	struct Person p1 = { "亚瑟", 18 };
	struct Person p2 = { "妲己", 20 };
	struct Person p3 = { "安琪拉", 19 };
	struct Person p4 = { "凯", 21 };
	struct Person p5 = { "孙悟空", 999 };
	struct Person p6 = { "李白", 999};

	printf("插入数据前: 容量:%d  大小:%d
", array->m_capacity, array->m_size);

	//插入数据
	insert_DynamicArray(array, 0, &p1);
	insert_DynamicArray(array, 0, &p2);
	insert_DynamicArray(array, 1, &p3);
	insert_DynamicArray(array, 0, &p4);
	insert_DynamicArray(array, -1, &p5);
	insert_DynamicArray(array, 2, &p6);

	// 凯 妲己 李白 安琪拉  亚瑟  孙悟空

	//遍历数据
	foreach_DynamicArray(array, myPrintPerson);


	printf("插入数据后: 容量:%d  大小:%d
", array->m_capacity, array->m_size);


	//测试删除 按位置删除
	removeByPos_DynamicArray(array, 2);
	printf("---------------------
");
	foreach_DynamicArray(array, myPrintPerson);
	printf("删除数据后: 容量:%d  大小:%d
", array->m_capacity, array->m_size);

	struct Person  p = { "亚瑟", 18 };
	removeByValue_DynamicArray(array, &p, myComparePerson);
	printf("---------------------
");
	foreach_DynamicArray(array, myPrintPerson);
	printf("删除数据后: 容量:%d  大小:%d
", array->m_capacity, array->m_size);


	//array->pAddr = NULL;
	//array->m_capacity = 0;
	//array->m_size = 0;

	//销毁数组
	destroy_DynamicArray(array);
	array = NULL;

	system("pause");
	return EXIT_SUCCESS;
}

单向链表

  • 02 单向链表.c
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>

//节点结构体
struct LinkNode
{
	//数据域
	void * data;
	//指针域
	struct LinkNode * next;
};

//链表结构体
struct LList
{
	//头节点
	struct LinkNode pHeader;
	//链表长度
	int m_size;
};

typedef void * LinkList;


//初始化链表
LinkList init_LinkList()
{
	 struct LList * myList = malloc(sizeof(struct LList));

	 if (myList == NULL)
	 {
		 return NULL;
	 }

	 myList->pHeader.data = NULL;
	 myList->pHeader.next = NULL;
	 myList->m_size = 0;

	 return myList;
}

//插入链表
void insert_LinkList(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->m_size)
	{
		//无效位置 强制做尾插
		pos = myList->m_size;
	}

	//找到插入节点的前驱节点位置
	struct LinkNode * pCurrent = &myList->pHeader;

	for (int i = 0; i < pos;i++)
	{
		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->m_size++;

}

//遍历链表
void foreach_LinkList(LinkList list, void(*myForeach)(void *))
{
	if (list ==NULL)
	{
		return;
	}

	struct LList * mylist = list;

	struct LinkNode* pCurrent = mylist->pHeader.next;

	for (int i = 0; i < mylist->m_size;i++)
	{
		myForeach(pCurrent->data);
		pCurrent = pCurrent->next;
	}

}


//删除链表  按位置
void removeByPos_LinkList(LinkList list, int pos)
{
	if ( list == NULL)
	{
		return;
	}

	struct LList * mylist = list;

	if (pos < 0 || pos > mylist->m_size - 1)
	{
		return;
	}

	//找到待删除节点的前驱节点
	struct LinkNode * pCurrent = &mylist->pHeader;
	for (int i = 0; i < pos;i++)
	{
		pCurrent = pCurrent->next;
	}

	//记录待删除的节点
	struct LinkNode * pDel = pCurrent->next;

	//重新建立节点关系
	pCurrent->next = pDel->next;

	free(pDel);
	pDel = NULL;

	//更新链表长度
	mylist->m_size--;
}

//按照值删除链表
void removeByValue_LinkList(LinkList list , void * data ,  int(*myCompare)(void * ,void *) )
{
	if (list == NULL)
	{
		return;
	}
	if ( data == NULL)
	{
		return;
	}

	struct LList * mylist = list;
	//创建两个辅助指针
	struct LinkNode * pPrev = &mylist->pHeader;
	struct LinkNode * pCurrent = pPrev->next;

	for (int i = 0; i < mylist->m_size;i++)
	{
		//pCurrent->data  data 将两个指针比较利用回调 交给用户
		if (myCompare (pCurrent->data,data))
		{
			pPrev->next = pCurrent->next;

			free(pCurrent);
			pCurrent = NULL;

			mylist->m_size--;
			break;
		}

		//辅助指针后移
		pPrev = pCurrent;
		pCurrent = pCurrent->next;
	}
}

//清空链表
void clear_LinkList(LinkList list)
{
	if (list == NULL)
	{
		return;
	}

	struct LList * mylist = list;

	struct LinkNode * pCurrent = mylist->pHeader.next;

	for (int i = 0; i < mylist->m_size;i++)
	{
		struct LinkNode * pNext = pCurrent->next;

		free(pCurrent);

		pCurrent = pNext;
	}

	mylist->pHeader.next = NULL;
	mylist->m_size = 0;

}

//返回链表长度
int  size_LinkList(LinkList list)
{
	if (list == NULL)
	{
		return -1;
	}

	struct LList * mylist = list;

	return mylist->m_size;
}

//销毁链表
void destroy_Linklist(LinkList list)
{
	if (list == NULL)
	{
		return ;
	}

	//清空链表
	clear_LinkList(list);

	free(list);

	list = NULL;

}




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

void myPrintPerson(void * data)
{
	struct Person * p = data;
	printf("姓名:%s  年龄:%d
", 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 = { "亚瑟", 18 };
	struct Person p2 = { "妲己", 20 };
	struct Person p3 = { "安琪拉", 19 };
	struct Person p4 = { "凯", 21 };
	struct Person p5 = { "孙悟空", 999 };
	struct Person p6 = { "李白", 999 };

	//初始化链表
	LinkList mylist = init_LinkList();

	printf("链表长度为:%d
", size_LinkList(mylist));

	//插入数据
	insert_LinkList(mylist, 0, &p1);
	insert_LinkList(mylist, 0, &p2);
	insert_LinkList(mylist, -1, &p3);
	insert_LinkList(mylist, 0, &p4);
	insert_LinkList(mylist, 1, &p5);
	insert_LinkList(mylist, 0, &p6);



	// 李白 凯 孙悟空 妲己 亚瑟 安琪拉

	//遍历
	foreach_LinkList(mylist, myPrintPerson);

	printf("链表长度为:%d
", size_LinkList(mylist));

	//测试删除 
	removeByPos_LinkList(mylist, 4);

	printf("------------------
");

	foreach_LinkList(mylist, myPrintPerson);
	printf("链表长度为:%d
", size_LinkList(mylist));

	struct Person p = { "孙悟空", 999 };
	removeByValue_LinkList(mylist, &p, myComparePerson);

	printf("------------------
");

	foreach_LinkList(mylist, myPrintPerson);
	printf("链表长度为:%d
", size_LinkList(mylist));

	//测试清空
	clear_LinkList(mylist);

	//返回链表长度
	printf("链表长度为:%d
", size_LinkList(mylist));

	//销毁
	destroy_Linklist(mylist);
	mylist = NULL;
}

int main(){

	test01();

	system("pause");
	return EXIT_SUCCESS;
}

Day02

笔记

1	单向链表-企业版
	1.1	设计:节点只维护指针域,用户数据预留前4个字节由底层使用
	1.2	接口:
		1.2.1	初始化链表
		1.2.2	插入链表
		1.2.3	遍历链表
		1.2.4	删除链表
		1.2.5	销毁链表
2	栈的基本概念
	2.1	栈符合 先进后出的数据结构
	2.2	入栈  push
	2.3	出栈  pop
	2.4	栈顶  top
	2.5	栈大小  size
	2.6	是否为空  isEmpty
	2.7	栈底  --- 高地址    栈顶 ---  低地址
	2.8	栈是否可以遍历 ---- 不可以
3	栈的顺序存储
	3.1	利用数组模拟出 先进后出数据结构
	3.2	数组中首地址  做栈底 方便数组尾部做插入删除
	3.3	对外接口
		3.3.1	初始化栈 init
		3.3.2	入栈  push
		3.3.3	出栈  pop
		3.3.4	栈顶  top
		3.3.5	栈大小  size
		3.3.6	是否为空  isEmpty
		3.3.7	销毁栈 destroy
4	栈的链式存储
	4.1	利用链表模拟出  先进后出的数据结构
	4.2	头节点端做栈顶 比较方便做入栈和出栈
	4.3	对外接口
		4.3.1	初始化栈 init
		4.3.2	入栈  push
		4.3.3	出栈  pop
		4.3.4	栈顶  top
		4.3.5	栈大小  size
		4.3.6	是否为空  isEmpty
		4.3.7	销毁栈 destroy
	4.4	测试
5	栈的应用案例-就近匹配
	5.1	从第一个字符开始扫描所有字符
	5.2	遇到普通字符  直接忽略
	5.3	遇到左括号,入栈
	5.4	遇到右括号
		5.4.1	如果栈中有元素   出栈
		5.4.2	如果栈中没有元素   立即停止,并且报错
	5.5	当所有字符都扫描完毕,查看栈中内容
		5.5.1	如果是空栈,没有问题
		5.5.2	如果不是空栈,报错


6	中缀表达式转后缀表达式
遍历中缀表达式中的数字和符号:
		对于数字:直接输出
		对于符号:
			左括号:进栈  
			运算符号:与栈顶符号进行优先级比较
		若栈顶符号优先级低:此符号进栈  
		(默认栈顶若是左括号,左括号优先级最低)
		若栈顶符号优先级不低:将栈顶符号弹出并输出,之后进栈
		右括号:将栈顶符号弹出并输出,直到匹配左括号,将左括号和右括号同时舍弃
	遍历结束:将栈中的所有符号弹出并输出


7	基于后缀表达式运算
	遍历后缀表达式中的数字和符号
		对于数字:进栈
		对于符号:
			从栈中弹出右操作数
			从栈中弹出左操作数
			根据符号进行运算
			将运算结果压入栈中
	遍历结束:栈中的唯一数字为计算结果
8	

Code

  • 01 单向链表-企业版.c
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>

//节点结构体
struct LinkNode
{
	//只维护指针域
	struct LinkNode*next;
};

//链表结构体
struct LList
{
	struct LinkNode pHeader;
	int m_Size;
};

typedef void * LinkList;

//初始化链表
LinkList init_LinkList()
{
	struct LList * myList = malloc(sizeof(struct LList));

	if (myList == NULL)
	{
		return NULL;
	}

	myList->pHeader.next = NULL;
	myList->m_Size = 0;

	return myList;
}

//插入
void insert_LinkList(LinkList list ,  int pos , void * data)
{
	if (list == NULL)
	{
		return;
	}
	if (data == NULL)
	{
		return;
	}

	struct LList * myList = list;
	if (pos < 0 || pos >myList->m_Size - 1)
	{
		//无效位置进行尾插
		pos = myList->m_Size;
	}

	//用户数据前4个字节 由我们来使用
	struct LinkNode * myNode = data;

	//找插入节点的前驱节点
	struct LinkNode * pCurrent = &myList->pHeader;

	for (int i = 0; i < pos;i++)
	{
		pCurrent = pCurrent->next;
	}
	//pCurrent是前驱节点位置


	//更改指针指向
	myNode->next = pCurrent->next;
	pCurrent->next = myNode;

	//更新链表长度
	myList->m_Size++;
}

//遍历链表
void foreach_LinkList(LinkList list, void(*myForeach)(void *))
{
	if (list == NULL)
	{
		return;
	}

	struct LList * myList = list;

	struct LinkNode * myNode = myList->pHeader.next;

	for (int i = 0; i < myList->m_Size;i++)
	{
		myForeach(myNode);
		myNode = myNode->next;
	}

}

//删除节点 按位置删除
void removeByPos_ListList( LinkList list, int pos)
{
	if (list == NULL)
	{
		return;
	}

	struct LList * mylist = list;

	if (pos < 0 ||  pos > mylist->m_Size - 1)
	{
		return;
	}

	//找待删除节点的前驱位置
	struct LinkNode * pCurrent = &mylist->pHeader;
	for (int i = 0; i < pos;i++)
	{
		pCurrent = pCurrent->next;
	}

	//记录待删除节点
	struct LinkNode * pDel = pCurrent->next;


	//更改指针指向
	pCurrent->next = pDel->next;

	//free(pDel); //数据是用户管理开辟的,用户管理释放

	//更新长度
	mylist->m_Size--;
}

//销毁数组
void destroy_LinkList( LinkList list)
{
	if (list == NULL)
	{
		return;
	}

	free(list);
	list = NULL;

}






//测试

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


void myPrintPerson(void * data)
{
	struct Person * p = data;
	printf("姓名: %s  年龄: %d 
", p->name, p->age);
}

void test01()
{

	//初始化链表
	LinkList mylist = 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(mylist, 0, &p1);
	insert_LinkList(mylist, 0, &p2);
	insert_LinkList(mylist, 1, &p3);
	insert_LinkList(mylist, -1, &p4);
	insert_LinkList(mylist, 0, &p5);


	//遍历链表
	// eee bbb  ccc aaa ddd
	foreach_LinkList(mylist, myPrintPerson);

	//删除 aaa
	removeByPos_ListList(mylist, 3);
	printf("-----------------------
");
	foreach_LinkList(mylist, myPrintPerson);

	//销毁数组
	destroy_LinkList(mylist);
	mylist = NULL;

}


int main(){
	test01();


	system("pause");
	return EXIT_SUCCESS;
}

02 栈的顺序存储

  • 头文件 -- seqStack.h
#pragma  once
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>

#define  MAX 1024

//struct SStack
//{
//	void * data[MAX];  //栈的数组
//
//	int m_Size; //栈大小
//};

typedef void * SeqStack;

//初始化栈
SeqStack init_SeqStack();

//入栈
void push_SeqStack(SeqStack stack, void * data);

//出栈
void pop_SeqStack(SeqStack stack);

//返回栈顶
void * top_SeqStack(SeqStack stack);

//返回栈大小
int size_SeqStack(SeqStack stack);

//判断栈是否为空
int isEmpty_SeqStack(SeqStack stack);

//销毁栈
void destroy_SeqStack(SeqStack stack);
  • 源文件--seqStack.c
#include "seqStack.h"

struct SStack
{
	void * data[MAX];  //栈的数组

	int m_Size; //栈大小
};

//初始化栈
SeqStack init_SeqStack()
{
	struct SStack * myStack = malloc(sizeof(struct SStack));

	if (myStack == NULL)
	{
		return NULL;
	}

	//初始化数组
	memset(myStack->data, 0, sizeof(void *)* MAX);

	//初始化栈大小
	myStack->m_Size = 0;

	return myStack;
}
//入栈
void push_SeqStack(SeqStack stack, void * data)
{
	//入栈本质  --- 数组尾插
	if (stack == NULL)
	{
		return;
	}
	if (data == NULL)
	{
		return;
	}

	struct SStack * mystack = stack;
	if (mystack->m_Size == MAX)
	{
		return;
	}

	mystack->data[mystack->m_Size] = data;

	mystack->m_Size++;
}
//出栈
void pop_SeqStack(SeqStack stack)
{
	//出栈本质  --- 数组尾删
	if (stack == NULL)
	{
		return;
	}

	struct SStack * mystack = stack;

	if (mystack->m_Size == 0)
	{
		return;
	}

	mystack->data[mystack->m_Size - 1] = NULL;

	mystack->m_Size--;

}
//返回栈顶
void * top_SeqStack(SeqStack stack)
{
	if (stack == NULL)
	{
		return NULL;
	}

	struct SStack * mystack = stack;

	if (mystack->m_Size == 0)
	{
		return NULL;
	}
	return mystack->data[mystack->m_Size - 1];
}
//返回栈大小
int size_SeqStack(SeqStack stack)
{
	if (stack == NULL)
	{
		return -1;
	}

	struct SStack * mystack = stack;

	return mystack->m_Size;

}
//判断栈是否为空
int isEmpty_SeqStack(SeqStack stack)
{
	if (stack == NULL)
	{
		return -1;//返回-1代表真  空栈
	}

	struct SStack * mystack = stack;

	if (mystack->m_Size == 0)
	{
		return 1;
	}

	return 0; //返回0 代表 不是空栈

}
//销毁栈
void destroy_SeqStack(SeqStack stack)
{
	if (stack == NULL)
	{
		return;
	}

	free(stack);
	stack = NULL;
}
  • 源文件--02 栈的顺序存储.c
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include "seqStack.h"


//#define  MAX 1024
//
//struct SStack
//{
//	void * data[MAX];  //栈的数组
//
//	int m_Size; //栈大小
//};
//
//typedef void * SeqStack;
//
////初始化栈
//SeqStack init_SeqStack()
//{
//	struct SStack * myStack = malloc(sizeof(struct SStack));
//
//	if (myStack == NULL)
//	{
//		return NULL;
//	}
//
//	//初始化数组
//	memset(myStack->data, 0, sizeof(void *)* MAX);
//
//	//初始化栈大小
//	myStack->m_Size = 0;
//
//	return myStack;
//}
////入栈
//void push_SeqStack(SeqStack stack , void * data)
//{
//	//入栈本质  --- 数组尾插
//	if (stack == NULL)
//	{
//		return;
//	}
//	if ( data == NULL)
//	{
//		return;
//	}
//
//	struct SStack * mystack = stack;
//	if (mystack->m_Size == MAX)
//	{
//		return;
//	}
//
//	mystack->data[mystack->m_Size] = data;
//
//	mystack->m_Size++;
//}
////出栈
//void pop_SeqStack(SeqStack stack)
//{
//	//出栈本质  --- 数组尾删
//	if (stack == NULL)
//	{
//		return;
//	}
//
//	struct SStack * mystack = stack;
//
//	if (mystack->m_Size == 0)
//	{
//		return;
//	}
//
//	mystack->data[mystack->m_Size - 1] = NULL;
//
//	mystack->m_Size--;
//
//}
////返回栈顶
//void * top_SeqStack(SeqStack stack)
//{
//	if (stack == NULL)
//	{
//		return NULL;
//	}
//
//	struct SStack * mystack = stack;
//
//	if (mystack->m_Size == 0)
//	{
//		return NULL;
//	}
//	return mystack->data[mystack->m_Size - 1];
//}
////返回栈大小
//int size_SeqStack(SeqStack stack)
//{
//	if (stack == NULL)
//	{
//		return -1;
//	}
//
//	struct SStack * mystack = stack;
//
//	return mystack->m_Size;
//
//}
////判断栈是否为空
//int isEmpty_SeqStack(SeqStack stack)
//{
//	if (stack == NULL)
//	{
//		return -1;//返回-1代表真  空栈
//	}
//
//	struct SStack * mystack = stack;
//
//	if (mystack->m_Size == 0)
//	{
//		return 1;
//	}
//
//	return 0; //返回0 代表 不是空栈
//
//}
////销毁栈
//void destroy_SeqStack(SeqStack stack)
//{
//	if (stack == NULL)
//	{
//		return;
//	}
//
//	free(stack);
//	stack = NULL;
//}





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

void test01()
{
	//初始化栈
	SeqStack myStack = init_SeqStack();

	//创建数据
	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 };

	//入栈
	push_SeqStack(myStack, &p1);
	push_SeqStack(myStack, &p2);
	push_SeqStack(myStack, &p3);
	push_SeqStack(myStack, &p4);
	push_SeqStack(myStack, &p5);

	printf("栈的元素个数为:%d
", size_SeqStack(myStack));

	while (isEmpty_SeqStack(myStack) == 0) //栈不为空,查看栈顶元素,出栈
	{
		struct Person * p = top_SeqStack(myStack);
		printf("姓名:%s 年龄:%d
", p->name, p->age);

		//出栈
		pop_SeqStack(myStack);
	}

	printf("栈的元素个数为:%d
", size_SeqStack(myStack));

	//销毁栈
	destroy_SeqStack(myStack);
}

int main(){
	test01();


	system("pause");
	return EXIT_SUCCESS;
}

03 栈的链式存储.c

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>

//节点结构体
struct stackNode
{
	struct stackNode * next;
};

//栈的结构体
struct LStack
{
	struct stackNode  pHeader;
	int m_size;
};

typedef void * LinkStack;

//初始化
LinkStack init_LinkStack()
{
	struct LStack * myStack = malloc(sizeof( struct LStack));

	if (myStack == NULL)
	{
		return NULL;
	}
	myStack->pHeader.next = NULL;
	myStack->m_size = 0;

	return myStack;
}
//入栈
void push_LinkStack( LinkStack stack , void * data)
{
	//入栈本质 --- 链表头插
	if (stack == NULL)
	{
		return;
	}

	if (data == NULL)
	{
		return;
	}

	struct LStack * myStack = stack;

	//将用户数据 取出前4字节用
	struct stackNode * myNode = data;

	//更改指针指向
	myNode->next = myStack->pHeader.next;
	myStack->pHeader.next = myNode;

	//更新链表长度
	myStack->m_size++;

}

//出栈
void pop_LinkStack(LinkStack stack)
{
	//出栈本质 --- 链表头删
	if (stack == NULL)
	{
		return;
	}

	struct LStack * myStack = stack;

	if (myStack->m_size == 0)
	{
		return;
	}

	//更改指针指向
	//缓存第一个有数据节点
	struct stackNode * pFirst = myStack->pHeader.next;

	myStack->pHeader.next = pFirst->next;

	//更新栈大小
	myStack->m_size--;

}

//返回栈顶元素
void * top_LinkStack(LinkStack stack)
{
	if (stack == NULL)
	{
		return NULL;
	}
	struct LStack * myStack = stack;

	if (myStack->m_size == 0)
	{
		return NULL;
	}

	return myStack->pHeader.next;

}

//返回栈个数
int size_LinkStack(LinkStack stack)
{
	if (stack == NULL)
	{
		return -1;
	}
	struct LStack * myStack = stack;

	return myStack->m_size;
}

//判断是否为空
int isEmpty_LinkStack(LinkStack stack)
{
	if (stack == NULL)
	{
		return -1;
	}
	struct LStack * myStack = stack;

	if (myStack->m_size == 0)
	{
		return 1;
	}

	return 0;
}
//销毁
void destroy_LinkStack(LinkStack stack)
{
	if (stack == NULL)
	{
		return;
	}
	free(stack);
	stack = NULL;
}




//测试
struct Person
{
	void * node;
	char name[64];
	int age;
};

void test01()
{
	//初始化栈
	LinkStack myStack = init_LinkStack();

	//创建数据
	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 };

	//入栈
	push_LinkStack(myStack, &p1);
	push_LinkStack(myStack, &p2);
	push_LinkStack(myStack, &p3);
	push_LinkStack(myStack, &p4);
	push_LinkStack(myStack, &p5);

	printf("链式存储-- 栈的元素个数为:%d
", size_LinkStack(myStack));

	while (isEmpty_LinkStack(myStack) == 0) //栈不为空,查看栈顶元素,出栈
	{
		struct Person * p = top_LinkStack(myStack);
		printf("姓名:%s 年龄:%d
", p->name, p->age);

		//出栈
		pop_LinkStack(myStack);
	}

	printf("链式存储-- 栈的元素个数为:%d
", size_LinkStack(myStack));

	//销毁栈
	destroy_LinkStack(myStack);
}
int main(){

	test01();

	system("pause");
	return EXIT_SUCCESS;
}

04 栈的应用案例(就近匹配).c

  • 头文件-- seqStack.h
#pragma  once
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>

#define  MAX 1024

//struct SStack
//{
//	void * data[MAX];  //栈的数组
//
//	int m_Size; //栈大小
//};

typedef void * SeqStack;

//初始化栈
SeqStack init_SeqStack();

//入栈
void push_SeqStack(SeqStack stack, void * data);

//出栈
void pop_SeqStack(SeqStack stack);

//返回栈顶
void * top_SeqStack(SeqStack stack);

//返回栈大小
int size_SeqStack(SeqStack stack);

//判断栈是否为空
int isEmpty_SeqStack(SeqStack stack);

//销毁栈
void destroy_SeqStack(SeqStack stack);
  • 源文件--seqStack.c
#include "seqStack.h"

struct SStack
{
	void * data[MAX];  //栈的数组

	int m_Size; //栈大小
};

//初始化栈
SeqStack init_SeqStack()
{
	struct SStack * myStack = malloc(sizeof(struct SStack));

	if (myStack == NULL)
	{
		return NULL;
	}

	//初始化数组
	memset(myStack->data, 0, sizeof(void *)* MAX);

	//初始化栈大小
	myStack->m_Size = 0;

	return myStack;
}
//入栈
void push_SeqStack(SeqStack stack, void * data)
{
	//入栈本质  --- 数组尾插
	if (stack == NULL)
	{
		return;
	}
	if (data == NULL)
	{
		return;
	}

	struct SStack * mystack = stack;
	if (mystack->m_Size == MAX)
	{
		return;
	}

	mystack->data[mystack->m_Size] = data;

	mystack->m_Size++;
}
//出栈
void pop_SeqStack(SeqStack stack)
{
	//出栈本质  --- 数组尾删
	if (stack == NULL)
	{
		return;
	}

	struct SStack * mystack = stack;

	if (mystack->m_Size == 0)
	{
		return;
	}

	mystack->data[mystack->m_Size - 1] = NULL;

	mystack->m_Size--;

}
//返回栈顶
void * top_SeqStack(SeqStack stack)
{
	if (stack == NULL)
	{
		return NULL;
	}

	struct SStack * mystack = stack;

	if (mystack->m_Size == 0)
	{
		return NULL;
	}
	return mystack->data[mystack->m_Size - 1];
}
//返回栈大小
int size_SeqStack(SeqStack stack)
{
	if (stack == NULL)
	{
		return -1;
	}

	struct SStack * mystack = stack;

	return mystack->m_Size;

}
//判断栈是否为空
int isEmpty_SeqStack(SeqStack stack)
{
	if (stack == NULL)
	{
		return -1;//返回-1代表真  空栈
	}

	struct SStack * mystack = stack;

	if (mystack->m_Size == 0)
	{
		return 1;
	}

	return 0; //返回0 代表 不是空栈

}
//销毁栈
void destroy_SeqStack(SeqStack stack)
{
	if (stack == NULL)
	{
		return;
	}

	free(stack);
	stack = NULL;
}
  • 04 栈的应用案例(就近匹配).c
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include "seqStack.h"
/*
从第一个字符开始扫描
当遇见普通字符时忽略,
当遇见左括号时压入栈中
当遇见右括号时从栈中弹出栈顶符号,并进行匹配
匹配成功:继续读入下一个字符
匹配失败:立即停止,并报错
结束:
成功: 所有字符扫描完毕,且栈为空
失败:匹配失败或所有字符扫描完毕但栈非空
*/

int isLeft(char ch)
{
	return ch == '(';
}

int isRight(char ch)
{
	return ch == ')';
}

void printError(char * str, char * errMsg , char * pos)
{
	printf("错误信息:%s
", errMsg);

	printf("%s
", str);

	//计算打印空格数量
	int num = pos - str;

	for (int i = 0; i < num;i++)
	{
		printf(" ");
	}
	printf("|
");
}

void test01()
{

	char * str = "5+5*(6)+9/3*1)-(1+3(";
	//char * str = "5+5*(6)+9/3*1-(1+3(";


	char * p = str;

	//初始化栈
	SeqStack myStack = init_SeqStack();

	while ( *p != '')
	{
		//如果是左括号,入栈
		if (isLeft(*p))
		{
			//入栈
			push_SeqStack(myStack, p);
		}

		//如果是右括号 
		if (isRight(*p))
		{
			//栈中有元素   出栈
			if (size_SeqStack(myStack) > 0)
			{
				pop_SeqStack(myStack);
			}
			else
			{
				//右括号没有匹配到对应的左括号,立即停止,并报错
				printError(str,"右括号没有匹配到对应的左括号!", p);
				break;
			}
		}
		p++;
	}

	//遍历结束 判断是否有 左括号没有匹配到对应的右括号
	while (size_SeqStack(myStack) > 0)
	{
		printError(str, "左括号没有匹配到对应的右括号!", top_SeqStack(myStack));
		//出栈
		pop_SeqStack(myStack);
	}	

	//销毁栈
	destroy_SeqStack(myStack);
	myStack = NULL;


}

int main(){

	test01();

	system("pause");
	return EXIT_SUCCESS;
}

Day03

Code

01 队列的顺序存储

头文件

  • dynamicArray.h
#pragma  once
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>


//动态数组结构体
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);
  • seqQueue.h
#pragma  once 
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include "dynamicArray.h"
#define  MAX  1024

typedef void * seqQueue;

//初始化队列
seqQueue init_SeqQueue();
//入队
void push_SeqQueue(seqQueue queue , void * data);
//出队
void pop_SeqQueue(seqQueue queue);
//返回队列大小
int size_SeqQueue(seqQueue queue);
//判断队列是否为空
int isEmpty_SeqQueue(seqQueue queue);
//返回队头元素
void * front_SeqQueue(seqQueue queue);
//返回队尾元素
void * back_SeqQueue(seqQueue queue);
//销毁队列
void destroy_SeqQueue(seqQueue queue);

源文件

  • dynamicArray.c
#include "dynamicArray.h"


//初始化数组
struct dynamicArray * init_DynamicArray(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->m_capacity = capacity;
	array->m_size = 0;

	return array;
}

//插入数组
void insert_DynamicArray(struct dynamicArray * array, int pos, void * data)
{
	if (array == NULL)
	{
		return;
	}
	if (data == NULL)
	{
		return;
	}

	//无效位置  尾插
	if (pos < 0 || pos > array->m_size)
	{
		pos = array->m_size;
	}

	//判断是否满了,如果满动态扩展
	if (array->m_size == array->m_capacity)
	{
		//1、计算新空间大小
		int newCapacity = array->m_capacity * 2;

		//2、创建新空间
		void ** newSpace = malloc(sizeof(void *)* newCapacity);

		//3、将原有数据拷贝到新空间下
		memcpy(newSpace, array->pAddr, sizeof(void *)* array->m_capacity);

		//4、释放原有内存空间
		free(array->pAddr);

		//5、更新新空间指向
		array->pAddr = newSpace;

		//6、更新新容量
		array->m_capacity = newCapacity;
	}

	//插入新元素

	//移动元素 进行插入新元素
	for (int i = array->m_size - 1; i >= pos; i--)
	{
		//数据向后移动
		array->pAddr[i + 1] = array->pAddr[i];
	}

	//将新元素 插入到指定位置上
	array->pAddr[pos] = data;
	//更新大小
	array->m_size++;
}


//遍历数组
void foreach_DynamicArray(struct dynamicArray * array, void(*myPrint)(void*))
{
	if (array == NULL)
	{
		return;
	}
	if (myPrint == NULL)
	{
		return;
	}

	for (int i = 0; i < array->m_size; i++)
	{
		myPrint(array->pAddr[i]);
	}
}


//删除数组  按位置删除
void removeByPos_DynamicArray(struct dynamicArray * array, int pos)
{
	if (NULL == array)
	{
		return;
	}

	if (pos < 0 || pos > array->m_size - 1)
	{
		return;
	}

	//数据前移
	for (int i = pos; i < array->m_size - 1; i++)
	{
		array->pAddr[i] = array->pAddr[i + 1];
	}

	//更新数组大小
	array->m_size--;

}

//按值删除数据
void removeByValue_DynamicArray(struct dynamicArray * array, void * data, int(*myCompare)(void *, void *))
{
	if (array == NULL)
	{
		return;
	}
	if (data == NULL)
	{
		return;
	}

	for (int i = 0; i < array->m_size; i++)
	{
		if (myCompare(array->pAddr[i], data))
		{
			//如果找到要删除的数据,i就是要删除的具体位置
			removeByPos_DynamicArray(array, i);
			break;
		}
	}

}

//销毁数组
void destroy_DynamicArray(struct dynamicArray* array)
{
	if (array == NULL)
	{
		return;
	}

	if (array->pAddr != NULL)
	{
		free(array->pAddr);
		array->pAddr = NULL;
	}


	free(array);
	array = NULL;
}
  • seqQueue.c
#include "seqQueue.h"

//初始化队列
seqQueue init_SeqQueue()
{
	struct dynamicArray * arr = init_DynamicArray(MAX);

	return arr;
}
//入队
void push_SeqQueue(seqQueue queue, void * data)
{
	//本质  尾插
	
	if (queue == NULL)
	{
		return;
	}
	if ( data == NULL)
	{
		return;
	}
	struct dynamicArray * myQueue = queue;
	if (myQueue->m_size == MAX)
	{
		return;
	}

	insert_DynamicArray(myQueue, myQueue->m_size, data);

}
//出队
void pop_SeqQueue(seqQueue queue)
{
	//本质  头删

	if (queue == NULL)
	{
		return;
	}

	struct dynamicArray * myQueue = queue;

	if (myQueue->m_size <= 0 )
	{
		return;
	}

	removeByPos_DynamicArray(myQueue, 0);

}
//返回队列大小
int size_SeqQueue(seqQueue queue)
{
	if (queue == NULL)
	{
		return -1;
	}

	struct dynamicArray * myQueue = queue;

	return myQueue->m_size;

}
//判断队列是否为空
int isEmpty_SeqQueue(seqQueue queue)
{
	if (queue == NULL)
	{
		return -1;
	}
	struct dynamicArray * myQueue = queue;

	if (myQueue->m_size == 0)
	{
		return 1;
	}
	return 0;


}
//返回队头元素
void * front_SeqQueue(seqQueue queue)
{
	if (queue == NULL)
	{
		return NULL;
	}
	struct dynamicArray * myQueue = queue;

	return myQueue->pAddr[0];

}
//返回队尾元素
void * back_SeqQueue(seqQueue queue)
{
	if (queue == NULL)
	{
		return NULL;
	}
	struct dynamicArray * myQueue = queue;

	return myQueue->pAddr[myQueue->m_size-1];
}
//销毁队列
void destroy_SeqQueue(seqQueue queue)
{
	if (queue == NULL)
	{
		return;
	}
	
	destroy_DynamicArray(queue);

}
  • 01 队列的顺序存储.c
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include "seqQueue.h"

struct Person
{
	char name[64];
	int age;
};
void test01()
{
	//初始化队列
	seqQueue myQueue= init_SeqQueue();

	//准备数据
	struct Person p1 = { "aaa", 10 };
	struct Person p2 = { "bbb", 20 };
	struct Person p3 = { "ccc", 30 };
	struct Person p4 = { "ddd", 40 };


	//入队
	push_SeqQueue(myQueue, &p1);
	push_SeqQueue(myQueue, &p2);
	push_SeqQueue(myQueue, &p3);
	push_SeqQueue(myQueue, &p4);
	printf("队列大小为:%d
", size_SeqQueue(myQueue));
	while ( isEmpty_SeqQueue(myQueue) == 0)
	{
		//访问队头
		struct Person * pFront = front_SeqQueue(myQueue);
		printf("队头元素 -- 姓名:%s  年龄: %d
", pFront->name, pFront->age);
		//访问队尾
		struct Person * pBack = back_SeqQueue(myQueue);
		printf("队尾元素 -- 姓名:%s  年龄: %d
", pBack->name, pBack->age);
		//出队
		pop_SeqQueue(myQueue);
	}

	printf("队列大小为:%d
", size_SeqQueue(myQueue));

	//销毁队列
	destroy_SeqQueue(myQueue);

}



int main(){
	test01();


	system("pause");
	return EXIT_SUCCESS;
}

02 队列的链式存储

头文件

  • linkQueue.h
#pragma  once
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>


//节点结构体
struct QueueNode
{
	struct QueueNode * next;
};

//队列结构体
struct LQueue
{
	struct QueueNode pHeader;
	int m_size;
	struct QueueNode * pTail;
};

typedef void * LinkQueue;

//初始化队列
LinkQueue init_LinkQueue();
//入队
void push_LinkQueue(LinkQueue queue , void * data);
//出队
void pop_LinkQueue(LinkQueue queue);
//返回队列大小
int size_LinkQueue(LinkQueue queue);
//判断是否为空
int isEmpty_LinkQueue(LinkQueue queue);
//返回队头
void * front_LinkQueue(LinkQueue queue);
//返回队尾
void * back_LinkQueue(LinkQueue queue);
//销毁队列
void destroy_LinkQueue(LinkQueue queue);

源文件

  • linkQueue.c
#include "linkQueue.h"

//初始化队列
LinkQueue init_LinkQueue()
{
	 struct LQueue * myQueue = malloc(sizeof(struct  LQueue));

	 if (myQueue == NULL)
	 {
		 return NULL;
	 }

	 myQueue->pHeader.next = NULL;

	 myQueue->m_size = 0;

	 myQueue->pTail = &myQueue->pHeader;

	 return myQueue;
}
//入队
void push_LinkQueue(LinkQueue queue, void * data)
{
	if (queue == NULL)
	{
		return;
	}
	if ( data == NULL)
	{
		return;
	}

	//本质 尾插
	struct LQueue * myQueue = queue;


	struct QueueNode * myNode = data;

	//更改指针指向
	myQueue->pTail->next = myNode;
	myNode->next = NULL;

	//更新新的尾节点
	myQueue->pTail = myNode;

	myQueue->m_size++;

}
//出队
void pop_LinkQueue(LinkQueue queue)
{
	if (queue == NULL)
	{
		return;
	}

	struct LQueue * myQueue = queue;

	//本质 头删

	if (myQueue->m_size == 0)
	{
		return;
	}

	if (myQueue->m_size == 1)
	{
		myQueue->pHeader.next = NULL;
		myQueue->pTail = &myQueue->pHeader;  //1个节点的时候,要将尾节点还原到头
		myQueue->m_size--;
		return;
	}

	//记录第一个有数据的节点
	struct QueueNode * pFirst = myQueue->pHeader.next;

	//更改指针指向
	myQueue->pHeader.next = pFirst->next;

	myQueue->m_size--;

}
//返回队列大小
int size_LinkQueue(LinkQueue queue)
{
	if (queue == NULL)
	{
		return -1;
	}

	struct LQueue * myQueue = queue;
	return myQueue->m_size;


}
//判断是否为空
int isEmpty_LinkQueue(LinkQueue queue)
{
	if (queue == NULL)
	{
		return -1;
	}

	struct LQueue * myQueue = queue;
	if (myQueue->m_size == 0)
	{
		return 1;
	}
	return 0;

}
//返回队头
void * front_LinkQueue(LinkQueue queue)
{
	if (queue == NULL)
	{
		return NULL;
	}

	struct LQueue * myQueue = queue;

	return myQueue->pHeader.next;

}
//返回队尾
void * back_LinkQueue(LinkQueue queue)
{
	if (queue == NULL)
	{
		return NULL;
	}

	struct LQueue * myQueue = queue;
	return myQueue->pTail;
}
//销毁队列
void destroy_LinkQueue(LinkQueue queue)
{
	if (queue == NULL)
	{
		return;
	}

	free(queue);
	queue = NULL;

}
  • 02 队列的链式存储.c
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include "linkQueue.h"

struct Person
{
	void * node;
	char name[64];
	int age;
};
void test01()
{
	//初始化队列
	LinkQueue myQueue = init_LinkQueue();

	//准备数据
	struct Person p1 = { NULL,"aaa", 10 };
	struct Person p2 = { NULL,"bbb", 20 };
	struct Person p3 = { NULL,"ccc", 30 };
	struct Person p4 = { NULL,"ddd", 40 };


	//入队
	push_LinkQueue(myQueue, &p1);
	push_LinkQueue(myQueue, &p2);
	push_LinkQueue(myQueue, &p3);
	push_LinkQueue(myQueue, &p4);
	printf("队列大小为:%d
", size_LinkQueue(myQueue));
	while (isEmpty_LinkQueue(myQueue) == 0)
	{
		//访问队头
		struct Person * pFront = front_LinkQueue(myQueue);
		printf("链式存储::队头元素 -- 姓名:%s  年龄: %d
", pFront->name, pFront->age);
		//访问队尾
		struct Person * pBack = back_LinkQueue(myQueue);
		printf("链式存储::队尾元素 -- 姓名:%s  年龄: %d
", pBack->name, pBack->age);
		//出队
		pop_LinkQueue(myQueue);
	}

	printf("队列大小为:%d
", size_LinkQueue(myQueue));

	//销毁队列
	destroy_LinkQueue(myQueue);

}

int main(){

	test01();

	system("pause");
	return EXIT_SUCCESS;
}

03 二叉树的递归遍历.c

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>

struct BinaryNode
{
	//数据域
	char ch;
	//指针域
	struct BinaryNode * lChild;
	struct BinaryNode * rChild;
};


void recursion(struct BinaryNode * root)
{
	if (root == NULL)
	{
		return;
	}

	//先序遍历
	printf("%c ", root->ch);

	recursion(root->lChild);

	recursion(root->rChild);

}


void test01()
{
	struct BinaryNode nodeA = { 'A', NULL, NULL };
	struct BinaryNode nodeB = { 'B', NULL, NULL };
	struct BinaryNode nodeC = { 'C', NULL, NULL };
	struct BinaryNode nodeD = { 'D', NULL, NULL };
	struct BinaryNode nodeE = { 'E', NULL, NULL };
	struct BinaryNode nodeF = { 'F', NULL, NULL };
	struct BinaryNode nodeG = { 'G', NULL, NULL };
	struct BinaryNode nodeH = { 'H', NULL, NULL };

	//建立关系
	nodeA.lChild = &nodeB;
	nodeA.rChild = &nodeF;

	nodeB.rChild = &nodeC;
	
	nodeC.lChild = &nodeD;
	nodeC.rChild = &nodeE;

	nodeF.rChild = &nodeG;
	
	nodeG.lChild = &nodeH;

	//递归遍历
	recursion(&nodeA);

}


int main(){

	test01();

	system("pause");
	return EXIT_SUCCESS;
}

04 二叉树编程.c

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>

struct BinaryNode
{
	//数据域
	char ch;
	//指针域
	struct BinaryNode * lChild;
	struct BinaryNode * rChild;
};


void calculateLeafNum(struct BinaryNode * root, int * p)
{
	if (root == NULL)
	{
		return;
	}

	//如果节点 左子树 与右子树 同时为空  称为叶子
	if (root->lChild == NULL && root->rChild == NULL)
	{
		(*p)++;
	}

	calculateLeafNum(root->lChild, p);

	calculateLeafNum(root->rChild, p);

}

//获取树高度
int getTreeHeight(struct BinaryNode * root)
{
	if (root == NULL)
	{
		return 0;
	}

	//获取左子树高度 
	int  lHeight = getTreeHeight(root->lChild);
	//获取右子树高度
	int  rHeight = getTreeHeight(root->rChild);
	//从左子树和右子树中取大的值+1
	int height = lHeight > rHeight ? lHeight + 1 : rHeight + 1;

	return height;
}

//拷贝二叉树
struct BinaryNode * copyTree(struct BinaryNode * root)
{
	if (root ==NULL)
	{
		return NULL;
	}

	//先拷贝左子树
	struct BinaryNode * lChild = copyTree(root->lChild);
	//再拷贝右子树
	struct BinaryNode * rChild = copyTree(root->rChild);

	struct BinaryNode * newNode = malloc(sizeof(struct BinaryNode));
	newNode->ch = root->ch;

	newNode->lChild = lChild;

	newNode->rChild = rChild;

	return newNode;
}

void recursion(struct BinaryNode * root)
{
	if (root == NULL)
	{
		return;
	}

	printf("%c ", root->ch);

	recursion(root->lChild);

	recursion(root->rChild);

}


void freeTree(struct BinaryNode * root)
{
	if (root == NULL)
	{
		return;
	}

	//先释放左子树
	freeTree(root->lChild);
	//再释放右子树
	freeTree(root->rChild);
	//释放根
	printf("%c被释放了
", root->ch);
	free(root);
}

void test01()
{
	struct BinaryNode nodeA = { 'A', NULL, NULL };
	struct BinaryNode nodeB = { 'B', NULL, NULL };
	struct BinaryNode nodeC = { 'C', NULL, NULL };
	struct BinaryNode nodeD = { 'D', NULL, NULL };
	struct BinaryNode nodeE = { 'E', NULL, NULL };
	struct BinaryNode nodeF = { 'F', NULL, NULL };
	struct BinaryNode nodeG = { 'G', NULL, NULL };
	struct BinaryNode nodeH = { 'H', NULL, NULL };

	//建立关系
	nodeA.lChild = &nodeB;
	nodeA.rChild = &nodeF;

	nodeB.rChild = &nodeC;

	nodeC.lChild = &nodeD;
	nodeC.rChild = &nodeE;

	nodeF.rChild = &nodeG;

	nodeG.lChild = &nodeH;

	//1、求二叉树 叶子数量
	int num = 0;
	calculateLeafNum(&nodeA, &num);

	printf("树的叶子数量为:%d
", num);


	//2、 求树的高度/深度
	int height = getTreeHeight( &nodeA);

	printf("树的高度为:%d
", height);


	//3、 拷贝二叉树
	struct BinaryNode * newTree = copyTree(&nodeA);

	//递归遍历
	recursion(newTree);

	printf("
");
	//4、 释放二叉树
	freeTree(newTree);


}


int main(){
	test01();


	system("pause");
	return EXIT_SUCCESS;
}

05 二叉树非递归遍历

头文件

  • seqStack.h
#pragma  once
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>

#define  MAX 1024

//struct SStack
//{
//	void * data[MAX];  //栈的数组
//
//	int m_Size; //栈大小
//};

typedef void * SeqStack;

//初始化栈
SeqStack init_SeqStack();

//入栈
void push_SeqStack(SeqStack stack, void * data);

//出栈
void pop_SeqStack(SeqStack stack);

//返回栈顶
void * top_SeqStack(SeqStack stack);

//返回栈大小
int size_SeqStack(SeqStack stack);

//判断栈是否为空
int isEmpty_SeqStack(SeqStack stack);

//销毁栈
void destroy_SeqStack(SeqStack stack);

源文件

  • seqStack.c
#include "seqStack.h"

struct SStack
{
	void * data[MAX];  //栈的数组

	int m_Size; //栈大小
};

//初始化栈
SeqStack init_SeqStack()
{
	struct SStack * myStack = malloc(sizeof(struct SStack));

	if (myStack == NULL)
	{
		return NULL;
	}

	//初始化数组
	memset(myStack->data, 0, sizeof(void *)* MAX);

	//初始化栈大小
	myStack->m_Size = 0;

	return myStack;
}
//入栈
void push_SeqStack(SeqStack stack, void * data)
{
	//入栈本质  --- 数组尾插
	if (stack == NULL)
	{
		return;
	}
	if (data == NULL)
	{
		return;
	}

	struct SStack * mystack = stack;
	if (mystack->m_Size == MAX)
	{
		return;
	}

	mystack->data[mystack->m_Size] = data;

	mystack->m_Size++;
}
//出栈
void pop_SeqStack(SeqStack stack)
{
	//出栈本质  --- 数组尾删
	if (stack == NULL)
	{
		return;
	}

	struct SStack * mystack = stack;

	if (mystack->m_Size == 0)
	{
		return;
	}

	mystack->data[mystack->m_Size - 1] = NULL;

	mystack->m_Size--;

}
//返回栈顶
void * top_SeqStack(SeqStack stack)
{
	if (stack == NULL)
	{
		return NULL;
	}

	struct SStack * mystack = stack;

	if (mystack->m_Size == 0)
	{
		return NULL;
	}
	return mystack->data[mystack->m_Size - 1];
}
//返回栈大小
int size_SeqStack(SeqStack stack)
{
	if (stack == NULL)
	{
		return -1;
	}

	struct SStack * mystack = stack;

	return mystack->m_Size;

}
//判断栈是否为空
int isEmpty_SeqStack(SeqStack stack)
{
	if (stack == NULL)
	{
		return -1;//返回-1代表真  空栈
	}

	struct SStack * mystack = stack;

	if (mystack->m_Size == 0)
	{
		return 1;
	}

	return 0; //返回0 代表 不是空栈

}
//销毁栈
void destroy_SeqStack(SeqStack stack)
{
	if (stack == NULL)
	{
		return;
	}

	free(stack);
	stack = NULL;
}
  • 05 二叉树非递归遍历.c
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include "seqStack.h"

struct BinaryNode
{
	//数据域
	char ch;
	//指针域
	struct BinaryNode * lChild;
	struct BinaryNode * rChild;
	//标志
	int flag;
};


/*
1、将根节点 入栈 
2、只要栈中元素个数大于 0  执行循环
	获取栈顶元素
	出栈
	如果标志位真  直接输出  并且执行下一次循环
	如果为假 将标志改为真
	将右子树  左子树 根 入栈
	执行下一次循环
*/

void nonRecursion(struct BinaryNode * root)
{
	//初始化栈
	SeqStack myStack = init_SeqStack();

	push_SeqStack(myStack, root);

	while (size_SeqStack(myStack) > 0)
	{
		//获取栈顶元素
		struct BinaryNode * pTop = top_SeqStack(myStack);

		//出栈
		pop_SeqStack(myStack);

		//如果标志位真  直接输出  并且执行下一次循环
		if (pTop->flag == 1)
		{
			printf("%c ", pTop->ch);
			continue;
		}
		//如果为假 将标志改为真
		pTop->flag = 1;

		//将右子树  左子树 根 入栈
		if (pTop->rChild != NULL)
		{
			push_SeqStack(myStack, pTop->rChild);
		}
		if (pTop->lChild != NULL)
		{
			push_SeqStack(myStack, pTop->lChild);
		}
		push_SeqStack(myStack, pTop);

	}

	//销毁栈
	destroy_SeqStack(myStack);

}

void test01()
{
	struct BinaryNode nodeA = { 'A', NULL, NULL,0 };
	struct BinaryNode nodeB = { 'B', NULL, NULL,0 };
	struct BinaryNode nodeC = { 'C', NULL, NULL,0 };
	struct BinaryNode nodeD = { 'D', NULL, NULL,0 };
	struct BinaryNode nodeE = { 'E', NULL, NULL,0 };
	struct BinaryNode nodeF = { 'F', NULL, NULL,0 };
	struct BinaryNode nodeG = { 'G', NULL, NULL,0 };
	struct BinaryNode nodeH = { 'H', NULL, NULL,0 };

	//建立关系
	nodeA.lChild = &nodeB;
	nodeA.rChild = &nodeF;

	nodeB.rChild = &nodeC;

	nodeC.lChild = &nodeD;
	nodeC.rChild = &nodeE;

	nodeF.rChild = &nodeG;

	nodeG.lChild = &nodeH;

	//非递归遍历
	nonRecursion(&nodeA);

	



}

int main(){
	test01();


	system("pause");
	return EXIT_SUCCESS;
}

06 插入排序.c

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>

void insertSort(int arr[], int len)
{
	for (int i = 1; i < len;i++)
	{
		if (arr[i-1] > arr[i])
		{
			int temp = arr[i];
			int j = i - 1;
			for (; j >= 0 && temp < arr[j]; j--)
			{
				//数据后移
				arr[j + 1] = arr[j];
			}
			arr[j + 1] = temp;
		}
	}
}

void printArray(int arr[] ,int len)
{
	for (int i = 0; i < len; i++)
	{
		printf("%d
",arr[i]);
	}
}

void test01()
{
	int arr[] = { 4, 1, 2, 3, 5, 7, 6 };
	//插入排序
	int len = sizeof(arr) / sizeof(int);
	insertSort(arr, len);

	//打印数组
	printArray(arr, len);

}

int main(){

	test01();

	system("pause");
	return EXIT_SUCCESS;
}
原文地址:https://www.cnblogs.com/zranguai/p/14999546.html