一、数据结构绪论
1.定义
相互之间存在一种或多种特定关系的数据元素的集合。
2.逻辑结构与物理结构
(1)逻辑结构
- 集合,所有数据在同一个集合中,关系平等。
- 线性,数据和数据之间是一对一的关系
- 树, 一对多
- 图,多对多
(2)物理结构(在内存当中的存储关系)
- 顺序存储,数据存放在连续的存储单位中。逻辑关系和物理关系一致
- 链式,数据存放的存储单位是随机或任意的,可以连续也可以不连续。
struct Per 数据元素
{
char name;//数据项
int age;
char phone;
}
struct Per list[100]; //数据对象
3.抽象数据类型
(1)数据的类型,ADT abstruct datatype 定义
是指一组性质相同的值的集合及定义在此集合上的一些操作的总称。
(2)分类
- 原子类型,int,char,float
- 结构类型,sturct, union
(3)抽象数据类型, 数学模型 + 操作。程序 = 数据 + 算法
二、算法
1.定义
算法是解决特定问题求解步骤的描述,计算机中表现为指令的有限序列,每条指令表示一个或多个
操作。
2.算法的特征
(1)输入,输出特性,输入时可选的,输出时必须的。
(2)有穷性,执行的步骤会自动结束,不能是死循环,并且每一步是在可以接受的时间内完成。
(3)确定性,同一个输入,会得到唯一的输出。
(4)可行性,每一个步骤都是可以实现的。
2.算法的设计
(1)正确性
1)语法正确
2)合法的输入能得到合理的结果
3)对非法的输入,给出满足要求的规格说明
4)对精心选择,甚至刁难的测试都能正常运行,结果正确
(2)可读性,便于交流,阅读,理解
(3)健壮性,输入非法数据,能进行相应的处理,而不是产生异常
(4)高效,存储低,效率高
3.算法时间复杂度
也就是执行这个算法所花时间的度量 n 1 = O(n) O(1)
O(1)<O(logn)<O(N)<O(nlogn)<O(n^2)<O(n^3)<O(2^n)<O(n!)<O(n^n)
eg: n =O(n); n^3 =O(n^3) ;
for() n
{
for() n
}
4.推导时间复杂度
(1)用常数1 取代运行时间中的所有加法常数
(2)在修改后的运行函数中,只保留最高阶项。
(3)如果最高阶存在且不是1,则取除这个项相乘的常数。
三、线性表
1.定义
零个或者多个数据元素的有限序列
2.特征
(1)元素之间是有顺序了。如果存在多个元素,第一个元素无前驱,最有一个没有后继,其他的
元素只有一个前驱和一个后继。
(2)当线性表元素的个数n(n>=0)定义为线性表的长度,当n=0时,为空表。在非空的表中每个
元素都有一个确定的位置,如果a1是第一个元素,那么an就是第n个元素。
3.线性表顺序存储的常规操作 ADT
typedef struct person {
char name[32];
char sex;
int age;
int score;
}DATATYPE;
typedef int Datatype;
typedef struct list {
DATATYPE *head;
int tlen;
int clen;
}SeqList;
SeqList *CreateSeqList(int len);//创建顺序表
int DestroySeqList(SeqList *list);//销毁数据链(整个)
int ShowSeqList(SeqList *list);//数组遍历b表
int InsertTailSeqList(SeqList *list, DATATYPE *data);//尾插,在顺序表的最后插入元素
int IsFullSeqList(SeqList *list);//判断是否满
int IsEmptySeqList(SeqList *list);//判断是否空
int InsertPosSeqList(SeqList *list, DATATYPE *data, int pos);//按指定位置插入元素
int FindSeqList(SeqList *list, char *name);//查找元素,根据名字
int ModifySeqList(SeqList *list, char *old, DATATYPE *newdata);//根据名字修改指定元素
int DeleteSeqList(SeqList *list, char *name);//根据名字删除指定元素
int ClearSeqList(SeqList *list);//清空表,清空表中已有元素(结构在,数据删除)
int GetSizeSeqList(SeqList *list);//获得表中有效元素个数
DATATYPE *GetItemSeqList(SeqList *list,int ind);//获得指定下标元素本身
注:内存泄露检测工具
sudo apt-get install valgrind
valgrind ./all
4.线性表顺序存储的优点,缺点
(1)优点
- 1,无需为表中的逻辑关系增加额外的存储空间
- 2,可以快速随机访问元素O(1)
(2)缺点
- 1,插入,删除元素需要移动元素o(n)
- 2,无法动态存储
5..手撕上述代码
(1)seqlist.c
#include "seqlist.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
SeqList *CreateSeqList(int len)
{
SeqList *sl = malloc(sizeof(SeqList));
if(NULL == sl)
{
fprintf(stderr,"CreateSeqList malloc error\n");
return NULL;
}
sl->head = malloc(sizeof(DATATYPE)*len);
if(NULL == sl->head)
{
fprintf(stderr,"CreateSeqList malloc2 error\n");
return NULL;
}
sl->tlen = len;
sl->clen = 0;
return sl;
}
int IsFullSeqList(SeqList *list)
{
if(NULL == list)
{
fprintf(stderr,"IsFullSeqList paramter error\n");
return 1;
}
return list->clen == list->tlen;
}
int InsertTailSeqList(SeqList *list, DATATYPE *data)
{
if(IsFullSeqList(list))
{
fprintf(stderr, "seqList full\n");
return 1;
}
memcpy(&list->head[list->clen],data,sizeof(DATATYPE));
//list->head[list->clen] = *data;
list->clen++;
return 0;
}
int ShowSeqList(SeqList *list)
{
int len = GetSizeSeqList(list);
int i = 0;
for(i = 0;i < len;++i)
{
printf("%s %c %d %d\n",list->head[i].name,list->head[i].sex,list->head[i].age,list->head[i].score);
}
return 0;
}
int GetSizeSeqList(SeqList *list)
{
return list->clen;
}
int IsEmptySeqList(SeqList *list)
{
return 0 == list->clen;//双等号常量放左边
}
int FindSeqList(SeqList *list, char *name)
{
int i = 0;
int len = GetSizeSeqList(list);
for(i = 0;i < len;++i)
{
if(0 == strcmp(list->head[i].name,name))
{
return i;
}
}
return -1;
}
DATATYPE *GetItemSeqList(SeqList *list,int ind)
{
if(NULL == list)
{
return NULL;
}
int len = GetSizeSeqList(list);
if(ind<0 || ind>len)
{
return NULL;
}
return &list->head[ind];
}
int InsertPosSeqList(SeqList *list, DATATYPE *data, int pos)
{
if(IsFullSeqList(list))
{
return 1;
}
int len = GetSizeSeqList(list);
if(pos < 0 || pos > len)
{
return 1;
}
int i = 0;
for(i = list->clen;i > pos;--i)
{
memcpy(&list->head[i],&list->head[i - 1],sizeof(DATATYPE));
}
memcpy(&list->head[pos],data,sizeof(DATATYPE));
list->clen++;
return 0;
}
int DeleteSeqList(SeqList *list, char *name)
{
if(IsEmptySeqList(list))
{
return 1;
}
int ret = FindSeqList(list, name);
if(-1 == ret)
{
return 1;
}
int i = 0;
int len = GetSizeSeqList(list);
for(i = ret;i < len - 1;++i)
{
memcpy(&list->head[i],&list->head[i + 1],sizeof(DATATYPE));
}
list->clen--;
return 0;
}
int ModifySeqList(SeqList *list, char *old, DATATYPE *newdata)
{
if(IsEmptySeqList(list))
{
return 1;
}
int ret = FindSeqList(list, old);
if(-1 == ret)
{
return 1;
}
memcpy(&list->head[ret],newdata,sizeof(DATATYPE));
return 0;
}
int ClearSeqList(SeqList *list)
{
list->clen = 0;
return 0;
}
int DestroySeqList(SeqList *list)
{
if(NULL == list)
{
return 1;
}
free(list->head);
free(list);
return 0;
}
(2)seqlist.h
#ifndef _SEQLIST_H_
#define _SEQLIST_H_
typedef struct person {
char name[32];
char sex;
int age;
int score;
}DATATYPE;
typedef int Datatype;
typedef struct list {
DATATYPE *head;
int tlen;
int clen;
}SeqList;
SeqList *CreateSeqList(int len);//创建顺序表
int DestroySeqList(SeqList *list);//销毁数据链(整个)
int ShowSeqList(SeqList *list);//数组遍历b表
int InsertTailSeqList(SeqList *list, DATATYPE *data);//尾插,在顺序表的最后插入元素
int IsFullSeqList(SeqList *list);//判断是否满
int IsEmptySeqList(SeqList *list);//判断是否空
int InsertPosSeqList(SeqList *list, DATATYPE *data, int pos);//按指定位置插入元素
int FindSeqList(SeqList *list, char *name);//查找元素,根据名字
int ModifySeqList(SeqList *list, char *old, DATATYPE *newdata);//根据名字修改指定元素
int DeleteSeqList(SeqList *list, char *name);//根据名字删除指定元素
int ClearSeqList(SeqList *list);//清空表,清空表中已有元素(结构在,数据删除)
int GetSizeSeqList(SeqList *list);//获得表中有效元素个数
DATATYPE *GetItemSeqList(SeqList *list,int ind);//获得指定下标元素本身
#endif
(3)main.c
#include "seqlist.h"
#include <stdio.h>
int main(int argc,char **argv)
{
SeqList*s1 = CreateSeqList(5);
DATATYPE data[] = {
{"zhang",'F',20,80},
{"lisi",'M',21,83},
{"wang",'F',22,83},
{"guanerge",'M',40,90},
{"liubei",'M',41,92},
};
InsertTailSeqList(s1, &data[0]);
InsertTailSeqList(s1, &data[1]);
InsertTailSeqList(s1, &data[2]);
ShowSeqList(s1);
//InsertPosSeqList(s1, &data[3],1);
DeleteSeqList(s1, "lisi");
printf("................\n");
ShowSeqList(s1);
// int ret = FindSeqList(sl, "lisi");
// if(-1 == ret)
// {
// printf("not find\n");
// }
// else
// {
// DATATYPE *tmp = GetItemSeqList(sl,ret);
// printf("%s %d\n",tmp->name,tmp->score);
// }
return 0;
}
注:head:数组名,是指针指向首元素地址;
tlen:总长度;
clen:当前长度,代表使用的有效长度;