最最简单的数据结构线性表——顺序表(数据结构C语言实现2)

简介: 最最简单的数据结构线性表——顺序表(数据结构C语言实现2)

本节目标

了解线性表结构

能够自己实现顺序表

顺序表oj题

1.线性表概念

1线性表线性表(linear list)


是n个具有相同特性的数据元素的有限序列。线性表是一种在实际中广泛使用的数据结构,常见的线性表:顺序表、链表、栈、队列、字符串…线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是连续的,线性表在物理上存储时,通常以数组和链式结构的形式存储。


数组结构形式

image.png

链表结构形式

image.png

我们今天来实现顺序表结构,即数组结构形式的顺序表。

2.顺序表实现

3.顺序表相关OJ题练习


顺序表实现

概念


顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储。在数组上完成数据的增删查改。


结构


1 静态顺序表:使用定长数组存储。

2 动态顺序表:使用动态开辟的数组存储。

静态顺序表

顺序表都以数组形式,静态顺序表示定长数组。


//顺序表的静态存储
    #define N 7   //定长为7个元素的顺序表
    typedef int SLDataType;
    typedef struct SeqList 
    {
        SLDataType array[N];  //定长数组
        size_t size;   //有效元素个数
    }SeqList;

image.png

这就是静态顺序表,

很明显当顺序表能存下数据的个数是有限的。所以极其不便。我们静态顺序表就介绍到这。


动态顺序表

//顺序表的动态存储
    typedef int SLDataType;
    typedef struct SeqList 
    {
        SLDataType *array;  //指向动态开辟的数组
        size_t size;   //有效元素个数
        size_t capicity; //容量空间大小 
    }SeqList;

image.png

如何实现动态开辟数呢?


void *malloc( size_t size );

<stdlib.h>


Allocates memory blocks.

这是个动态开辟内存空间的函数。

函数的返回值:void*无类型的指针,需要根据自己开辟数据类型的指针强制转换。

函数的常数:size_t字节大小,根据自己需要开辟空间大小。


接口实现

静态顺序表只适用于确定知道需要存多少数据的场景。静态顺序表的定长数组导致N定大了,空间开多了浪费,开少了不够用。所以现实中基本都是使用动态顺序表,根据需要动态的分配空间大小,所以下面我们实现动态顺序表。


线性表就是存数据的一种数据结构,而增删查改等接口的实现是这种数据结构的学习的基础!


// 顺序表的动态存储
typedef struct SeqList
{
SLDataType* array;  // 指向动态开辟的数组
size_t size ;       // 有效数据个数
size_t capicity ;   // 容量空间的大小
}SeqList;
// 基本增删查改接口
// 顺序表初始化
void SeqListInit(SeqList* psl);
// 顺序表销毁
void SeqListDestory(SeqList* psl);
// 顺序表打印
void SeqListPrint(SeqList* psl);
// 检查空间,如果满了,进行增容
void CheckCapacity(SeqList* psl);
// 顺序表尾插
void SeqListPushBack(SeqList* psl, SLDataType x);
// 顺序表尾删
void SeqListPopBack(SeqList* psl);
// 顺序表头插
void SeqListPushFront(SeqList* psl, SLDataType x);
// 顺序表头删void SeqListPopFront(SeqList* psl);
// 顺序表查找
int SeqListFind(SeqList* psl, SLDataType x); 
// 顺序表在pos位置插入x
void SeqListInsert(SeqList* psl, size_t pos, SLDataType x);
// 顺序表删除pos位置的值
void SeqListErase(SeqList* psl, size_t pos);
// 顺序表初始化
void SeqListInit(SeqList* psl)
{
  psl->array = NULL;
  psl->size = 0;
  psl->capacity = 0;
}
// 顺序表销毁
void SeqListDestory(SeqList* psl)
{
  free(psl->array);   //释放空间,防止内存泄漏
  psl->array = NULL;
}
// 顺序表打印
void SeqListPrint(SeqList* psl)
{    
  int i = 0;
  for(i=0;i<psl->size;i++)
  { 
   printf("%d ",psl->array[i]);
  }
  printf("\n");
}
// 检查空间,如果满了,进行增容
void SeqListCheckCapacity(SeqList* psl)
{
  // 满了就要扩容
  if (psl->size == psl->capacity)
  {
  int newcapacity = psl->capacity == 0 ? 4 : psl->capacity * 2;
  SLDataType* tmp = (SLDataType*)realloc(psl->array, newcapacity * sizeof(SLDataType));
  if (tmp == NULL)
  {
    printf("realloc fail\n");
    exit(-1);
  }
  else
  {
    psl->array = tmp;
    psl->capacity = newcapacity;
  }
  }
}
// 顺序表尾插
void SeqListPushBack(SeqList* psl, SLDataType x)
{
  SeqListCheckCapacity(psl);
  psl->array[psl->size] = x;
  psl->size++;
}

image.png

// 顺序表头插
void SeqListPushFront(SeqList* psl, SLDataType x)
{
  SeqListCheckCapacity(psl);
  int i = 0;
  for (i = psl->size; i >0; i--)
  {
   psl->array[i]=psl->array[i-1];
  }
  psl->array[i] = x;
  psl->size++;
}

image.png

//顺序表尾删
void SeqListPopBack(SeqList* psl)
{
  psl->size--;
}

image.png

// 顺序表头删
void SeqListPopFront(SeqList* psl)
{
  int end = 0;
  while (end<psl->size)
  {
  psl->array[end] = psl->array[end+1];
  end++;
  }
  psl->size--;
}

image.png

