【数据结构和算法】实现线性表中的静态、动态顺序表(上)

简介: 【数据结构和算法】实现线性表中的静态、动态顺序表

本文是数据结构的开篇,上文学习了关于使用C语言实现静态、动态、文件操作的通讯录,其中使用到了结构体这一类型,实际上,是可以属于数据结构的内容,接下来我们来了解一下顺序表的相关内容。

前言

数据结构是什么?

对于大家来说,这是一个全新的内容模块,数据结构是计算机存储、组织数据的方式。数据结构是指相互之间存在一种或多种特定关系的数据元素的集合。通常情况下,精心选择的数据结构可以带来更高的运行或者存储效率。数据结构往往同高效的检索算法索引技术有关。

我们接下来是对于数据结构的顺序表的实现的讲解


一、线性表

线性表(linear list)是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结构,常见的线性表:顺序表、链表、栈、队列、字符串...

线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是连续的,线性表在物理上存储时,通常以数组和链式结构的形式存储。

实际上,学会了顺序表和链表,自然栈、队列、二叉树等各种结构就好学啦,又称顺序表和链表是数据结构的基础,是实现后序内容的基础。

一、顺序表是什么?

1.将表中元素一个接一个的存入一组连续的存储单元中,这种存储结构顺序结构

2.使用顺序结构存储的线性表叫做顺序表

总结:

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

二、分析顺序表的实现

顺序表,分为动态和静态两种顺序表,顺序表的实际操作功能大致为,增删改查,又细分为头尾增删,初始化、摧毁顺序表等操作。

我们接下来分别介绍静态和动态顺序表是如何实现的!!!

三、静态顺序表

使用结构体为:

1.顺序表初始化

如图所示:

代码演示:

//初始化函数
void InitSeqtable(Seqtable* st) {
  //for (int i = 0; i < MAX; i++) {
  //  st->date[i] = 0;//初始化为0  实际上可以不用初始化数组
  //}
  st->size = 0;
}

2.增加元素

分为头插入、尾插入

1.尾插

如图所示:

代码演示:

//尾插入
void BackSeqtable(Seqtable* st, int data) {
  //尾部插入的时候要进行判别是否为满
  if (st->size == MAX) {
    //表示满了
    perror("顺序表已经满员,无法插入新数据\n");
    exit(-1);//退出就可以
  }
  //没有满员,就加入数据即可
  st->date[st->size++] = data;
}

2.头插

如图所示:

代码如下:

//头插入
void FrontSeqtable(Seqtable* st, int data) {
  //一样先进行判断是否满员
  if (st->size == MAX) {
    perror("满员无法插入");
    exit(-1);
  }
  //头部插入。就是将原有数据向后移动一个位置
  int num = st->size - 1;
  for (int i = num; i>=0; i--) {
    st->date[i + 1] = st->date[i];
  }
  //while (num>=0) {
  //  st->date[num + 1] = st->date[num];
  //  num--;
  //}
  //最后插入数据
  st->date[0] = data;
  st->size++;
}

3.删除元素

分为头删、尾删

1.尾删

如图所示:

代码如下:

//尾删除
void SeqtablePopBack(Seqtable* st) {
  //尾删除,需要判断是否为空
  assert(st->size > 0);//断言判断
  st->size--;//直接元素个数减去一个就可以
}

2.头删

如图所示:

代码如下:

//头删除
void SeqtablePopFront(Seqtable* st) {
  //头部删除,也要判空
  assert(st->size > 0);//断言
  //将后面的数据覆盖前面的数据
  for (int i = 0; i < st->size-1; i++) {
    st->date[i] = st->date[i + 1];
  }
  st->size--;//size减去一个元素即可
}

4.改变数据和查找

想要改变指定下标的数据,输入要查找的元素,更改这个的数据,要先查找到对应坐标,简易的更改数值,不考虑重复的问题,从左向右的顺序查询

代码如下:

//查找
int SearchSeqtable(Seqtable* st) {
  assert(st->size > 0);//如果为空,不用查找,直接报错
  int num = 0;
  scanf("%d", &num);//输入查找的元素
  for (int i = 0; i < st->size; i++) {
    if (st->date[i] == num) {
      return i;//找到返回下标
    }
  }
  return -1;//没找到返回-1
}
void ChangeSeqtable(Seqtable* st) {
  int num=SearchSeqtable(st);//进入查找,返回下标
  if (num == -1) {
    printf("顺序表中没有该元素,无法修改\n");
    return;
  }
  int a = 0;
  scanf("%d", &a);//输入想要更改的数据
  st->date[num] = a;
}

5.打印和销毁顺序表

代码如下:

//摧毁顺序表
void SeqtableDestory(Seqtable* st) {
  //摧毁的话,静态表直接初始化为0
  st->size = 0;
}
//打印
void PrintSeqtable(Seqtable* st) {
  for (int i = 0; i < st->size; i++) {
    printf("%d ", st->date[i]);
  }
}

四、动态顺序表

动态顺序表和静态顺序表的差别就是结构体、初始化、摧毁顺序表、扩容

