思维导图如下
一、数据结构核心名称解释
1.逻辑结构:数据的逻辑结构是指数据元素之间的逻辑关系描述。根据数据元素之间的关系的不同特性,通常有四种基本逻辑结构:
a.集合结构:结构中的数据元素之间除了同属于一个集合的关系外,无任何其他关系。
b.线性结构:结构中的数据元素之间存在着一对一的线性关系。
c.树状结构:结构中数据元素之间存在着一对多的层次关系。
d.图状结构或网状结构:结构中的数据元素之间存在着多对多的任意关系。
1.1逻辑结构分为:
a.线性结构---线性表、栈、队、字符串、数组、广义表
b.非线性结构--数、图
2存储结构:(又称物理结构)是逻辑结构在计算机中的存储映像,包括数据元素映像和关系印映像,它是逻辑结构在计算机
二、逻辑结构和物理结构的区别
逻辑结构:实体数据元素间逻辑关系即实体性质理解基础进行抽象模型
物理结构:数据元素计算机存储即计算机数据理解逻辑结构计算机语言映射
三、算法设计要求
1.算法的正确性。
2.可读性。
3.健壮性。
4.高效性和低存储量。
四、算法效率衡量方法
1.时间复杂度:为了便于比较解决同一个问题的不同算法,通常以算法中击败操作重复执行的频度作为度量标准;常见的时间复杂度如下图:
2空间复杂度:算法空间复杂度的计算公式记作(Space Complexity):S(n) = O(f(n)),其中n是问题规模,f(n)为语句关于n所占存储空间的函数。
如当一个算法的空间复杂度为一个常量,即不随被处理数据量n的大小而改变时,可表示为O(1);当一个算法的空间复杂度与以2为底的n的对数成正比时,可表示为0(10g2n);当一个算法的空I司复杂度与n成线性比例关系时,可表示为0(n)。
3.算法的性能选择:
a.诺该程序适用次数较少,则力求算法精明易懂。
b.对于反复使用的程序,应尽可能使用快速的算法。
c.诺待解决的问题数据量极大,计算机的存储空间较小,则相应算法主要考虑如何节省空间。
八、线性表--关于顺序存储的实现(增删改查)
1.结构体的创建
typedef struct {
ElemType*data;
intlength;
}Sqlist;
2.顺序表初始化
StatusInitList(Sqlist*L){
//为顺序表分配一个大小为MAXSIZE 的数组空间
L->data= malloc(sizeof(ElemType) *MAXSIZE);
//存储分配失败退出
if(!L->data)exit(ERROR);
//空表长度为0
L->length=0;
return OK;
}
3.顺序表的插入
/*
初始条件:顺序线性表L已存在,1≤i≤ListLength(L);
操作结果:在L中第i个位置之前插入新的数据元素e,L的长度加1
*/
StatusListInsert(Sqlist*L,inti,ElemTypee){
//i值不合法判断
if((i<1) || (i>L->length+1))returnERROR;
//存储空间已满
if(L->length==MAXSIZE)returnERROR;
//插入数据不在表尾,则先移动出空余位置
if(i <= L->length){
for(intj = L->length-1; j>=i-1;j--){
//插入位置以及之后的位置后移动1位
L->data[j+1] = L->data[j];
}
}
//将新元素e 放入第i个位置上
L->data[i-1] = e;
//长度+1;
++L->length;
return OK;
}
4. 顺序表的取值
StatusGetElem(SqlistL,inti,ElemType*e){
//判断i值是否合理, 若不合理,返回ERROR
if(i<1|| i > L.length)return ERROR;
//data[i-1]单元存储第i个数据元素.
*e = L.data[i-1];
return OK;
}
5.顺序表的删除
/*
初始条件:顺序线性表L已存在,1≤i≤ListLength(L)
操作结果: 删除L的第i个数据元素,L的长度减1
*/
StatusListDelete(Sqlist*L,inti){
//线性表为空
if(L->length==0)returnERROR;
//i值不合法判断
if((i<1) || (i>L->length+1))returnERROR;
for(intj = i; j < L->length;j++){
//被删除元素之后的元素向前移动
L->data[j-1] = L->data[j];
}
//表长度-1;
L->length--;
return OK;
}
6. 清空顺序表
/* 初始条件:顺序线性表L已存在。操作结果:将L重置为空表 */
StatusClearList(Sqlist*L)
{
L->length=0;
return OK;
}
7. 判断顺序表清空
/* 初始条件:顺序线性表L已存在。操作结果:若L为空表,则返回TRUE,否则返回FALSE */
StatusListEmpty(SqlistL)
{
if(L.length==0)
return TRUE;
else
return FALSE;
}
8. 获取顺序表长度ListEmpty元素个数 */
intListLength(SqlistL)
{
returnL.length;
}
//1.8 顺序输出List
/* 初始条件:顺序线性表L已存在 */
/* 操作结果:依次对L的每个数据元素输出 */
StatusTraverseList(SqlistL)
{
inti;
for(i=0;i
printf("%d\n",L.data[i]);
printf("\n");
return OK;
}
9. 顺序表查找元素并返回位置
/* 初始条件:顺序线性表L已存在 */
/* 操作结果:返回L中第1个与e满足关系的数据元素的位序。 */
/* 若这样的数据元素不存在,则返回值为0 */
intLocateElem(SqlistL,ElemTypee)
{
inti;
if(L.length==0)return0;
for(i=0;i
{
if(L.data[i]==e)
break;
}
if(i>=L.length)return0;
returni+1;
}
九、线性表==关于链式(单链表)存储的设计(增删改查与头插法/尾插法)
//定义结点
typedef struct Node{
ElemTypedata;
structNode*next;
}Node;
typedefstructNode* LinkList;
//2.1 初始化单链表线性表
StatusInitList(LinkList*L){
//产生头结点,并使用L指向此头结点
*L = (LinkList)malloc(sizeof(Node));
//存储空间分配失败
if(*L ==NULL)returnERROR;
//将头结点的指针域置空
(*L)->next=NULL;
return OK;
}
//2.2 单链表插入
/*
初始条件:顺序线性表L已存在,1≤i≤ListLength(L);
操作结果:在L中第i个位置之后插入新的数据元素e,L的长度加1;
*/
StatusListInsert(LinkList*L,inti,ElemTypee){
intj;
LinkListp,s;
p = *L;
j =1;
//寻找第i-1个结点
while(p && j
p = p->next;
++j;
}
//第i个元素不存在
if(!p || j>i)returnERROR;
//生成新结点s
s = (LinkList)malloc(sizeof(Node));
//将e赋值给s的数值域
s->data= e;
//将p的后继结点赋值给s的后继
s->next= p->next;
//将s赋值给p的后继
p->next= s;
return OK;
}
//2.3 单链表取值
/*
初始条件: 顺序线性表L已存在,1≤i≤ListLength(L);
操作结果:用e返回L中第i个数据元素的值
*/
Status GetElem(LinkList L,int i,ElemType *e){
//j: 计数.
intj;
//声明结点p;
LinkList p;
//将结点p 指向链表L的第一个结点;
p = L->next;
//j计算=1;
j =1;
//p不为空,且计算j不等于i,则循环继续
while(p && j
//p指向下一个结点
p = p->next;
++j;
}
//如果p为空或者j>i,则返回error
if(!p || j > i)returnERROR;
//e = p所指的结点的data
*e = p->data;
return OK;
}
//2.4 单链表删除元素
/*
初始条件:顺序线性表L已存在,1≤i≤ListLength(L)
操作结果:删除L的第i个数据元素,并用e返回其值,L的长度减1
*/
StatusListDelete(LinkList*L,inti,ElemType*e){
intj;
LinkListp,q;
p = (*L)->next;
j =1;
//查找第i-1个结点,p指向该结点
while(p->next&& j<(i-1)) {
p = p->next;
++j;
}
//当i>n 或者 i<1 时,删除位置不合理
if(!(p->next) || (j>i-1))return ERROR;
//q指向要删除的结点
q = p->next;
//将q的后继赋值给p的后继
p->next= q->next;
//将q结点中的数据给e
*e = q->data;
//让系统回收此结点,释放内存;
free(q);
return OK;
}
/* 初始条件:顺序线性表L已存在 */
/* 操作结果:依次对L的每个数据元素输出 */
StatusListTraverse(LinkListL)
{
LinkList p=L->next;
while(p)
{
printf("%d\n",p->data);
p=p->next;
}
printf("\n");
return OK;
}
/* 初始条件:顺序线性表L已存在。操作结果:将L重置为空表 */
StatusClearList(LinkList*L)
{
LinkListp,q;
p=(*L)->next; /* p指向第一个结点 */
while(p) /* 没到表尾 */
{
q=p->next;
free(p);
p=q;
}
(*L)->next=NULL; /* 头结点指针域为空 */
return OK;
}
//3.1 单链表前插入法
/* 随机产生n个元素值,建立带表头结点的单链线性表L(前插法)*/
voidCreateListHead(LinkList*L,intn){
LinkList p;
//建立1个带头结点的单链表
*L = (LinkList)malloc(sizeof(Node));
(*L)->next=NULL;
//循环前插入随机数据
for(inti =0; i < n;i++)
{
//生成新结点
p = (LinkList)malloc(sizeof(Node));
//i赋值给新结点的data
p->data= i;
//p->next = 头结点的L->next
p->next= (*L)->next;
//将结点P插入到头结点之后;
(*L)->next= p;
}
}
//3.2 单链表后插入法
/* 随机产生n个元素值,建立带表头结点的单链线性表L(后插法)*/
voidCreateListTail(LinkList*L,intn){
LinkListp,r;
//建立1个带头结点的单链表
*L = (LinkList)malloc(sizeof(Node));
//r指向尾部的结点
r = *L;
for(inti=0; i
//生成新结点
p = (Node*)malloc(sizeof(Node));
p->data= i;
//将表尾终端结点的指针指向新结点
r->next= p;
//将当前的新结点定义为表尾终端结点
r = p;
}
//将尾指针的next = null
r->next=NULL;
}