一 课程体系
概念
顺序表,单链表,栈,队列
树
图
算法
查找算法,排序算法
二 为什么要学习数据结构
1.程序结构 = 数据结构 + 算法
数据结构是写代码非常重要的东西,也是一门基础课程
2.任何一门编程语言,数据结构都是非常重要的组成部分
比如c++里面的STL(标准模板库)
数据库的本质也是使用数据结构的内容编写的
数据结构中的图的遍历算法是人工智能的基础
红黑树在驱动中体现
3.我们之前已经学习了C基础部分,知道C语言中相对重要也是难度比较大的地方:数组,函数,指针,
结构体,数据结构这门课会天天使用这些东西,也算是对这个知识的深入理解。
三 数据结构的概念
3.1基本概念
数据结构:
数据:研究的对象
结构:数据之间的关系
数据结构主要学习的就是数据和数据之间的关系
在实际开发中,数据结构主要用于在搞清楚数据之间的关系之后在内存中临时存储数据。
3.2 数据结构的定义
数据结构主要研究的是数据的逻辑关系,存储关系以及操作
3.3 逻辑关系
逻辑关系就是指数据之间的逻辑关系,只要指的是邻接关系
逻辑关系在考虑数据之间的关系的时候会涉及直接前驱和直接后继的概念
线性关系:一对一的关系,任何一个数据只能有一个直接前驱和一个直接后继
例如:线性表,栈,队列
树形关系:一对多的关系,任何一个数据只能有一个直接前驱,但可以有多个直接后驱。
例如:树,二叉树
图形关系(网状关系3.4存储关系):多对多的关系,任何一个数据有多个直接前驱和多个直接后继
例如:图
3.4存储关系
存储主要指的是数据在内存中如何存储
顺序存储:
数据在内存中会开辟一块连续的内存空间,一般使用数组来存储数据
链式存储:
数据在内存中不需要开辟一段连续的内存空间
索引存储(一般不用)
哈希存储(一般不用)
注意:理论上任何一种逻辑结构都有两种最常用的存储方式
3.5 操作
增 删 改 查
四 顺序表(线性表的顺序存储)
4.1 概念
线性表:数据和数据之间是一对一的关系
顺序存储:需要在内存中开辟一段连续的内存空间存储数据,一般使用数组来存储数据。
为了方便对数组进行操作,通常会定义一个变量来保存最后一个元素的下标。
4.2 对顺序表的操作
4.2.1 创建一个空的顺序表
#include <stdio.h>
#include <stdlib.h>
//对数据的类型进行取别名,方便对表中的数据进行修改
//提高代码的拓展性
typedef int DataType;
#define N 32
typedef struct
{
DataType Data[N];
int pos;
}Seqlist;
//创建一个空的顺序表
Seqlist *SeqlistCreate();
int main(int *argc, char *argv[])
{
Seqlist *st = SeqlSeqlistInsert(st,100);
SeqlistInsert(st,200);
SeqlistInsert(st,300);
SeqlistInsert(st,400);
SeqlistInsert(st,500);
SeqlistInsert(st,600);
SeqlistInsert(st,700);
SeqlistInsert(st,800);istCreate();
return 0;
}
//创建一个空的顺序表
Seqlist *SeqlistCreate()
{
//在堆上申请空间
Seqlist *st = (Seqlist *)malloc(sizeof(Seqlist));
//由于返回值类型为void* 类型的,因此需要进行强制转换成SeqList* 类型的
//初始化,标识当前顺序表没有元素
st->pos = -1;
//最后一个元素的下标为-1,代表为空,也就是无元素
return st;
}
4.2.2 判断顺序表是否为满
int SeqlistIsFull(Seqlist *st)
{
#if 0
if(st->pos == N - 1)
{
return 1;
}
else
{
return 0;
}
#endif
return st->pos == N - 1 ? 1 : 0;
}
4.2.3 插入数据
//插入数据(每调用一次插入一个数据)
void SeqlistInsert(Seqlist *st,DataType value)
{
//插入数据之前先判断当前顺序表是否为满
if(SeqlistIsFull(st) == 1)
{
printf("插入失败,顺序表为满!\n");
return ;
}
st->pos++;
//将数据插入到pos位置的地方
st->Data[st->pos] = value;
printf("插入成功!\n");
}
4.2.4 遍历顺序表
void SeqlistPrint(Seqlist *st)
{
int i;
for(i = 0 ; i <= st->pos;i++)
{
printf("%d ",st->Data[i]);
}
printf("\n");
}
4.2.5 判断顺序表是否为空
int SeqlistIsEmpty(Seqlist *st)
{
return st->pos == -1 ? 1 : 0;
}
4.2.6 删除数据并返回删除的数据
DataType SeqlistDelete(Seqlist *st)
{
if(SeqlistIsEmpty(st) == 1)
{
printf("删除失败,顺序表为空!\n");
return (DataType)-1;
}
DataType value = st->Data[st->pos];
st->pos--;
printf("删除成功\n");
return value;
}
4.2.7 按位置插入数据
void SeqListInsertByPos(Seqlist *st,int p,DataType value)
{
//判断顺序表是否为满
if(1 == SeqlistIsFull(st))
{
printf("插入失败,数据已满了!\n");
return;
}
//判断插入数据的位置是否合适
if(p < 0 || p > st->pos + 1)
{
printf("插入失败,插入的位置有误!\n");
return ;
}
int i;
//如果插入的数据的位置刚好是POS+1,则直接写插入即可
if(p == st->pos + 1)
{
st->Data[p] = value;
st->pos++;
}
else
{
for(i = st->pos; i >= p;i--)
{
st->Data[i + 1] = st->Data[i];
}
st->Data[p] = value;
st->pos++;
}
printf("按照位置插入成功!\n");
}
4.2.8 按照位置删除数据,返回删除的数据
DataType SeqlistDeleteByPos(Seqlist *st,int p)
{
//判断顺序表是否为空
if(1 == SeqlistIsEmpty(st))
{
printf("删除失败,顺序表为空!\n");
return (DataType)-1;
}
//判断删除的位置是否合适
if(p < 0 || p > st->pos)
{
printf("删除失败,删除的位置有误!\n");
return (DataType)-1;
}
//将要删除的数据保存一下
DataType value = st->Data[p];
//将p往上的数据向下移动
int i;
for(i = p; i < st->pos;i++)
{
st->Data[i] = st->Data[i+1];
}
st->pos--;
printf("按照位置删除数据成功\n");
return value;
}
4.2.9 按照数据修改数据
void SeqlistUpdateData(Seqlist *st,DataType OldValue,DataType NewValue)
{
//循环对比每一个数据,如果找到将其修改成新的数据
int i,flags;
for(i = 0; i < st->pos;i++)
{
if(st->Data[i] == OldValue)
{
st->Data[i] = NewValue;
flags = 1;
}
}
if(flags == 0)
{
printf("修改 %d 数据失败,数据不存在\n",OldValue);
}
else
{
printf("修改数据成功,将 %d修改成 %d\n",OldValue,NewValue);
}
}
4.2.10 按照位置修改数据
void SeqlistUpdateByPos(Seqlist *st,int p,DataType NewValue)
{
//判断位置是否合法
if(p < 0 || p > st->pos)
{
printf("修改失败,位置有误!\n");
return;
}
st->Data[p] = NewValue;
}
4.2.11 按照数据查找位置
int SeqlistSearchPosByDate(Seqlist *st,DataType value)
{
int i;
for(i = 0 ; i < st->pos;i++)
{
if(st->Data[i] == value)
{
printf("按照数据查找位置成功!\n");
return i;
}
}
printf("查找失败,数据 %d 不存在\n",value);
return -1;
}
4.2.12 按照位置查找数据
DataType SeqlistSearchDataByPos(Seqlist *st,int p)
{
//判断位置是否合法
if(p < 0 || p > st->pos)
{
printf("修改失败,位置有误\n");
return (DataType)-1;
}
printf("按照位置查找数据成功\n");
return st->Data[p];
}
五.整体代码
#include <stdio.h>
#include <stdlib.h>
//对数据的类型进行取别名,方便对表中的数据进行修改
//提高代码的拓展性
typedef int DataType;
#define N 32
typedef struct
{
DataType Data[N];
int pos;
}Seqlist;
//创建一个空的顺序表
Seqlist *SeqlistCreate();
//判断顺序表是否为满
int SeqlistIsFull(Seqlist *st);
//插入数据(每调用一次插入一个数据)
void SeqlistInsert(Seqlist *st,DataType value);
//遍历顺序表
void SeqlistPrint(Seqlist *st);
//判断顺序表是否为空
int SeqlistIsEmpty(Seqlist *st);
//删除数据并返回删除的数据
DataType SeqlistDelete(Seqlist *st);
//按位置插入数据
void SeqListInsertByPos(Seqlist *st,int p,DataType value);
//按照位置删除数据,返回删除的数据
DataType SeqlistDeleteByPos(Seqlist *st,int p);
//按照数据修改数据
void SeqlistUpdateData(Seqlist *st,DataType OldValue,DataType NewValue);
//按照位置修改数据
void SeqlistUpdateByPos(Seqlist *st,int p,DataType NewValue);
//按照数据查找位置
int SeqlistSearchPosByDate(Seqlist *st,DataType value);
//按照位置查找数据
DataType SeqlistSearchDataByPos(Seqlist *st,int p);
int main(int *argc, char *argv[])
{
Seqlist *st = SeqlistCreate();
SeqlistInsert(st,100);
SeqlistInsert(st,200);
SeqlistInsert(st,300);
SeqlistInsert(st,400);
SeqlistInsert(st,500);
SeqlistInsert(st,600);
SeqlistInsert(st,700);
SeqlistInsert(st,800);
SeqlistPrint(st);
SeqListInsertByPos(st,2,666);
SeqlistPrint(st);
SeqlistUpdateData(st,100,777);
SeqlistPrint(st);
SeqlistUpdateByPos(st,7,888);
SeqlistPrint(st);
int pos;//记录顺序链表最后一个节点的位置(队列的大小)
pos = SeqlistSearchPosByDate(st,400);
DataType data;
data = SeqlistSearchDataByPos(st,3);
if(data == -1)
{
printf("按照位置查找数据失败\n");
}
else
{
printf("按照位置查找数据成功,数据为%d\n",data);
}
SeqlistDeleteByPos(st,3);
SeqlistPrint(st);
SeqlistDelete(st);
SeqlistPrint(st);
SeqlistDelete(st);
SeqlistDelete(st);
return 0;
}
//创建一个空的顺序表
Seqlist *SeqlistCreate()
{
//在堆上申请空间
Seqlist *st = (Seqlist *)malloc(sizeof(Seqlist));
//由于返回值类型为void* 类型的,因此需要进行强制转换成SeqList* 类型的
//初始化,标识当前顺序表没有元素
st->pos = -1;
//最后一个元素的下标为-1,代表为空,也就是无元素
return st;
}
//判断顺序表是否为满
int SeqlistIsFull(Seqlist *st)
{
#if 0
if(st->pos == N - 1)
{
return 1;
}
else
{
return 0;
}
#endif
return st->pos == N - 1 ? 1 : 0;
}
//插入数据(每调用一次插入一个数据)
void SeqlistInsert(Seqlist *st,DataType value)
{
//插入数据之前先判断当前顺序表是否为满
if(SeqlistIsFull(st) == 1)
{
printf("插入失败,顺序表为满!\n");
return ;
}
st->pos++;
//将数据插入到pos位置的地方
st->Data[st->pos] = value;
printf("插入成功!\n");
}
//遍历顺序表
void SeqlistPrint(Seqlist *st)
{
int i;
for(i = 0 ; i <= st->pos;i++)
{
printf("%d ",st->Data[i]);
}
printf("\n");
}
//判断顺序表是否为空
int SeqlistIsEmpty(Seqlist *st)
{
return st->pos == -1 ? 1 : 0;
}
//删除数据并返回删除的数据
DataType SeqlistDelete(Seqlist *st)
{
if(SeqlistIsEmpty(st) == 1)
{
printf("删除失败,顺序表为空!\n");
return (DataType)-1;
}
DataType value = st->Data[st->pos];
st->pos--;
printf("删除成功\n");
return value;
}
//按位置插入数据
void SeqListInsertByPos(Seqlist *st,int p,DataType value)
{
//判断顺序表是否为满
if(1 == SeqlistIsFull(st))
{
printf("插入失败,数据已满了!\n");
return;
}
//判断插入数据的位置是否合适
if(p < 0 || p > st->pos + 1)
{
printf("插入失败,插入的位置有误!\n");
return ;
}
int i;
//如果插入的数据的位置刚好是POS+1,则直接写插入即可
if(p == st->pos + 1)
{
st->Data[p] = value;
st->pos++;
}
else
{
for(i = st->pos; i >= p;i--)
{
st->Data[i + 1] = st->Data[i];
}
st->Data[p] = value;
st->pos++;
}
printf("按照位置插入成功!\n");
}
//按照位置删除数据,返回删除的数据
DataType SeqlistDeleteByPos(Seqlist *st,int p)
{
//判断顺序表是否为空
if(1 == SeqlistIsEmpty(st))
{
printf("删除失败,顺序表为空!\n");
return (DataType)-1;
}
//判断删除的位置是否合适
if(p < 0 || p > st->pos)
{
printf("删除失败,删除的位置有误!\n");
return (DataType)-1;
}
//将要删除的数据保存一下
DataType value = st->Data[p];
//将p往上的数据向下移动
int i;
for(i = p; i < st->pos;i++)
{
st->Data[i] = st->Data[i+1];
}
st->pos--;
printf("按照位置删除数据成功\n");
return value;
}
//按照数据修改数据
void SeqlistUpdateData(Seqlist *st,DataType OldValue,DataType NewValue)
{
//循环对比每一个数据,如果找到将其修改成新的数据
int i,flags;
for(i = 0; i < st->pos;i++)
{
if(st->Data[i] == OldValue)
{
st->Data[i] = NewValue;
flags = 1;
}
}
if(flags == 0)
{
printf("修改 %d 数据失败,数据不存在\n",OldValue);
}
else
{
printf("修改数据成功,将 %d修改成 %d\n",OldValue,NewValue);
}
}
//按照位置修改数据
void SeqlistUpdateByPos(Seqlist *st,int p,DataType NewValue)
{
//判断位置是否合法
if(p < 0 || p > st->pos)
{
printf("修改失败,位置有误!\n");
return;
}
st->Data[p] = NewValue;
}
//按照数据查找位置
int SeqlistSearchPosByDate(Seqlist *st,DataType value)
{
int i;
for(i = 0 ; i < st->pos;i++)
{
if(st->Data[i] == value)
{
printf("按照数据查找位置成功!\n");
return i;
}
}
printf("查找失败,数据 %d 不存在\n",value);
return -1;
}
//按照位置查找数据
DataType SeqlistSearchDataByPos(Seqlist *st,int p)
{
//判断位置是否合法
if(p < 0 || p > st->pos)
{
printf("修改失败,位置有误\n");
return (DataType)-1;
}
printf("按照位置查找数据成功\n");
return st->Data[p];
}