常用的时间复杂度所耗费的时间从小到大依次是:
推导大O阶的步骤:
1.用常数1取代运行时间中的所有加法常数;
2.在修改后的运行次数函数中,只保留最高阶项;
3.如果最高阶项存在且不是1,则去除与这个项相乘的常数。
线性表顺序存储结构
#define MAXSIZE 20 //存储空间初始分配量
typedef int ElemType;
typedef struct
{
ElemType data[MAXSIZE]; //数组存储数据元素,最大值为MAXSIZE
int length; //线性表当前长度
}sqlist;
描述顺序存储结构需要三个属性:
1.存储空间的起始位置:数组data,它的存储位置就是存储空间的存储位置。
2.线性表的最大存储容量:数组长度MAXSIZE。
3.线性表的当前长度:length。
顺序存储插入
1.如果插入位置不合理,抛出异常。
2.如果线性表长度大于等于数组长度,则抛出异常或动态增加向量。
3.从最后一个元素开始向前遍历到第i个位置,分别将它们都向后移动一个位置。
4.将要插入的元素填入位置i处;
5.表长加一。
#define OK 1
#define ERROR 0
typedef int Status;
Status Listinsert(sqlist *L,int i,ElemType e)
{
int k;
if(L->length==MAXSIZE-1) //顺序线性表已满(注意此处线性表下标从0开始)
return ERROR;
if(i < 1 || i>L->length+2) //i不在范围,范围是1<=i && i<=MAXSIZE+1
return ERROR;
for(k=L->length;k>=i-1;k--)
L->data[k+1] = l->data[k];
L->data[i-1] = e;
L->length++;
return OK;
}
顺序存储删除
1.如果删除位置不合理,抛出异常。
2.取出删除元素。
3.从删除元素位置开始遍历到最后一个元素位置,分别将它们都向前移动一个位置。
4.表长减一。
Status ListDelete(sqlist *L,int i,ElemType *e)
{
int k;
if(i<1 || i>L->length+1) //删除位置不正确
return ERROR;
*e = L->data[i-1];
for(k=i;k<=l->Length;k++)
L->data[j-1] = L->data[j];
L->length--;
return OK;
}
线性表顺序存储优缺点
优点
1.无需为表示表中元素之间的逻辑关系而增加额外的存储空间。
2.可以快速地存取表中任意位置的元素。
缺点
1.插入和删除操作需要移动大量元素。
2.当线性表长度变化较大时,难以确定存储空间的容量。
3.造成存储空间的“碎片”。
线性表链式存储结构
typedef struct node
{
ElemType data;
struct node *next;
}*linklist;
头指针与头结点的异同
头指针
1.头指针是指链表指向第一个结点的指针,若链表有头结点,则是指向头结点的指针。
2.头指针有标识作用,所以常用头指针冠以链表的名字。
3.无论链表是否为空,头指针均不为空。头指针是链表的必要元素。
头结点
1.头结点是为了操作的统一和方便而设立的,放在第一元素节点之前,其数据域一般无意义(也可存放链表的长度)。
2.有了头结点,对在第一元素节点前插入节点和删除第一节点,其操作与其他节点的操作就统一了。
3.头结点不一定是链表必须要素。
链式存储读取(读取链表第i个数据)
1.声明一个结点p指向第一个结点,初始化j从1开始;
2.当j
Status GetElem(linklist L,int i,ElemType *e)
{
int j;
linklist p;
p = l; //p指向链表的第一个节点
j = 1; //j为计数器
while(p && j<i) //p不为空且计数器j还没有等于i时,循环继续
{
p = p->next;
j++;
}
if(j ==i)
*e = p->data;
else
return ERROR;
}
链式存储插入(第i-1个结点后插入新结点)
单链表的插入标准语句s->next = p->next; p->next = s;
1.先构造一个新节点,用s指向;
2.再找到链表的第i-1个节点,用p指向;
3.然后修改指针,插入节点(p之后插入新节点s)。
linklist listinsert(linklist *L,int i,ElemType e)
{
linklist p,s;
if(i == 1)
{
s = (linklist)malloc(sizeof(struct node));
s->data = e;
s->next = L;
return s;
}
p = findkth(i-1,L);
if(p == NULL)
return ERROR;
else
{
s = (linklist)malloc(sizeof(struct node));
s->data = e;
s->next = p->next;
p->next = s;
return L;
}
}
链式存储删除(删除第i个位置上的节点)
s = p->next; p->next = s->next;
1.先找到链表的第i-1个节点,用p指向;
2.再用指针s指向要被删除的节点(p的下一个节点);
3.然后修改指针,删除s所指节点;
4.最后释放s所指节点的空间。
linklist delete(int i, list L)
{
linklist p,s;
if(i == 1)
{
s = L;
if(L)
L = L->next;
else
return NULL;
free(s);
return L;
}
p = findkth(i-1,L);
if(p ==NULL)
return NULL;
else if(p->next == NULL)
return NULL;
else
{
s = p->next;
p->next = s->next;
free(s);
return L;
}
}
线性表单链表结构与顺序存储结构优缺点
存储分配方式
1.顺序存储结构用一段连续的存储单元依次存储线性表的数据元素。
2.单链表采用链式存储结构,用一组任意的存储单元存放线性表的元素。
时间性能
查找
顺序存储结构:O(1)
单链表O(n)
插入和删除
顺序存储结构需要平均移动表长一半的元素,时间为O(n)
单链表在找出某位置的指针后,插入和删除时间仅为O(1)
空间性能
顺序存储结构需要预分配存储空间,分大了,浪费,分小了容易发生上溢。
单链表不需要分配存储空间,只要有就可以分,元素个数也不受限制。