《数据结构》c语言版学习笔记——线性表的顺序存储结构

简介: 《数据结构》c语言版学习笔记——线性表的顺序存储结构

前言


数据结构是大学里计算机专业类必掌握的一门课程,它很重要,尤其是对一些考研的计算机类学生来说,通常为专业课。数据结构并不是哪种编程语言所设定的,它可以用c语言来写,也可以用c++、java、python等等,学会了一门编程语言,仅仅只是掌握一些,而学会了数据结构可以掌握很多技巧和算法并不断提高编程能力,这对将来很重要。


提示:本系列文章均使用Visual Studio 2019编程,编程语言为c语言。


一、顺序存储结构的建立


1.条件


设顺序线性表L,n为数据元素,则1 ≦ n ≦ ListLength(L),这里解释一下这个闭区间,首先我们知道线性表是从1开始的,而不是像数组从0开始,这点要知道,所以n的值不能小于1,并且不能大于该线性表的长度。

我们设该线性表的存储空间为20,即#define MAXSIZE 20,然后假设ElemType为int类型,使用一个结构体,定义一个data数组来存储数据元素,length为当前长度。

即,我们可知道建立一个顺序线性表有三个要点:

①首先要定义其最大存储量

②存储空间

③线性表的当前长度


2.代码


#include <stdio.h>
#define MAXSIZE 20            //设定存储空间初始分配量
//顺序存储结构的建立
typedef int ElemType;
typedef struct
{
  ElemType data[MAXSIZE];   //数组存储数据元素,最大值为MAXSIZE
  int length;               //线性表当前长度
}SqList;


二、顺序存储结构的获得元素


1.条件


首先这里返回值类型Status是一个int整型,返回OK代表1,返回ERROR代表0。我们要实行GetElem操作,即将顺序线性表L的第i个元素值返回,因为数组是从0开始的,代码中只要n的数值在所定义的数组下标的范围内,把数组n-1下标的值返回。

即,我们可知道顺序线性表获得元素有两个要点:

①判断语句

②返回值


2.代码


#include <stdio.h>
#define MAXSIZE 20            //设定存储空间初始分配量
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
typedef int Status;
//顺序结构的获得元素操作
Status GetElem(SqList L, int n, ElemType* e)    //Status是函数类型,其值是函数结果状态代码,例OK等;
{                                               //SqList L为该线性表;int n为索引位置;ElemType*e为指针直接访问地址
  if (L.length == 0 || n<1 || n>L.length)     //线性表的长度不为0;线性表是从1访问的,而不是0;索引位置不能大于线性表的长度
    return ERROR;        //以上均返回错误
  *e = L.data[n-1];        //若满足以上条件,则将线性表L中的第n个位置元素值返回,即只要n的数值在数组下标范围内,就将数组第n-1下标的值返回
  return OK;
}


三、顺序存储结构的插入


1.条件


设k为当前位置,首先判断线性表是否已满,再对插入位置进行判断,然后判断插入位置是否在表尾,从而执行不同操作,若不在表尾,通过for语句遍历,将要插入的位置后的数据元素向后移动一位;若在表尾,则直接插入新元素,当前长度++。

即,顺序线性表插入元素有五个要点:

①若插入位置不合理,抛出异常

②判断语句

③从最后一个元素开始向前遍历到第i个位置,分别将它们都向后移动一个位置

④将要插入元素插入位置i处

⑤表长加1


2.代码


//顺序结构的插入操作
typedef int Status;
Status ListInsert(SqList* L, int n, ElemType e)
{
  int k;                          //k为当前位置
  if (L->length == MAXSIZE)       //当顺序线性表存储已满返回错误  
    return ERROR;    
  if (n<1 || n>L->length + 1)    //插入位置小于1、大于当前长度加一则返回错误
    return ERROR;
  if (n <= L->length)            //若插入位置不在线性表表尾,执行以下操作,将要插入的位置后数据元素向后移动一位
  {
    for (k = L->length - 1; k >= n - 1; k--)    //遍历从i索引位置到线性表长度的每个数据元素,将其全部向后移动一位
      L->data[k + 1] = L->data[k];           
  }
  //若插入位置在表尾,执行插入新元素操作
  L->data[n - 1] = e;             //[i-1]是因为顺序表位置-1=数组下标,数组从0开始,顺序表从1开始
  L->length++;
  return OK;
}


