由于我本人呢,不擅长写一些纯理论的东西,可是这些有些东西还是需要记一下,数据结构与算法,可以说是程序设计的灵魂,这样说似乎有点夸张,其实一点也不夸张。
由于我本科是不开设数据结构与算法这门课的,看那些资料书吧,大多数都是为了代码的规范,反复的定义一些基本的数据类型,入门学起来有些吃力,所以我主要围绕一个自己学习的过程来编写本篇博客,大概是关于一些排序算法,堆栈,队列,链表,树,图的学习记录,所有的程序我都会在Linux上跑一遍(为什么用Linux呢,因为本人懒惰成性,不喜欢用鼠标,所以选择Linux环境来学习,可是对于这些基础的东西,需要掌握的闹靠一点,还是建议选择类似于Vim这样的工具来编写程序,当然还有,你想几乎全键盘操作,在女生面前写起程序来,多装逼啊,当然这些都是玩笑话,也不全是我选择Linux开发的理由),当然,所有的源代码,我将上传到GitHub,供有兴趣者一起学习交流,由于毕业设计和找工作的原因,更新可能不会很快。
那么,我们就这么愉快的开始吧!
这是下载链接 https://download.youkuaiyun.com/my
什么是数据结构:
数据结构的起源:
1968年美国高刚纳德教授开一门课叫《基本算法》,开创了数据结构的先河。
尼古拉斯.沃斯 数据结构+算法=程序 获得了 图灵奖
数据结构主要是研究,程序设计中非数值计算的数据对象,以及对象的操作与对象之间的关系。
数据结构的相关概念:
数据:描述客观信息的符号
数据项:存储数据的域
数据元素:描述一个事物的个体(学生)
数据结构:数据元素 + 数据元素之间的关系构成的整体
算法:数据结构具有的某项功能,有限指令序列结合。
数据结构的三个方面:
数据的逻辑结构
数据的存储结构
数据结构的运算
数据元素的逻辑结构有哪些
1.集合结构:元素之间除了同属于一个集体之外没有任何关系。
2.线性结构:元素之间存在一对一的关系。
3.树型结构:元素之间存在一对多的关系。
4.图型结构:元素之间存在多对多的关系。(智能车位,扫地机器人,人工智能)
数据元素的存储结构:
1.顺序结构:元素是顺序排放的,元素与元素之间没有间隙
可以随机访问,速度快效率高,内存利用率低,元素的添加和删除麻烦。
2.链式结构:元素与元素之间通过一条线(指针)来连接。
元素的添加删除方便,内存利用率高,不支持随机访问,只能从头到尾进行遍历。
逻辑结构与存储结构的关系
逻辑结构是认为赋予元素的,存储结构是元素在内存中的存储位置形成的。
线性表: 顺序表(数组) 链式表(链表)
树: 顺序表(数组) 链式表(链表)
图: 混合(顺序+链式)
顺序表实现:
假设c中没有数组,如何封装一个数组。
结构体:
存储空间
长度
算法:
创建
销毁
添加
插入
删除
查找
访问
排序
遍历
//暂时就先实现这些功能吧,也欢迎大家一起交流学习。
#define TYPE int
//数据结构体
typedef struct Array
{
TYPE *ptr;
int len;
int i;
}Array;
//创建
Array *creat_array(int len);
//销毁
void destory_array(Array *arr);
//添加元素
bool add_array(Array *arr,TYPE val);
//删除指定位置元素
bool delete_array(Array *arr,int index);
//从指定位置插入元素
bool insert_array(Array *arr,int index,TYPE val);
//根据值查找返回元素的下标
TYPE find_array(Array *arr,TYPE val);
//访问元素
TYPE at_array(Array *arr,int index);
//排序
void sort_array(Array *arr);
//遍历
void show_array(Array *arr);
这是实现程序,实现改程序的时候,需要注意内存申请和释放的问题
//数据结构体
typedef struct Array
{
TYPE *ptr;
int len;
int i;
}Array;
//创建
Array *creat_array(int len)
{
Array *arr = malloc(sizeof(Array));
if(NULL == arr)
{
return NULL;
}
arr->ptr = malloc(sizeof(TYPE)*len);
if(NULL == arr->ptr)
{
return NULL;
}
arr->len = len;
arr->i = 0;
return arr;
}
//销毁
void destory_array(Array *arr)
{
if(NULL != arr)
{
if(NULL != arr->ptr)
{
free(arr->ptr);
}
arr->len = 0;
arr->i = 0;
free(arr);
}
}
//添加元素
bool add_array(Array *arr,TYPE val)
{
if(NULL == arr||arr->i > arr->len)
{
return false;
}
arr->ptr[arr->i++] = val;
return true;
}
//删除指定位置元素
bool delete_array(Array *arr,int index)
{
if(NULL == arr||index > arr->i)
{
return false;
}
if(index <= arr->i)
{
for(size_t i = index;i<arr->i;i++)
{
arr->ptr[i] = arr->ptr[i+1];
}
}
arr->i--;
return true;
}
//从指定位置插入元素
bool insert_array(Array *arr,int index,TYPE val)
{
if(NULL == arr || index > arr->len || arr->i > arr->len)
{
return false;
}
if(index <= arr->i)
{
for(size_t i = arr->len;i > index;i--)
{
arr->ptr[i] = arr->ptr[i-1];
}
}
arr->ptr[index] = val;
arr->i++;
return true;
}
//根据值查找返回元素的下标
int find_array(Array *arr,TYPE val)
{
if(NULL == arr)
{
return -1;
}
for(size_t i = 0;i<arr->i;i++)
{
if(val == arr->ptr[i]);
{
return i;
}
}
return -1;
}
//访问元素
TYPE at_array(Array *arr,int index)
{
if(NULL == arr || index > arr->i)
{
return (TYPE)NULL;
}
return arr->ptr[index];
}
//排序
void sort_array(Array *arr)
{
if(NULL == arr)
{
return;
}
//写一个冒泡
for(size_t i = 0;i<arr->i;i++)
{
for(size_t j = i;j<arr->i;j++)
{
if(arr->ptr[i] > arr->ptr[j])
{
TYPE temp = arr->ptr[i];
arr->ptr[i] = arr->ptr[j];
arr->ptr[j] = temp;
}
}
}
}
//遍历
void show_array(Array *arr)
{
if(NULL == arr)
{
return;
}
for(size_t i = 0;i<arr->i;i++)
{
printf("%d ",arr->ptr[i]);
}
printf("\n");
}
功能受限的表
栈:
特点:只有一个数据的进出口,数据先进后出|后进先出。
操作:入栈(压栈),出栈(弹栈),栈空,栈满
栈的多种实现方式:
硬堆栈:由CPU或某些硬件上的寄存器来做存储空间,实现的栈结构,这种栈的速度快,但容量有限。
软堆栈:这种栈主要是在内存中实现,这种栈分为静态(顺序栈)和动态栈(链式栈)两种。
栈的应用:
栈是程序设计中很常用的数据结构。
1.表达式解析:
200*(100+10);
2.函数的调用和递归的实现。
#define TYPE int
//设置栈结构
typedef struct StackArray
{
TYPE *ptr;
int len;
int top;
}StackArray;
//创建栈
StackArray *creat_stack_arr(int len);
//销毁栈
void destory_stack_arr(StackArray *stack);
//入栈
bool push_stack_arr(StackArray *stack,TYPE val);
//出栈
bool pop_stack_arr(StackArray *stack);
//察看栈顶元素
TYPE top_stack_arr(StackArray *stack);
//栈空
bool empty_stack_arr(StackArray *stack);
//栈满
bool full_stack_arr(StackArray *stack);
程序实现
StackArray *creat_stack_arr(int len)
{
StackArray *stack = malloc(sizeof(StackArray));
stack->ptr = malloc(sizeof(TYPE)*len);
stack->len = len;
stack->top = 0;
return stack;
}
void destory_stack_arr(StackArray *stack)
{
free(stack->ptr);
free(stack);
}
bool push_stack_arr(StackArray *stack,TYPE val)
{
if(stack->top >= stack->len)
{
return false;
}
stack->ptr[stack->top++] = val;
return true;
}
bool pop_stack_arr(StackArray *stack)
{
if(stack->top == 0)
{
return false;
}
stack->top--;
return true;
}
TYPE top_stack_arr(StackArray *stack)
{
return stack->ptr[stack->top-1];
}
bool empty_stack_arr(StackArray *stack)
{
return stack->top == 0;
}
bool full_stack_arr(StackArray *stack)
{
return stack->top >= stack->len;
}
队列:
特点:有两个端口进行数据的进出操作,一个口只能进数据,一个口只能出数据,先进先出。
操作:入队,出队,队空,队满。
队列的应用:
1.可靠信号的排队处理。(排队等着)
2.数据通信。(聊天的顺序,消息队列)
typedef int TYPE;
//设置队列结构
typedef struct QueueArray
{
TYPE *ptr;
int len; //队列的容量
int head; //队头位置
int tail; //队尾
int cnt; //队列元素的数量
}QueueArray;
//创建队列
QueueArray *creat_queue_arr(int len);
//销毁队列
void destory_queue_arr(QueueArray *queue);
//入队
bool push_queue_arr(QueueArray *queue,TYPE val);
//出队
bool pop_queue_arr(QueueArray* queue);
//队空
bool empty_queue_arr(QueueArray *queue);
//队满
bool full_queue_arr(QueueArray *queue);
//查看队头
TYPE head_queue_arr(QueueArray *queue);
实现
QueueArray *creat_queue_arr(int len)
{
QueueArray *queue = malloc(sizeof(QueueArray));
queue->ptr = malloc(sizeof(TYPE)*len);
queue->len = len;
queue->head = 0;
queue->tail = 0;
queue->cnt = 0;
return queue;
}
void destory_queue_arr(QueueArray *queue)
{
free(queue->ptr);
free(queue);
}
bool push_queue_arr(QueueArray *queue,TYPE val)
{
if(full_queue_arr(queue))
{
return false;
}
queue->ptr[queue->tail++] = val;
queue->tail %= queue->len;
queue->cnt++;
return true;
}
bool pop_queue_arr(QueueArray* queue)
{
if(empty_queue_arr(queue))
{
return false;
}
queue->head = (queue->head+1)%queue->len;
queue->cnt--;
return true;
}
bool empty_queue_arr(QueueArray *queue)
{
return !queue->cnt;
}
bool full_queue_arr(QueueArray *queue)
{
return queue->cnt == queue->len;
}
TYPE head_queue_arr(QueueArray *queue)
{
if(empty_queue_arr(queue))
{
return -1;
}
return queue->ptr[queue->head];
}
接下来呢,是链式表的一些学习笔记,打开这个链接可以看到
https://blog.youkuaiyun.com/qq_41915225/article/details/88364684