// 顺序表查找
int SeqListFind(SeqList* psl, SLDataType x)
{
  if (psl == NULL)
  return 0;
  int i = 0;
  for (i = 0; i < psl->size; i++)
  {
  if (psl->array[i] == x)
  {
    printf("找到了、下标为:%d\n", i);
    return i;
     }
  }
  printf("找不到\n");
  return -1;
}

image.png


// 顺序表在pos位置插入x
void SeqListInsert(SeqList* psl, size_t pos, SLDataType x)
{
  SeqListCheckCapacity(psl);
  if (psl->size > pos)
  {
  int i = 0;
  for (i = psl->size; i>pos; i--)
  {
    psl->array[i] = psl->array[i - 1];
  }
  psl->array[i] = x;
  psl->size++;
  }
  else
  {
  printf("该位置不存在\n");
  }
}

image.png

// 顺序表删除pos位置的值
void SeqListErase(SeqList* psl, size_t pos)
{
  if (psl == NULL)
  return 0;
  if (psl->size > pos)
  {
  int i = 0;
  for (i = pos; i < psl->size-1; i++)
  {
    psl->array[i] = psl->array[i + 1];
  }
  psl->size--;
  }
}

image.png

目录
相关文章
|
25天前
|
C语言
【数据结构】栈和队列(c语言实现)(附源码)
本文介绍了栈和队列两种数据结构。栈是一种只能在一端进行插入和删除操作的线性表,遵循“先进后出”原则;队列则在一端插入、另一端删除,遵循“先进先出”原则。文章详细讲解了栈和队列的结构定义、方法声明及实现,并提供了完整的代码示例。栈和队列在实际应用中非常广泛,如二叉树的层序遍历和快速排序的非递归实现等。
116 9
|
24天前
|
存储 搜索推荐 算法
【数据结构】树型结构详解 + 堆的实现(c语言)(附源码)
本文介绍了树和二叉树的基本概念及结构,重点讲解了堆这一重要的数据结构。堆是一种特殊的完全二叉树,常用于实现优先队列和高效的排序算法(如堆排序)。文章详细描述了堆的性质、存储方式及其实现方法,包括插入、删除和取堆顶数据等操作的具体实现。通过这些内容,读者可以全面了解堆的原理和应用。
62 16
|
24天前
|
C语言
【数据结构】二叉树(c语言)(附源码)
本文介绍了如何使用链式结构实现二叉树的基本功能,包括前序、中序、后序和层序遍历,统计节点个数和树的高度,查找节点,判断是否为完全二叉树,以及销毁二叉树。通过手动创建一棵二叉树,详细讲解了每个功能的实现方法和代码示例,帮助读者深入理解递归和数据结构的应用。
80 8
|
26天前
|
存储 C语言
【数据结构】手把手教你单链表(c语言)(附源码)
本文介绍了单链表的基本概念、结构定义及其实现方法。单链表是一种内存地址不连续但逻辑顺序连续的数据结构,每个节点包含数据域和指针域。文章详细讲解了单链表的常见操作,如头插、尾插、头删、尾删、查找、指定位置插入和删除等,并提供了完整的C语言代码示例。通过学习单链表,可以更好地理解数据结构的底层逻辑,提高编程能力。
51 4
|
28天前
|
存储 算法 安全
2024重生之回溯数据结构与算法系列学习之顺序表【无论是王道考研人还真爱粉都能包会的;不然别给我家鸽鸽丢脸好嘛?】
顺序表的定义和基本操作之插入;删除;按值查找;按位查找等具体详解步骤以及举例说明
|
28天前
|
存储 C语言
【数据结构】顺序表(c语言实现)(附源码)
本文介绍了线性表和顺序表的基本概念及其实现。线性表是一种有限序列,常见的线性表有顺序表、链表、栈、队列等。顺序表是一种基于连续内存地址存储数据的数据结构,其底层逻辑是数组。文章详细讲解了静态顺序表和动态顺序表的区别,并重点介绍了动态顺序表的实现,包括初始化、销毁、打印、增删查改等操作。最后,文章总结了顺序表的时间复杂度和局限性,并预告了后续关于链表的内容。
60 3
|
28天前
|
算法 安全 NoSQL
2024重生之回溯数据结构与算法系列学习之顺序表习题精讲【无论是王道考研人还真爱粉都能包会的;不然别给我家鸽鸽丢脸好嘛?】
顺序表的定义和基本操作之插入;删除;按值查找;按位查找习题精讲等具体详解步骤以及举例说明
|
26天前
|
C语言
【数据结构】双向带头循环链表(c语言)(附源码)
本文介绍了双向带头循环链表的概念和实现。双向带头循环链表具有三个关键点:双向、带头和循环。与单链表相比,它的头插、尾插、头删、尾删等操作的时间复杂度均为O(1),提高了运行效率。文章详细讲解了链表的结构定义、方法声明和实现,包括创建新节点、初始化、打印、判断是否为空、插入和删除节点等操作。最后提供了完整的代码示例。
41 0
|
28天前
|
算法 安全 搜索推荐
2024重生之回溯数据结构与算法系列学习之王道第2.3章节之线性表精题汇总二(5)【无论是王道考研人还是IKUN都能包会的;不然别给我家鸽鸽丢脸好嘛?】
IKU达人之数据结构与算法系列学习×单双链表精题详解、数据结构、C++、排序算法、java 、动态规划 你个小黑子;这都学不会;能不能不要给我家鸽鸽丢脸啊~除了会黑我家鸽鸽还会干嘛?!!!
|
C语言
C语言顺序表,合并并排序(代码注释讲解)
C语言顺序表,合并并排序(代码注释讲解)
356 0