四、顺序存储结构的删除


1.条件


设k为当前位置,首先判断线性表是否为空表,再判断删除元素长度,用指针取出所要删除的数据元素,然后再判断删除位置是否在表尾,若不在表尾,通过for语句遍历,将要删除的位置后数据元素向前移动一位;若在表尾,则删除该元素,当前长度- -。

顺序线性表删除元素有四个要点:

①若删除位置不合理,抛出异常

②取出删除元素

③从删除元素位置开始遍历到最后一个元素位置,将它们向前移动一位

④表长减1


2.代码


//顺序结构的删除操作
typedef int Status;
Status ListDelete(SqList* L, int n, ElemType* e)
{
  int k;                    //k为当前位置
  if (L->length == 0)       //若线性表为空,即空表,则返回错误
    return ERROR;
  if (n<1 || n>L->length)   //当删除元素小于1,大于当前长度,删除位置不正确返回错误
    return ERROR;
  *e = L->data[n - 1];      //e相当于回收站,将要删除的元素位置放到e中;*e表示取指针e所指地址存储的值;线性表中第n个值相当于数组data[n-1]
  if (n < L->length)        //若删除操作不是最后位置,执行以下操作,将要删除的位置后数据元素向前移动一位
  {
    for (k = n; k < L->length; k++)    //遍历从n索引位置到线性表长度的每个数据元素,将其全部向后移动一位
      L->data[k - 1] = L->data[k];
  }
  L->length--;             
  return OK;
}


五、总代码


//线性表顺序存储结构
#include <stdio.h>
#define MAXSIZE 20            //设定存储空间初始分配量
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
//顺序存储结构的建立
typedef int Status;
typedef int ElemType;
typedef struct
{
  ElemType data[MAXSIZE];   //数组存储数据元素,最大值为MAXSIZE
  int length;               //线性表当前长度
}SqList;
//顺序结构的获得元素操作
Status GetElem(SqList L, int n, ElemType* e)    //Status是函数类型,其值是函数结果状态代码,例OK等;
{                                               //SqList L为该线性表;int n为索引位置;ElemType*e为指针直接访问地址
  if (L.length == 0 || n<1 || n>L.length)     //线性表的长度不为0;线性表是从1访问的,而不是0;索引位置不能大于线性表的长度
    return ERROR;        //以上均返回错误
  *e = L.data[n-1];        //若满足以上条件,则将线性表L中的第n个位置元素值返回,即只要n的数值在数组下标范围内,就将数组第n-1下标的值返回
  return OK;
}
//顺序结构的插入操作
Status ListInsert(SqList* L, int n, ElemType e)
{
  int k;                          //k为当前位置
  if (L->length == MAXSIZE)       //当顺序线性表存储已满返回错误  
    return ERROR;    
  if (n<1 || n>L->length + 1)    //插入位置小于1、大于当前长度加一则返回错误
    return ERROR;
  if (n <= L->length)            //若插入位置不在线性表表尾,执行以下操作,将要插入的位置后数据元素向后移动一位
  {
    for (k = L->length - 1; k >= n - 1; k--)    //遍历从i索引位置到线性表长度的每个数据元素,将其全部向后移动一位
      L->data[k + 1] = L->data[k];           
  }
  //若插入位置在表尾,执行插入新元素操作
  L->data[n - 1] = e;             //[i-1]是因为顺序表位置-1=数组下标,数组从0开始,顺序表从1开始
  L->length++;
  return OK;
}
//顺序结构的删除操作
Status ListDelete(SqList* L, int n, ElemType* e)
{
  int k;               //k为当前位置
  if (L->length == 0)       //若线性表为空,即空表,则返回错误
    return ERROR;
  if (n<1 || n>L->length)   //当删除元素小于1,大于当前长度,删除位置不正确返回错误
    return ERROR;
  *e = L->data[n - 1];      //e相当于回收站,将要删除的元素位置放到e中;*e表示取指针e所指地址存储的值;线性表中第n个值相当于数组data[n-1]
  if (n < L->length)        //若删除操作不是最后位置,执行以下操作,将要删除的位置后数据元素向前移动一位
  {
    for (k = n; k < L->length; k++)    //遍历从n索引位置到线性表长度的每个数据元素,将其全部向后移动一位
      L->data[k - 1] = L->data[k];
  }
  L->length--;             
  return OK;
}


