数据结构杂谈

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

这里写图片描述

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

空间性能

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值