1 时间复杂度
1-1 线性阶
1-2 对数阶
1-3 平方阶
常见时间复杂度表
2 线性表
2-1 线性表顺序存储结构
线性表的长度与数组长度区分
线性表的顺序存储的结构代码
#define MAXSIZE 20 //存储空间初始分配量
typedef int ElemType; // 暂定int
typedef struct
{
ElemType date[MAXSIZE]; //数组存储数据成员,最大值为MAXSIZE
int length; //线性表当前长度
}SqList;
用数组存储,那么存储器中的每个存储单元都是有编号的,这个编号称为地址
那么,对于每个线性表位置的存入与取出,对于计算机来说都是相同的时间。它的存储时间性能为O(1)。我们通常把具有这一特点的存储结构称为顺序存储结构。
3 顺序存储结构的插入与删除
3-1 获得元素操作 // wr
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
typedef int Status;
/* Status 是函数类型,其值是函数结果状态代码,如OK
初始条件:顺序线性表L存在,1<=i<=ListLength(L)
操作结果:用e返回L中第i个数据元素的值*/
Status GetElem(SqList L, int i, ElemType *e)//这个函数为什么我调用不起来
{
if (L.length == 0 || i<1 || i>L.length)
return ERROR;
*e = L.date[i - 1];
return OK;
}
Status ListInsert(SqList *L, int i, ElemType e)
{
int k;
if (L->length == MAXSIZE)//顺序线性表已满
return ERROR;
if (i<1 || i>L->length + 1)//当i不在范围内
return ERROR;
if (i <= L->length)
{
for (k = L->length; k >= i - 1; k--)//将要插入位置后数据元素向后移动一位
L->date[k + 1] = L->date[k];
}
L->date[i - 1] = e;
L->length++;
return OK;
}
3-3 删除操作
删除算法的思路
Status ListDelete(SqList *L, int i, ElemType *e)
{
int k;
if (L->length == 0) //表长为0
return ERROR;
if (i<1 || i>L->length ) // 删除位置不正确
{
return ERROR;
}
*e = L->date[i - 1];
if (i < L->length)//若删除的不是最后一个元素
{
for (k = i; k < L->length; k++)//删除位置后继元素前移
L->date[k - 1] = L->date[k];
}
L->length--;
return OK;
}
3-4 线性表的顺序存储结构的优缺点
4 线性表的链式存储结构
头结点:
注意看头结点和第一个结点,头结点不是第一个结点
4-1 头结点和第一个结点的区别
typedef struct Node
{
ElemType date;
struct Node *next;
}Node;
typedef struct Node *LinkList;//定义 LinkList
Status GetElem(LinkList L, int i, ElemType *e)
{
int j;
LinkList p; //声明一结点p
p = L->next;//让p指向链表L的第一个结点
j = 1; //j为计数器
while ( p && j<i)//p不为空,或计数器j还没有到i时,循环继续
{
p = p->next;
++j;
}
if (!p || j > i)
return ERROR;//第i个元素不存在
*e = p->date; //读取第i个元素
return OK;
}
4-4 单链表的插入与删除
插入:-------------------------------------
显然;
单链表第i个元素的插入操作算法思路
代码实现:
Status ListInsert(LinkList *L, int i, ElemType e)
{
int j;
LinkList p, s;
p = *L;
j = 1;
while (p&&j < i)
{
p = p->next;
++j;
}
if (!p || j > i)
return ERROR; //第i个元素不存在
s = (LinkList)malloc(sizeof(Node));//生成新结点(c标准函数)//加个头文件
s->date = e;
s->next = p->next; //基操勿6
p->next = s;
return OK;
}
删除:-------------------------------------
单链表第i个数据删除结点的算法思路
代码实现
Status ListDelete(LinkList *L, int i, ElemType *e)
{
int j;
LinkList p, q;
p = *L;
j = 1;
while (p->next && j < i)
{
p = p->next;
++j;
}
if (!(p->next) || j > i)
return ERROR; //第i个元素不存在
q = p->next;
p->next = q->next; //将q的后继赋值给p的后继
*e = q->date; //将q结点中的数据给e
free(q); //让系统回收此结点,释放内存
return OK;
}
4-5 单链表的整表创建 //wr
单链表整表创建的算法思路
声明一结点p和计数器变量i
初始化一空链表L
让L的头结点的指针指向NULL,即建立一个带头结点的单链表
循环
生产一新结点赋值给p
随机生成一数字赋值给p的数据域p->date
将p插入头结点和与前一新结点之间
代码实现
void CreateListHead(LinkList *L, int n)//头插法
{
LinkList 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->date = rand() % 100 + 1; //随机生成100以内的数字
p->next = (*L)->next;
(*L)->next = p; //插入到表头
}
}
void CreateListTail(LinkList *L, int n)
{
LinkList p, r;
int i;
srand(time(0));
*L = (LinkList)malloc(sizeof(Node));//为整个线性表??
r = *L; //r为指向尾部的结点
for (i = 0; i < n; i++)
{
p = (LinkList)malloc(sizeof(Node));//生成新结点
p->date = rand() % 100 + 1; //随机生成100以内的数字
r->next = p; //将表位终端结点的指针指向新结点
r = p; //将当前的新结点定义为表尾终端结点
}
r->next = NULL; //表示当前链表结束 /// 解释见图
}
Status ClearList(LinkList *L)
{
LinkList p, q;
p = (*L)->next; //p指向第一个结点
while (p) //没到表尾(NULL)
{
q = p->next;
free(p);
p = q;
}
(*L)->next = NULL; //头结点指针域为空
return OK;
}
#define MAXSIZE 1000
typedef struct
{
ElemType date;
int cur; //游标Cursor,为0时表示无指向
}Component,StaticLinkList[MAXSIZE];
//space[0].cur为头指针,"0"表示空指针
Status InitList(StaticLinkList space)
{
int i;
for (i = 0; i < MAXSIZE - 1; i++)
space[i].cur = i+1;
space[MAXSIZE - 1] = 0; //目前静态链表为空,最后一个元素的cur为0
return OK;
}
int Malloc_SLL(StaticLinkList space)
{
int i = space[0].cur;//当前数组第一个元素存的值,就是返回的第一个备用空闲下标
if (space[0].cur)
space[0].cur = space[i].cur;//由于要拿出一个分量来使用,所以我们就得
//把他的下一个分量用来做备用
return i;
}
Status ListInsert(StaticLinkList L, int i, ElemType e)
{
int j, k, l;
k = MAX_SIZE - 1; //注意k首先是最后一个元素下标 //???哪来的MAX_SIZE
if (i < 1 || ListLength(L) + 1)
return ERROR;
j = Malloc_SLL(L);//获得空闲分量的下标
if (j)
{
L[j].date = e;//将数据赋值给此分量的date
for (l = 1; l <= i - 1; l++)//找到第i个元素之前的位置
{
k = L[k].cur;
}
L[j].cur = L[k].cur;//把第i个元素之前的cur赋值给新元素的cur
L[k].cur = j; //把新元素的下标赋值给第i个元素之前的元素的cur
return OK;
}
}
//删除在L中的第i个元素e
Status ListDelete(StaticLinkList L, int i)
{
int j, k;
if (i<1 || i>ListLength(L))
return ERROR;
k = MAX_SIZE - 1;
for (j = 1; j <= i - 1; j++)
k = L[k].cur;
j = L[k].cur;
L[k].cur = L[j].cur;
Free_SLL(L, j);
return OK;
}
void Free_SLL(StaticLinkList space, int k)
{
space[k].cur = space[0].cur;//把第一个元素cur值赋给要删除的分量cur
space[0].cur = k; //把要删除的分量下标赋值给第一个元素的cur
}
int ListLength(StaticLinkList L)
{
int j = 0;
int i = L[MAX_SIZE - 1].cur;
while (i)
{
i = L[i].cur;
j++;
}
return j;
}
typedef struct DulNode
{
ElemType date;
struct DulNode *prior;
struct DulNode *next;
} DulNode,*DuLinkList ;
s->prior = p; //把p赋值给s的前驱 1
s->next = p->next;//把p->next赋值给s的后继 2
p->next->prior=s; //把s赋值给p->next的前驱 3
p->next=s; //把s赋值给p的后继 4
删除:
第三章到此结束。根本没搞明白有木有…下一章是栈与队列。
大话数据结构||学习笔记||从开头至链表||c/c++;