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\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(){
//初始化动态数组
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\n", 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\n", array->m_capacity, array->m_size);
//测试删除 按位置删除
removeByPos_DynamicArray(array, 2);
printf("---------------------\n");
foreach_DynamicArray(array, myPrintPerson);
printf("删除数据后: 容量:%d 大小:%d\n", array->m_capacity, array->m_size);
struct Person p = { "亚瑟", 18 };
removeByValue_DynamicArray(array, &p, myComparePerson);
printf("---------------------\n");
foreach_DynamicArray(array, myPrintPerson);
printf("删除数据后: 容量:%d 大小:%d\n", 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\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 = { "亚瑟", 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\n", 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\n", size_LinkList(mylist));
//测试删除
removeByPos_LinkList(mylist, 4);
printf("------------------\n");
foreach_LinkList(mylist, myPrintPerson);
printf("链表长度为:%d\n", size_LinkList(mylist));
struct Person p = { "孙悟空", 999 };
removeByValue_LinkList(mylist, &p, myComparePerson);
printf("------------------\n");
foreach_LinkList(mylist, myPrintPerson);
printf("链表长度为:%d\n", size_LinkList(mylist));
//测试清空
clear_LinkList(mylist);
//返回链表长度
printf("链表长度为:%d\n", 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 \n", 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("-----------------------\n");
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\n", size_SeqStack(myStack));
while (isEmpty_SeqStack(myStack) == 0) //栈不为空,查看栈顶元素,出栈
{
struct Person * p = top_SeqStack(myStack);
printf("姓名:%s 年龄:%d\n", p->name, p->age);
//出栈
pop_SeqStack(myStack);
}
printf("栈的元素个数为:%d\n", 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\n", size_LinkStack(myStack));
while (isEmpty_LinkStack(myStack) == 0) //栈不为空,查看栈顶元素,出栈
{
struct Person * p = top_LinkStack(myStack);
printf("姓名:%s 年龄:%d\n", p->name, p->age);
//出栈
pop_LinkStack(myStack);
}
printf("链式存储-- 栈的元素个数为:%d\n", 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\n", errMsg);
printf("%s\n", str);
//计算打印空格数量
int num = pos - str;
for (int i = 0; i < num;i++)
{
printf(" ");
}
printf("|\n");
}
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 != '\0')
{
//如果是左括号,入栈
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\n", size_SeqQueue(myQueue));
while ( isEmpty_SeqQueue(myQueue) == 0)
{
//访问队头
struct Person * pFront = front_SeqQueue(myQueue);
printf("队头元素 -- 姓名:%s 年龄: %d\n", pFront->name, pFront->age);
//访问队尾
struct Person * pBack = back_SeqQueue(myQueue);
printf("队尾元素 -- 姓名:%s 年龄: %d\n", pBack->name, pBack->age);
//出队
pop_SeqQueue(myQueue);
}
printf("队列大小为:%d\n", 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\n", size_LinkQueue(myQueue));
while (isEmpty_LinkQueue(myQueue) == 0)
{
//访问队头
struct Person * pFront = front_LinkQueue(myQueue);
printf("链式存储::队头元素 -- 姓名:%s 年龄: %d\n", pFront->name, pFront->age);
//访问队尾
struct Person * pBack = back_LinkQueue(myQueue);
printf("链式存储::队尾元素 -- 姓名:%s 年龄: %d\n", pBack->name, pBack->age);
//出队
pop_LinkQueue(myQueue);
}
printf("队列大小为:%d\n", 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被释放了\n", 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\n", num);
//2、 求树的高度/深度
int height = getTreeHeight( &nodeA);
printf("树的高度为:%d\n", height);
//3、 拷贝二叉树
struct BinaryNode * newTree = copyTree(&nodeA);
//递归遍历
recursion(newTree);
printf("\n");
//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\n",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;
}
03-数据结构(C语言版)的更多相关文章
- 《数据结构-C语言版》(严蔚敏,吴伟民版)课本源码+习题集解析使用说明
<数据结构-C语言版>(严蔚敏,吴伟民版)课本源码+习题集解析使用说明 先附上文档归类目录: 课本源码合辑 链接☛☛☛ <数据结构>课本源码合辑 习题集全解析 链接☛☛☛ ...
- 数据结构C语言版 有向图的十字链表存储表示和实现
/*1wangxiaobo@163.com 数据结构C语言版 有向图的十字链表存储表示和实现 P165 编译环境:Dev-C++ 4.9.9.2 */ #include <stdio.h> ...
- 数据结构C语言版 表插入排序 静态表
数据结构C语言版 表插入排序.txt两个人吵架,先说对不起的人,并不是认输了,并不是原谅了.他只是比对方更珍惜这份感情./* 数据结构C语言版 表插入排序 算法10.3 P267-P270 编译 ...
- 数据结构C语言版 弗洛伊德算法实现
/* 数据结构C语言版 弗洛伊德算法 P191 编译环境:Dev-C++ 4.9.9.2 */ #include <stdio.h>#include <limits.h> # ...
- c++学习书籍推荐《清华大学计算机系列教材:数据结构(C++语言版)(第3版)》下载
百度云及其他网盘下载地址:点我 编辑推荐 <清华大学计算机系列教材:数据结构(C++语言版)(第3版)>习题解析涵盖验证型.拓展型.反思型.实践型和研究型习题,总计290余道大题.525道 ...
- 深入浅出数据结构C语言版(8)——后缀表达式、栈与四则运算计算器
在深入浅出数据结构(7)的末尾,我们提到了栈可以用于实现计算器,并且我们给出了存储表达式的数据结构(结构体及该结构体组成的数组),如下: //SIZE用于多个场合,如栈的大小.表达式数组的大小 #de ...
- 【数据结构(C语言版)系列二】 栈
栈和队列是两种重要的线性结构.从数据结构角度看,栈和队列也是线性表,但它们是操作受限的线性表,因此,可称为限定性的数据结构.但从数据类型角度看,它们是和线性表大不相同的两类重要的抽象数据类型. 栈的定 ...
- 深入浅出数据结构C语言版(5)——链表的操作
上一次我们从什么是表一直讲到了链表该怎么实现的想法上:http://www.cnblogs.com/mm93/p/6574912.html 而这一次我们就要实现所说的承诺,即实现链表应有的操作(至于游 ...
- 【数据结构(C语言版)系列三】 队列
队列的定义 队列是一种先进先出的线性表,它只允许在表的一端进行插入,而在另一端删除元素.这和我们日常生活中的排队是一致的,最早进入队列的元素最早离开.在队列中,允许插入的一端叫做队尾(rear),允许 ...
- 深入浅出数据结构C语言版(4)——表与链表
在我们谈论本文具体内容之前,我们首先要说明一些事情.在现实生活中我们所说的"表"往往是二维的,比如课程表,就有行和列,成绩表也是有行和列.但是在数据结构,或者说我们本文讨论的范围内 ...
随机推荐
- 分享一个自己写的基于canvas的原生js图片爆炸插件
DEMO访问地址: https://bupt-hjm.github.io/BoomGo/博客地址: http://bupt-hjm.github.io/2016/07/10/boom/插件及使用方法地 ...
- python爬取梦幻西游召唤兽资质信息(不包含变异)
一.分析 1.爬取网站:https://xyq.163.com/chongwu/ 2.获取网页源码: request.get("https://xyq.163.com/chongwu/&qu ...
- Java/C++实现备忘录模式--撤销操作
改进课堂上的"用户信息操作撤销"实例,使得系统可以实现多次撤销(可以使用HashMap.ArrayList等集合数据结构实现). 类图: Java代码: import java.u ...
- sring框架的jdbc应用
xml配置 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http: ...
- python+pytest接口自动化(13)-token关联登录
在PC端登录公司的后台管理系统或在手机上登录某个APP时,经常会发现登录成功后,返回参数中会包含token,它的值为一段较长的字符串,而后续去请求的请求头中都需要带上这个token作为参数,否则就提示 ...
- linux – tty,ttyS,pts,ptmx,vcs,vcsa设备文件之间的区别?(/dev/tty等)
linux – tty,ttyS,pts,ptmx,vcs,vcsa设备文件之间的区别? 终端有字符终端和图形终端两种模式.在linux的图形环境下,我们可以通过鼠标点击来完成所有的管理任务,这是图形 ...
- 服务器的cpu 核心、线程
此版本有大范围改动,因为cpu作为一个大脑,所以更细致的进行了,相关的分析和阐述. 1.版本1. 2022.1.242.版本2: 2022.3.2 采集数据: ht2机器为物理机,cpu是4颗cpu, ...
- 【转载】Java密钥库及keytool使用详解
---------------- 版权声明:本文为CSDN博主「adrninistrat0r」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明. 原文链接:https: ...
- Azure Virtual Desktop(一)创建配置管理
一,引言 Azure 虚拟创面是一项 Azure 服务,可以让我们管理: 1)VDI(虚拟桌面基础架构) 2)云端的 RDSH:RDSH 是 RDS(远程桌面服务)中的一个角色.这些类型的服务器用于托 ...
- Java语言学习day19--7月25日
今日内容介绍1.继承2.抽象类3.综合案例---员工类系列定义 ###01继承的概述 *A:继承的概念 *a:继承描述的是事物之间的所属关系,通过继承可以使多种事物之间形成一种关系体系 *b:在Jav ...