数据结构杂谈

来源:互联网 发布:农村选举知乎 编辑:程序博客网 时间:2024/06/05 16:35

常用的时间复杂度所耗费的时间从小到大依次是:

这里写图片描述

推导大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    0typedef 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)

空间性能

顺序存储结构需要预分配存储空间,分大了,浪费,分小了容易发生上溢。
单链表不需要分配存储空间,只要有就可以分,元素个数也不受限制。

原创粉丝点击