结构体如下:

//动态顺序表
typedef struct Seqtable {
  int* data;//数据域
  int size;//个数
  int capacity;//容量
}Seqtable;
//实际上动态顺序表和静态顺序表,只有在初始化、销毁、扩容的时候不一样

1.初始化

//初始化顺序表
void InitSeqtable(Seqtable* st) {
  st->size = st->capacity = 0;
  st->data = NULL;
}

2.扩容

如图所示:

代码演示:

//扩容
void Expansion(Seqtable* st) {
  //1.直接扩容二倍,这样防止后序一致扩容
  int newcapacity = st->capacity = 0 ? 4 : st->capacity * 2;
  int* tmp = (int*)realloc(st->data, newcapacity * sizeof(int));
  if (tmp == NULL) {
    //表示创建失败
    perror("realloc fail\n");
    exit(-1);
  }
  //创建成功  tmp给data
  st->data = tmp;
  st->capacity = newcapacity;
}

如图上,另外一种扩容方法,可以看这篇文章中动态通讯录扩容,里面有介绍(24条消息) 【C语言】使用C语言实现静态、动态的通讯录(简单易懂)_小王学代码的博客-CSDN博客

3.销毁顺序表

void SeqListDestory(Seqtable* ps) {
  free(ps->data);//直接释放a的空间 
  ps->data = NULL;//然后指向NULL
  ps->capacity = ps->size = 0;
}

除此之外,和静态顺序表都差不多一样了

相关文章
|
11天前
|
存储 Java 程序员
【数据结构】初识集合&深入剖析顺序表(Arraylist)
Java集合框架主要由接口、实现类及迭代器组成,包括Collection和Map两大类。Collection涵盖List(有序、可重复)、Set(无序、不可重复),Map则由键值对构成。集合通过接口定义基本操作,具体实现由各类如ArrayList、HashSet等提供。迭代器允许遍历集合而不暴露其实现细节。List系列集合元素有序且可重复,Set系列元素无序且不可重复。集合遍历可通过迭代器、增强for循环、普通for循环及Lambda表达式实现,各有适用场景。其中ArrayList实现了动态数组功能,可根据需求自动调整大小。
26 11
|
19天前
|
存储 C语言 C++
数据结构基础详解(C语言) 顺序表:顺序表静态分配和动态分配增删改查基本操作的基本介绍及c语言代码实现
本文介绍了顺序表的定义及其在C/C++中的实现方法。顺序表通过连续存储空间实现线性表,使逻辑上相邻的元素在物理位置上也相邻。文章详细描述了静态分配与动态分配两种方式下的顺序表定义、初始化、插入、删除、查找等基本操作,并提供了具体代码示例。静态分配方式下顺序表的长度固定,而动态分配则可根据需求调整大小。此外,还总结了顺序表的优点,如随机访问效率高、存储密度大,以及缺点,如扩展不便和插入删除操作成本高等特点。
|
19天前
|
存储 算法 C语言
C语言手撕数据结构代码_顺序表_静态存储_动态存储
本文介绍了基于静态和动态存储的顺序表操作实现,涵盖创建、删除、插入、合并、求交集与差集、逆置及循环移动等常见操作。通过详细的C语言代码示例,展示了如何高效地处理顺序表数据结构的各种问题。
|
1天前
|
存储 Java
java数据结构,线性表顺序存储(数组)的实现
文章介绍了Java中线性表顺序存储(数组)的实现。线性表是数据结构的一种,它使用数组来实现。文章详细描述了线性表的基本操作,如增加、查找、删除、修改元素,以及其他操作如遍历、清空、求长度等。同时,提供了完整的Java代码实现,包括MyList接口和MyLinearList实现类。通过main函数的测试代码,展示了如何使用这些方法操作线性表。
|
1月前
|
算法
【初阶数据结构】复杂度算法题篇
该方法基于如下的事实:当我们将数组的元素向右移动 k 次后,尾部 kmodn 个元素会移动至数组头部,其余元素向后移动 kmodn 个位置。
|
1月前
|
机器学习/深度学习 人工智能 算法
【人工智能】线性回归模型:数据结构、算法详解与人工智能应用,附代码实现
线性回归是一种预测性建模技术,它研究的是因变量(目标)和自变量(特征)之间的关系。这种关系可以表示为一个线性方程,其中因变量是自变量的线性组合。
43 2
|
1月前
|
存储 算法
【数据结构与算法】顺序表
【数据结构与算法】顺序表
16 0
【数据结构与算法】顺序表
|
1月前
|
算法
【初阶数据结构篇】二叉树算法题
二叉树是否对称,即左右子树是否对称.
|
1月前
|
算法 索引
【初阶数据结构篇】单链表算法题进阶
深拷贝应该正好由 n 个全新节点组成,其中每个新节点的值都设为其对应的原节点的值。
|
1月前
|
存储 算法
【初阶数据结构篇】顺序表和链表算法题
此题可以先找到中间节点,然后把后半部分逆置,最近前后两部分一一比对,如果节点的值全部相同,则即为回文。