数据结构------------线性表之顺序表(详细教学)

简介: 数据结构------------线性表之顺序表(详细教学)

1.线性表

线性表linear listn个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使

用的数据结构,常见的线性表:顺序表、链表、栈、队列、字符串...

线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是连续的,

线性表在物理上存储时,通常以数组和链式结构的形式存储。

      上图为单链表 

1.1顺序表定义

顺序表是在计算机内存中以数组的形式保存的线性表,线性表的顺序存储是指用一组地址连续的存储单元依次存储线性表中的各个元素、使得线性表中在逻辑结构上相邻的数据元素存储在相邻的物理存储单元中,即通过数据元素物理存储的相邻关系来反映数据元素之间逻辑上的相邻关系,采用顺序存储结构的线性表通常称为顺序表。顺序表是将表中的结点依次存放在计算机内存中一组地址连续的存储单元中。

1.2顺序表实现

1.2.1概念及结构

顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存

储。在数组上完成数据的增删查改。

顺序表一般可以分为:

                                静态的顺序表(定长数组实现

                                动态的顺序表

                                               

// 顺序表的静态存储
#define N 100           //为了便于修改数据大小
typedef int SLDataType;//为了便于修改数据类型
typedef struct SeqList
{
     SLDataType array[N]; // 定长数组
     size_t size;        // 有效数据的个数
}SeqList;

 静态实现  

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

  动态实现  

1.2.2接口实现

静态顺序表只适用于确定知道需要存多少数据的场景。静态顺序表的定长数组导致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);
// 顺序表查找
intSeqListFind(SeqList*psl, SLDataType x); 
// 顺序表在pos位置插入x
void SeqListInsert(SeqList* psl, size_t pos, SLDataType x);// 顺序表删除pos位置的值
void SeqListErase(SeqList* psl, size_t pos);

1.初始化顺序表

void SeqListInit(SL* ps)
{
  assert(ps);
  ps->a = NULL;
  ps->size = 0;
  ps->capacity = 0;//注意这里空间赋为0开辟空间翻倍要赋初值
}

由于下面的增删查改要多次使用检查空间是否足够,这里我们使用一个检查空间函数来解决这个问题。

void SeqListCheckCapacity(SL* ps)
{
  int newcapicity = ps->capacity == 0 ? 4 : ps->capacity * 2;
  SQDataType* tmp = (SQDataType*)realloc(ps->a, ps->capacity * 2 * sizeof(SQDataType));
  if (tmp == NULL)
  {
    printf("realloc fail\n");
    exit(-1);
  }
  else
  {
    ps->a = tmp;
    ps->capacity = newcapicity;
  }
}

  1.头插接口的实现

(后面的元素向后挪一个,从最后开始,因为从头开始会导致数据的覆盖)

void SeqListPushFront(SL* ps, SQDataType x)//头插
{
  SeqListCheckCapacity(ps);//检查容量
  //初始条件
  //结束条件
  //迭代过程
  int end = ps->size - 1;
  while (end >= 0)
  {
    ps->a[end + 1] = ps->a[end];
    --end;
  }
  ps->a[0] = x;
  ps->size++;
}

2.尾插的实现

void SeqListPushBack(SL* ps, SQDataType x)
{
  SeqListCheckCapacity(ps);
  ps->a[ps->size] = x;
  ps->size++;
}

3.头删与尾删

//尾删
void SeqListPopBack(SL* ps)
{
  assert(ps->size > 0);
  ps->a[ps->size - 1] = 0;
  ps->size--;
}
//头删
void SeqListPopFront(SL* ps)
{
  assert(ps->size > 0);
  int start = 1;
  while (start < ps->size)
  {
    ps->a[start - 1] = ps->a[start];
    ++start;
  }
  ps->size--;
}

4.随机位置的写删

void SeqListPopFront(SL* ps)
{
  assert(ps->size > 0);
  int start = 1;
  while (start < ps->size)
  {
    ps->a[start - 1] = ps->a[start];
    ++start;
  }
  ps->size--;
  SeqListErase(ps, 0);
}
void SeqListInsert(SL* ps, int pos, SQDataType x)
{
  assert(pos <= ps->size);
  SeqListCheckCapacity(ps);
  int end = ps->size - 1;
  while (end >= pos)
  {
    ps->a[end + 1] = ps->a[end];
    --end;
  }
  ps->a[pos] = x;
  ps->size++;
}

