数据结构与算法之《顺序表》

简介: 数据结构与算法之《顺序表》

1.什么是顺序表


这篇文章我们来讲一下基础数据结构的顺序表,相信大家在学习C语言的时候接触过数组这种数据结构,但是它又跟顺序表又有什么关系呢?

62e2849ae30c4469bff8f86066174dd1.png


我们知道数组的内存是连续的,一个下标对应着一片内存,而且支持随机访问。这就叫做顺序结构,而数组就是这种结构。果不其然我们的顺序表也是这种结构,但是顺序表就是数组吗?答案是是的,只是其描述角度不同。


  • 线性表是数据结构中的逻辑结构。
  • 线性表采用顺序存储的方式存储就称之为顺序表。
  • 数组是顺序表在实际编程中的具体实现方式之一。



5cc47d090db2dfee6b7e550f66d2bdbe.jpg


顺序表的优势和缺点

前面介绍完了顺序表的定义,我们说说它的优势和不足的地方:

我们知道顺序表的优势如下 :

    支持随机访问,查找速度O(1)

    空间利用率高

那缺点就显而易见了:

增加和删除的速度较慢,如果要在中间插入一个元素则需要挪动后面的所有的元素,造成多余的时间开销,删除同理。 时间复杂度是O(n), 如果不经常删除和改动元素则不推荐使用顺序表这种顺序结构,而用链表则效率更高。

顺序表的长度需要提前指定,长度受到限制。 有同学说我可以进行动态内存分配啊,这样不就行了?其实动态内存分配是解决了长度受限的问题,但存在一个潜在的问题,顺序表扩容我们一般一次就扩充两倍,但是用的可能没有这么多,那多出来的内存空间不就浪费了吗?这是我们说的多余的内存开销问题。


顺序表预备知识

动态内存分配(malloc)

结构体(struct)

顺序表的代码实现

以下为所有的代码实现:

函数接口:


void Sequential_table_deletion(SL*ps,int pos);
void Sequential_table_lookup(SL*ps,int pos,int x); //顺序表中插入数据
int  Seqlistwo(SL*ps,int n);//顺序表中查找元素
void SeqlistPopBack(SL*ps,int n);//尾插函数
void Array_expansion(SL*ps); //扩容
void Seqlistfis(SL*ps);//(3)  //头删 
void Seqlistpuch(SL*ps,int n);  // 头插法
void Array_expansion(SL*ps) //扩容

结构体定义:

typedef struct Seqlist
{
   int *a;
   int size; //表示数组中存储了多少个数据
    int ciap;// 数组能实际存储的容量大小
}SL;


顺序表头部插入

顺序表的头部插入就是先把顺序表的第一个元素空出来,然后把所有的数据往后挪动达到头插的目的

void Seqlistpuch(SL*ps,int n)  // 头插法
{
  Array_expansion(ps);  //检查增容
    int end = ps->size-1;
  while(end>=0)
  {
    ps->a[end+1]=ps->a[end];
    end--;
  }   
  ps->a[0] = n;
  ps->size++;
}


顺序表的销毁

顺序表的销毁就简单了,只要当前表不为空指针,一直释放就可以了

void SeqListDestroy(SeqList* ps)
{
  //断言
  assert(ps);
  //释放空间
  if (ps->a != NULL)
  {
    free(ps->a);
    ps->a = NULL;
    ps->capacity = 0;
    ps->size = 0;
  }
}


顺序表的头插

在使用头插函数前,我们需要检查当前顺序表的空间是否足够我们使用;然后再对顺序表进行操作,当然我们传进来的参数不能为空指针,我们把长度定义为end,让它后一个数等于前一个数,同时长度-1.我们的头插就完成了。


void SeqListPushFront(SeqList*ps,SLDateType x)
{
  断言
  //assert(ps);
  检查扩容
  //SeqListCheck(ps);
  //int end = ps->size-1;
  挪动数据
  //while (end >= 0)
  //{
  //  ps->a[end + 1] = ps->a[end];
  //  end--;
  //}
  在头部插入数据
  //ps->a[0] = x;
  //ps->size++;
  SeqListInsert(ps, 0, x);
}