总结


以上就是本次的笔记内容,本文仅仅通过文字和代码简单介绍了顺序存储结构的各项操作,建议自己分析总结其各个操作并结合自己的编程能力选择编程语言再写一遍代码从而加深印象。


相关文章
|
14天前
|
存储 搜索推荐 算法
【数据结构】树型结构详解 + 堆的实现(c语言)(附源码)
本文介绍了树和二叉树的基本概念及结构,重点讲解了堆这一重要的数据结构。堆是一种特殊的完全二叉树,常用于实现优先队列和高效的排序算法(如堆排序)。文章详细描述了堆的性质、存储方式及其实现方法,包括插入、删除和取堆顶数据等操作的具体实现。通过这些内容,读者可以全面了解堆的原理和应用。
57 16
|
1月前
|
存储 Java
数据结构第二篇【关于java线性表(顺序表)的基本操作】
数据结构第二篇【关于java线性表(顺序表)的基本操作】
30 6
|
18天前
|
算法 安全 搜索推荐
2024重生之回溯数据结构与算法系列学习之王道第2.3章节之线性表精题汇总二(5)【无论是王道考研人还是IKUN都能包会的;不然别给我家鸽鸽丢脸好嘛?】
IKU达人之数据结构与算法系列学习×单双链表精题详解、数据结构、C++、排序算法、java 、动态规划 你个小黑子;这都学不会;能不能不要给我家鸽鸽丢脸啊~除了会黑我家鸽鸽还会干嘛?!!!
|
1月前
|
编译器 C语言 Python
C语言结构
C语言结构
15 0
|
1月前
探索顺序结构:栈的实现方式
探索顺序结构:栈的实现方式
|
1月前
|
C语言 C++
C语言 之 内存函数
C语言 之 内存函数
34 3
|
7天前
|
C语言
c语言调用的函数的声明
被调用的函数的声明: 一个函数调用另一个函数需具备的条件: 首先被调用的函数必须是已经存在的函数,即头文件中存在或已经定义过; 如果使用库函数,一般应该在本文件开头用#include命令将调用有关库函数时在所需要用到的信息“包含”到本文件中。.h文件是头文件所用的后缀。 如果使用用户自己定义的函数,而且该函数与使用它的函数在同一个文件中,一般还应该在主调函数中对被调用的函数做声明。 如果被调用的函数定义出现在主调函数之前可以不必声明。 如果已在所有函数定义之前,在函数的外部已做了函数声明,则在各个主调函数中不必多所调用的函数在做声明
23 6
|
27天前
|
存储 缓存 C语言
【c语言】简单的算术操作符、输入输出函数
本文介绍了C语言中的算术操作符、赋值操作符、单目操作符以及输入输出函数 `printf` 和 `scanf` 的基本用法。算术操作符包括加、减、乘、除和求余,其中除法和求余运算有特殊规则。赋值操作符用于给变量赋值,并支持复合赋值。单目操作符包括自增自减、正负号和强制类型转换。输入输出函数 `printf` 和 `scanf` 用于格式化输入和输出,支持多种占位符和格式控制。通过示例代码详细解释了这些操作符和函数的使用方法。
34 10
|
20天前
|
存储 算法 程序员
C语言:库函数
C语言的库函数是预定义的函数,用于执行常见的编程任务,如输入输出、字符串处理、数学运算等。使用库函数可以简化编程工作,提高开发效率。C标准库提供了丰富的函数,满足各种需求。
|
26天前
|
机器学习/深度学习 C语言
【c语言】一篇文章搞懂函数递归
本文详细介绍了函数递归的概念、思想及其限制条件,并通过求阶乘、打印整数每一位和求斐波那契数等实例,展示了递归的应用。递归的核心在于将大问题分解为小问题,但需注意递归可能导致效率低下和栈溢出的问题。文章最后总结了递归的优缺点,提醒读者在实际编程中合理使用递归。
53 7