这里我们发现以上的头插/删和尾插/删可以通过以上的随机位置读写完成,大大减少了代码量

于是代码简化成

//头删
void SeqListPopFront(SL* ps)
{
  SeqListErase(ps, 0);
}
//尾删
void SeqListPopBack(SL* ps)
{
  SeqListErase(ps, ps->size - 1);
}
//头插
void SeqListPushFront(SL* ps, SQDataType x)
{
  SeqListInsert(ps, 0, x);
}
//尾插
void SeqListPushBack(SL* ps, SQDataType x)
{
  SeqListInsert(ps, ps->size, x);
}

5.其余接口实现

int SeqListFind(SL* ps, SQDataType x)
{
  for (int i = 0; i < ps->size; ++i)
  {
    if (ps->a[i] == x)
    {
      return i;
    }
  }
  return -1;
}
void SeqListModity(SL* ps, int pos, SQDataType x)
{
  assert(pos < ps->size);
  ps->a[pos] = x;
}
void SeqListPrint(SL* ps)
{
  for (int i = 0; i < ps->size; ++i)
  {
    printf("%d ", ps->a[i]);
  }
  printf("\n");
}
相关文章
|
1月前
|
存储 算法 C++
【C++数据结构——查找】二分查找(头歌实践教学平台习题)【合集】
二分查找的基本思想是:每次比较中间元素与目标元素的大小,如果中间元素等于目标元素,则查找成功;顺序表是线性表的一种存储方式,它用一组地址连续的存储单元依次存储线性表中的数据元素,使得逻辑上相邻的元素在物理存储位置上也相邻。第1次比较:查找范围R[0...10],比较元素R[5]:25。第1次比较:查找范围R[0...10],比较元素R[5]:25。第2次比较:查找范围R[0..4],比较元素R[2]:10。第3次比较:查找范围R[3...4],比较元素R[3]:15。,其中是顺序表中元素的个数。
136 68
【C++数据结构——查找】二分查找(头歌实践教学平台习题)【合集】
|
1月前
|
存储 C语言 C++
【C++数据结构——栈与队列】顺序栈的基本运算(头歌实践教学平台习题)【合集】
本关任务:编写一个程序实现顺序栈的基本运算。开始你的任务吧,祝你成功!​ 相关知识 初始化栈 销毁栈 判断栈是否为空 进栈 出栈 取栈顶元素 1.初始化栈 概念:初始化栈是为栈的使用做准备,包括分配内存空间(如果是动态分配)和设置栈的初始状态。栈有顺序栈和链式栈两种常见形式。对于顺序栈,通常需要定义一个数组来存储栈元素,并设置一个变量来记录栈顶位置;对于链式栈,需要定义节点结构,包含数据域和指针域,同时初始化栈顶指针。 示例(顺序栈): 以下是一个简单的顺序栈初始化示例,假设用C语言实现,栈中存储
142 77
|
1月前
|
存储 C++
【C++数据结构——树】哈夫曼树(头歌实践教学平台习题) 【合集】
【数据结构——树】哈夫曼树(头歌实践教学平台习题)【合集】目录 任务描述 相关知识 测试说明 我的通关代码: 测试结果:任务描述 本关任务:编写一个程序构建哈夫曼树和生成哈夫曼编码。 相关知识 为了完成本关任务,你需要掌握: 1.如何构建哈夫曼树, 2.如何生成哈夫曼编码。 测试说明 平台会对你编写的代码进行测试: 测试输入: 1192677541518462450242195190181174157138124123 (用户分别输入所列单词的频度) 预
59 14
【C++数据结构——树】哈夫曼树(头歌实践教学平台习题) 【合集】
|
1月前
|
存储 C++ 索引
【C++数据结构——栈与队列】环形队列的基本运算(头歌实践教学平台习题)【合集】
【数据结构——栈与队列】环形队列的基本运算(头歌实践教学平台习题)【合集】初始化队列、销毁队列、判断队列是否为空、进队列、出队列等。本关任务:编写一个程序实现环形队列的基本运算。(6)出队列序列:yzopq2*(5)依次进队列元素:opq2*(6)出队列序列:bcdef。(2)依次进队列元素:abc。(5)依次进队列元素:def。(2)依次进队列元素:xyz。开始你的任务吧,祝你成功!(4)出队一个元素a。(4)出队一个元素x。
43 13
【C++数据结构——栈与队列】环形队列的基本运算(头歌实践教学平台习题)【合集】
|
1月前
|
算法 C++
【C++数据结构——查找】二叉排序树(头歌实践教学平台习题)【合集】
【数据结构——查找】二叉排序树(头歌实践教学平台习题)【合集】 目录 任务描述 相关知识 测试说明 我的通关代码: 测试结果: 任务描述 本关任务:实现二叉排序树的基本算法。 相关知识 为了完成本关任务,你需要掌握:二叉树的创建、查找和删除算法。具体如下: (1)由关键字序列(4,9,0,1,8,6,3,5,2,7)创建一棵二叉排序树bt并以括号表示法输出。 (2)判断bt是否为一棵二叉排序树。 (3)采用递归方法查找关键字为6的结点,并输出其查找路径。 (4)分别删除bt中关键
53 11
【C++数据结构——查找】二叉排序树(头歌实践教学平台习题)【合集】
|
1月前
|
存储 人工智能 算法
【C++数据结构——图】最短路径(头歌教学实验平台习题) 【合集】
任务描述 本关任务:编写一个程序,利用Dijkstra算法,实现带权有向图的最短路径。 相关知识 为了完成本关任务,你需要掌握:Dijkst本关任务:编写一个程序,利用Dijkstra算法,实现带权有向图的最短路径。为了完成本关任务,你需要掌握:Dijkstra算法。带权有向图:该图对应的二维数组如下所示:Dijkstra算法:Dijkstra算法是指给定一个带权有向图G与源点v,求从v到G中其他顶点的最短路径。Dijkstra算法的具体步骤如下:(1)初始时,S只包含源点,即S={v},v的距离为0。
58 15
|
1月前
|
Java C++
【C++数据结构——树】二叉树的基本运算(头歌实践教学平台习题)【合集】
本关任务:编写一个程序实现二叉树的基本运算。​ 相关知识 创建二叉树 销毁二叉树 查找结点 求二叉树的高度 输出二叉树 //二叉树节点结构体定义 structTreeNode{ intval; TreeNode*left; TreeNode*right; TreeNode(intx):val(x),left(NULL),right(NULL){} }; 创建二叉树 //创建二叉树函数(简单示例,手动构建) TreeNode*create
48 12
|
1月前
|
C++
【C++数据结构——树】二叉树的性质(头歌实践教学平台习题)【合集】
本文档介绍了如何根据二叉树的括号表示串创建二叉树,并计算其结点个数、叶子结点个数、某结点的层次和二叉树的宽度。主要内容包括: 1. **定义二叉树节点结构体**:定义了包含节点值、左子节点指针和右子节点指针的结构体。 2. **实现构建二叉树的函数**:通过解析括号表示串,递归地构建二叉树的各个节点及其子树。 3. **使用示例**:展示了如何调用 `buildTree` 函数构建二叉树并进行简单验证。 4. **计算二叉树属性**: - 计算二叉树节点个数。 - 计算二叉树叶子节点个数。 - 计算某节点的层次。 - 计算二叉树的宽度。 最后,提供了测试说明及通关代
46 10
|
1月前
|
算法 C++
【C++数据结构——图】最小生成树(头歌实践教学平台习题) 【合集】
【数据结构——图】最小生成树(头歌实践教学平台习题)目录 任务描述 相关知识 测试说明 我的通关代码: 测试结果:【合集】任务描述 本关任务:编写一个程序求图的最小生成树。相关知识 为了完成本关任务,你需要掌握:1.建立邻接矩阵,2.Prim算法。建立邻接矩阵 上述带权无向图对应的二维数组,根据它建立邻接矩阵,如图1建立下列邻接矩阵。注意:INF表示无穷大,表示整数:32767 intA[MAXV][MAXV];Prim算法 普里姆(Prim)算法是一种构造性算法,从候选边中挑
43 10
|
1月前
|
存储 算法 C++
【C++数据结构——图】图的邻接矩阵和邻接表的存储(头歌实践教学平台习题)【合集】
本任务要求编写程序实现图的邻接矩阵和邻接表的存储。需掌握带权有向图、图的邻接矩阵及邻接表的概念。邻接矩阵用于表示顶点间的连接关系,邻接表则通过链表结构存储图信息。测试输入为图的顶点数、边数及邻接矩阵,预期输出为Prim算法求解结果。通关代码提供了完整的C++实现,包括输入、构建和打印邻接矩阵与邻接表的功能。
49 10

热门文章

最新文章