/*
第一章 数据结构绪论
数据结构是一种或多种特定关系的数据元素的集合
实时排队系统:队列结构
数据:是描述客观事务的符号,是计算机可以操作的对象.
数据项: 一个数据元素可以由若干个数据项组成.不可分割的最小单位.
结构: 简单理解就是关系.逻辑结构,物理结构.
逻辑结构: 集合 线性结构 树形结构 图形结构
物理结构: 逻辑结构在计算机中的存储形式. 顺序结构 链式结构
(存储单元不连续)
逻辑结构是面向问题的,而物理结构是面向计算机的.其基本的目标是将数据及其逻辑关系存储在计算机的内存中.
ADT 抽象数据类型名
Data
数据元素之间的逻辑关系的定义
operation
操作1
初始化
操作结果描述
操作2
...
操作n
...
endADT
第二章 算法
解决特定问题的步骤描述 在计算机中表现为指令的有限序列,并且每条指令标识一个或多个操作 特性: 输入输出 有穷性 确定性 和可行性
时间效率高 和存储量低
算法效率的度量方法:
事后统计法,利用计算机计时器对不同算法编制的程序的运行时间进行比较
事前分析估算法: 依据统计方法对算法进行估算
int i, sum = 0, n=100; 执行1次
for(i = 1; i <= n; i++) 执行n+1次
{
sum = sum + i; 执行1次
}
printf("%d",sum); 执行1次
int sum =0, n=100; 执行1次
sum = (1 + n)*n/2; 执行1次
printf("%d\n",sum); 执行1次
操作数量是f(n)=n;
算法的事件复杂度:语句执行的总次数T(n) 是关于问题规模的函数
进而分析T(n)随n的变化情况并确定T(n)的数量.算法的事件度量
T(n)=O(f(n)).f(n)是问题规模n的某个函数.
常熟阶:
顺序结构事件复杂度:O(1);执行次数恒定,不会随着n的变大而变化
线性阶:
循环的时间复杂度为O(n)因为循环体中的代码必须执行n次
对数阶:
O(logn):
平方阶:
嵌套循环的时间复杂度,O(n^2);
算法的时间复杂度看得不是太懂.
第三章 线性表
线性表(List):零个或对个数据元素的有序集合
线性表的抽象数据类型:
ADT 线性表(Lsit)
DATA
数据对象集合{a1,a2,a3,a4,a5....an},每个元素的类型均为
DataType,数据元素之间的关系时一一对应.
operation:
InitList(*L)
ListEmpty(L)
clearList(*L)
GetList(L,i,*e)
LocateElem(L,e)
ListInsert(*L,i,e)
ListDelete(*L,i,*e)
List Length(L)
A=A并B
void union(List *La,List* Lb)
{
int La_len,Lb_len,i;
ElemType e;
La_len = ListLength(La);
Lb_len = ListLength(Lb);
for(i=1;i<=Lb_len;i++)
{
GetElem(Lb,i,e);
if(!Locate(La,e,equal))
ListInsert(La,++La_len,e);
}
}
线性变的顺序存储结构:把一定内存给占了,然后相同数据元素依次放入
线性表的顺序存储结构:
#defienf MAXSIZE 20
typedef int ElemType;
typedef struct
{
ElemType data[MAXSIZE];
int length;
}Sqlist;
三个属性:
1 存储空间的起始位置: 数组data;
2 线性表的最大存储容量: 数组长度 Maxsize
(存储线性表的存储空间的长度)
3 线性表的当前长度:length
(数据元素的个数)
每个元素占c个存储单元,那么线性表中第i+1个数据元素的存储位置和第i个元素的存储位置的关系.
LOC(a(i+1)) = LOC(a(i))+c
LOC(a(i)) = LOC(a(1))+(i-1)*c
顺序存储结构的插入与删除
1 获得元素
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
typedef int Status;
Status 是函数类型,其值为函数结果状态代码
e返回L中i位置元素的值
Status GetElem(Sqlist L,int i,ElemType *e)
{
if(L.length ==0 || i<1||i>L.length)
return ERROR;
*e = L.data[i-1];
* return OK;
}
插入算法的思路:
1 如果插入位置不合理,抛出异常
2 如果线性表的长度等于数组长度,则抛出异常和动态增加容量;
3 从总后一个元素向前遍历到第i个位置,分别将他们都向后移动一个位置
4 将要插入的元素填入位置i处
Status ListInsert(SqList *L,int i,ElemType e)
{
int k;
if(L->length == MAXSIZE)
return ERROR;
if(i<1||i>L-length+1)
return ERROR;
if(i<=L->length) //中间插入
{
for(k=L->length-1;k>=i-1;k--)
L->data[k+1] = L->data[k];
}
L->data[i-1]=e; //尾部插入
L->length++;
return OK;
}
删除算法思路:
1 如果位置不合理 抛出异常
2 取出元素
3从删除元素开始遍历到最后一个元素,分别将他们都想前移动一个位置
4 表长减1
Status ListDelete(Sqlit *L, int i, ElemType *e)
{
int k;
if(L->length ==0)
return ERROR;
if(i<1||i>L->length)
return ERROR;
*e = L->data[i-1];
if(i<L->length)
{
for(k=i;k<L->length;k++)
L->data[k-1]=L->data[k]
}
L->length--;
return OK;
}
时间复杂度:
1 最后一个元素 O(1)
2 最坏情况O(n)
优点: 无需为表示元素的逻辑关系而增加额外的空间 可以快速存储表中的人以位置元素
缺点: 难以确保存储空间的容量 插入删除需要移动大量元素,造成存储空间"碎片"
线性表的链式存储: 数据域和指针域
头指针指向链表的第一个节点的指针.无论链表是否为空,头指针均不为空.
头节点放在头一个元素之前.
单链表的存储结构:
typedef struct Node
{
ElemType data;
struct Node* next;
}Node;
typedef struct Node* Linklist;
获得链表的第i个数据的算法:
1 声明一个p指针指向链表的第一个节点 初始化j从1开始
2 当j<i时遍历链表,让p的指针向后移动 不断指向下一个节点,j累加
3 若p为空,则元素不存在
4 查找成功 返回节点p
Status GetElem(LinkList L,int i, elemtype *e)
{
int j=0;
Linklist p;
p = L->next;//带有头节点的链表
j=1;
while(p&&j<i)
{
p = p->next;
++j;
}
if(!p || j>i)
return ERROR;
*e = p->data;
* reutrn OK;
}
链表的插入:
代码实现
Status ListInsert(Linklist *L,int i;ElemType)
{
int j;
Linklist p,s;
p = *L;
j= 1;
while(p&&j<i) //查找第i个节点
{
p=p->next;
j++;
}
if (!p|| j>i)
reutrn ERROR;
s = (Linklist)malloc(sizeof(Node));
assert(s);
s->data = e;
s->next = p->next;
p->next = s;
return OK;
}
链表的删除:(这里参数1 ,3 是结构参数,传的是指针)
Status Listdelete(Linklist *L,int i,ElemType *e)
{
int j=1;
Linklist p,q;
p=*L;
while(p->next&&j<i)
{
p=p->next;
j++;
}
if(!(p->next)||j>i)
return ERROR;
q=p->next; //保存要删除的节点
p->net = q->next;
*e = q->data;
free(q);
q=NULL;
return OK;
}
时间复杂度: 插入删除都是O(1);查找O(n);
man{ Linklist L=NULL; CreateList(&L);}
创建链表: (参数1 是一个二阶指针)
void CreateListHead(Linklsit *L,int n)
{
ListList p;
int i;
srand(time(0));
*L = (LinkList)malloc(sizeof(Node))
(*L)->next = NULL;
for(i=0;i<n;i++) //头插法
{
p=(Linklist)malloc(sizeof(Node));
p->data = rand()%100+1;
p->next = (*L)->next;
(*L)->next = p;
}
linklist r=*L;
for(i=0;i<n;i++)
{
p=(Linklist)malloc(sizeof(Node));
p->data = rand()%100+1; //
r->next = p;
r =p;
}
r->next =NULL;
}
Status ClearList(Linklist *L)
{
Linklist p,q;
p=(*L)->next;
while(p)
{
q=p->next;
free(p)
p=q;
}
(*L)->next = NULL;
retrun OK;
}
顺序结构用一段连续的存储单元 单链表采用任意存储单元
顺序结构需要预分配空间 单链表需要时分配
查找 顺序结构O(1) 单链表 O(n)
插入删除 顺序结构O(n) 单链表O(1)
静态链表
用数组描述的链表叫做静态链表
#define MAXSIZE 1000
typedef struct
{
Elemtype data;
int cur; //游标,为0 时无指向
}Component,StaticLinkList[MAXSIZE];
Status InitList(StaticLinkList space)
{
int i=0;
for(i=0;i<MAXSIZE; i++)
space[i].cur = i+1; //初始化游标
space[MAXSIZE].cur = 0; 最后一个元素的cur为0
return OK;
}
int Malloc_SLL(StaticLinkList space)
{
int i=space[0].cur; 1 //当前数组第一个元素的cur
if(space[0].cur)
space[0].cur = space[i].cur;
return i;
}
status ListInsert(StatusLinkList L,int i,ElemType e)
{
int j,k,l;
k = MAX_SIZE-1;
if(i<1||i>ListLength(L)+1)
retrun ERROR;
j = Malloc_SSL(L);
if(j)
{
L[j].data = e;
for(l=1;l<=i-1;l++)
k = L[k].cur;
L[j].cur = L[k].cur;
L[k].cur = j;
reuturn OK;
}
return ERROR;
}
静态链表看不懂
......
循环链表:
头节点: 尾节点rearA->next;
合并链表: 保存头节点 p=rear->next;
rearA->next = rearB->next->next;
rearB->next = p;
free(p); //感觉这里有问题 应该释放rearB的头节点
双向链表:
typedef struct DulNode
{
ElemType data;
struct DulNode *prior;
struct DulNode *next;
}DulNode,*DulNodeList;
p->next->prior = p =p->prior->next;
插入位置p后面 节点s ;
s->prior = p;
s->next=p->next;
p->next->prior = s;
p->next = s;
删除
p->prior->next = p->next;
p->next->prior = p->prior;
*/
原文:https://www.cnblogs.com/countryboy666/p/10923557.html