顺序表的尾删

当前下标大于0 ,长度-1

void SeqListPopBack(SeqList* ps)
{
  //断言
  assert(ps->size>0);
  ps->size--;
}


顺序表的尾插

所有元素向前挪动一个位置,长度+1

void SeqListPushBack(SeqList* ps, SLDateType x)
{
  //断言
  assert(ps);
  //检查扩容
  SeqListCheck(ps);
  //插入数据
  ps->a[ps->size] = x;
  ps->size++;
}


顺序表的任意位置插入

顺序表的任意插入,这个比头部或尾部插入有点麻烦,不过实现起来也不难。我们先要断言一下要插入的下标的有效性。

void removeElem(STL*ps,substitute pos,substitute elem)//在指定位置插入元素
{   
   assert(pos<0&&pos>ps->size);
   int i = 0;
   for(i = 0;i<ps->size;i++)
   {
       ps->a[i]=ps->a[i-1];
   }
 ps->a[pos]=elem;
 ps->size++;
}



顺序表的查找

顺序表的查找和数组是一样的,如果当前顺序表的元素等于要查找的值,则立即返回该数据的下标。否则返回空。

int SeqListFind(SeqList* ps, SLDateType x,int begain)
{
  assert(ps);
  int i = 0;
  //遍历数组进行查找
  for (i = begain; i < ps->size; i++)
  {
    if (ps->a[i] == x)
    {
      return i;
    }
  }
  //查找不到,返回-1
  return -1;
}


顺序表的打印


void Sequential_table_printing(STL*ps) 
{   
    int i = 0;
    for(i = 0;i<ps->size;++i)//打印顺序表的元素
    {
         printf("%d ",ps->a[i]);
    }
}


顺序表的打印和数组是一样的,通过访问其下标。

相关文章
|
2月前
|
存储 算法 程序员
【数据结构】C语言实现顺序表万字详解(附完整运行代码)
【数据结构】C语言实现顺序表万字详解(附完整运行代码)
43 0
|
2月前
|
存储 编译器
数据结构:顺序表详解
数据结构:顺序表详解
37 0
|
2月前
|
存储 机器学习/深度学习 API
顺序表:数据结构的建筑积木
朋友们大家好啊,本节内容我们进入数据结构的第二节,顺序表有关内容,同步我们会学习计组原理与cpp相关知识 本节我们重点探讨动态顺序表关于插入数据和删除数据的多种情况的分析
|
存储 索引
数据结构--动态顺序表
数据结构--动态顺序表
|
2月前
|
存储 消息中间件 算法
数据结构从入门到精通——顺序表
顺序表是一种常见的线性数据结构,它使用一段连续的存储单元依次存储数据元素。这种数据结构的特点是逻辑上相邻的元素在物理存储位置上也相邻,因此可以快速地访问表中的任意元素。 顺序表的实现通常依赖于数组,数组是一种静态的数据结构,一旦创建,其大小就是固定的。这意味着在顺序表中插入或删除元素可能会导致空间的浪费或不足。例如,如果在一个已经满了的顺序表中插入一个新元素,就需要重新分配更大的数组空间,并将原有元素复制到新数组中,这是一个相对耗时的操作。
54 0
|
2天前
|
C++
数据结构(顺序表 动态定义
数据结构(顺序表 动态定义
9 2
|
2天前
|
C++
数据结构(顺序表
数据结构(顺序表
9 1
|
2天前
|
存储
【栈】基于顺序表的栈功能实现
栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端 称为栈顶,另一端称为栈底。栈中的数据元素遵守后进先出LIFO(Last In First Out)的原则。
11 0
|
5天前
|
存储 编译器
【数据结构】~顺序表
【数据结构】~顺序表
|
11天前
|
存储
数据结构第二课 -----线性表之顺序表
数据结构第二课 -----线性表之顺序表