【C语言】超详细讲解顺序表的各种操作

目录

1.顺序表的定义

2.顺序表的特点

3.顺序表的定义

4.顺序表的常用操作的实现

4.1 顺序表的初始化

4.2 顺序表的建立

4.3 查找操作

1. 按位置查找

2.按值查找操作

4.4 插入操作

4.5 删除操作

4.6 输出表中的元素

5.顺序表的操作的完整程序代码

总结:


1.顺序表的定义

数据结构在内存中的表示通常有两种形式,一种是顺序存储,另一种是链式存储。线性表的顺序存储是指用一组地址连续的存储单元依次存储线性表的数据元素,我们把这种存储形式存储的线性表称为顺序表。

2.顺序表的特点

1.顺序表的逻辑结构和物理结构是一致的。

2.顺序表中任意一个数据元素都可以随机存取,所以顺序表是一种随机存取的存储结构。

3.顺序表的定义

#define MAXLEN 100 //定义MAXLEN
typedef int DataType;
typedef struct
{
	DataType data[MAXLEN];
	int Length;
}SeqList;

定义MAXLEN为100,表示顺序表最大的存储空间   利用宏方便对顺序表的大小进行修改

利用typedef将DataType定义成int类型的数据,如果顺序表存放的数据要修改成其他类型的,可以直接 利用typedef将DataType修改成我们想要的数据类型就可以了,这也方便对顺序表进行修改

顺序表SeqList是一个结构体类型,它有两个成员组成,data表示存储顺序表的数组,其长度MAXLEN表示顺序表中元素数目的最大值,Length表示顺序表的实际长度

注意:C语言的数组下标从0开始

4.顺序表的常用操作的实现

4.1 顺序表的初始化

顺序表的初始化就是要建立一个空表L,将L作为指针参数,将表L的实际长度设置为0  代码如下:

void InitList(SeqList* L)
{
	L->Length = 0;
}

4.2 顺序表的建立

对于初始化好的顺序表,我们要从键盘输入n个数,将这些数存在顺序表中,修改表场后建立顺序表L,代码如下:

void CreateList(SeqList* L,int n)
{
	int i = 0;
	for (i = 0; i < n; i++)
	{
		scanf("%d", &L->data[i]);
	}
	L->Length = i;
}

4.3 查找操作

顺序表的查找分为按值和按序号查找,下面开始介绍这两种方法的实现,大家可以根据需求进行使用。

1. 按位置查找

按位置查找就是查找第i个位置的元素的值,在i无效时返回出错,有效时返回成功,并用指针x所指的变量传回第i个元素的值 代码如下:

int GetElem(SeqList* L, int i, DataType* x)
{
	if (i<1 || i>L->Length)
	{
		return 0;
	}
	else
	{
		*x = L->data[i - 1];
		return 1;
	}
}

注意:在查找的时候要先判断i是不是合法的(是否为负数是否超过数组的最大下标值等),以及要考虑到i不是合法的数据时,要怎么处理。

2.按值查找操作

按值查找是指在顺序表中,查找与给指定值x相等的数据元素所在位置的下标。

算法的设计思想:首先令i等于0,然后从表的第一个位置开始逐个与给定值x进行判断,当i小于表长且与该位置的元素值与x的值不相等时i自加,直到循环结束为止。若i的值大于表长就是查找失败,就返回0;若查找成功就返回其位置,就是i+1(数组下标从0开始所以要加1)

代码如下:

int Locate(SeqList* L, DataType x)
{
    int i = 0;
    while (i < L->Length && L->data[i] != x)
    {
        i++;
    }
    if (i >= L->Length)
    {
        return 0;
    }
    else
    {
        return i + 1;
    }
}

4.4 插入操作

线性表的插入是指在表的第i个位置上(因为C语言的下标是从0开始的,所以插入位置下标为i-1)插入一个值为x的元素,插入后使原表长增加1,称为表长度为n+1的表。

顺序表的插入节点的步骤如下

1.将数组下标从第i个位置一直到最后一个位置的结点全部往后移,让出第i个位置

2.将新节点x插入第i个位置

3.修改表长

顺序表插入元素的过程如图所示:

 要注意一下几点问题

1.首先要检查顺序表是否已满,在表满的情况下不能插入,否则会产生溢出错误

2.检查插入位置的有效性,插入的有效范围是1<=i<=n+1(n是原来的表长)

3.注意数据移动的方向,必须从原线性表的最后一个结点开始往后移动

代码如下:

int InsElem(SeqList* L, int i, DataType x)
{
	int j = 0;
	if (L->Length >= MAXLEN)
	{
		printf("顺序表已满!");
		return -1;
	}
	if (i<1 || i>L->Length+1)
	{
		printf("插入位置出错");
		return 0;
	}
	if (i == L->Length + 1) //插入位置为表尾时
	{
		L->data[i - 1] = x;
		L->Length++;
		return 1;
	}
	for (j = L->Length - 1; j >= i - 1; j--)//插入位置为表中时
	{
		L->data[j + 1] = L->data[j];
	}
	L->data[i - 1] = x;
	L->Length++;
	return 1;
}

顺序表的插入操作大约需要移动一半的数据元素,时间复杂度为O(n).

4.5 删除操作

线性表的删除操作是指将第i个元素(C语言数组下标从0开始,删除位置下标为i-1)从顺序表中去掉,删除后顺序表长度-1

顺序表删除结点的步骤如下

1.将要删除的元素赋值给指针x所指的变量

2.将第i+1到最后一个结点依次顺序向前移动

3.顺序表长度-1,删除成功,并返回

删除操作过程图如下:

代码如下:

int DelElem(SeqList* L, int i, DataType* x)
{
	int j = 0;
	if (L->Length == 0)
	{
		printf("顺序表为空");
		return 0;
	}
	if (i<1 || i>L->Length)
	{
		printf("不存在第i个元素");
		return 0;
	}
	*x = L->data[i - 1];
	for (j = i; j < L->Length; j++)
	{
		L->data[j - 1] = L->data[j];
	}
	L->Length--;
	return 1;
}

删除操作的平均每次大概需要移动一半的元素,时间复杂度为O(n).

4.6 输出表中的元素

输出顺序表的元素,就是遍历一次一维数组,然后把它打印出来  代码如下:

void DispList(SeqList* L)
{
	int i = 0;
	for (i = 0; i < L->Length; i++)
	{
		printf("%d ", L->data[i]);
	}
}

5.顺序表的操作的完整程序代码

上面是顺序表的基本操作函数,为了运行相关代码,还要设计好主函数,运用之前学过的循环和开关语句,实现反复实行各种操作的功能。为了方便可以写一个菜单显示各项功能选项。

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#define MAXLEN 100 //定义MAXLEN
typedef int DataType;
typedef struct
{
    DataType data[MAXLEN];
    int Length;
}SeqList;


void InitList(SeqList* L)
{
    L->Length = 0;
}
void CreateList(SeqList* L,int n)
{
    int i = 0;
    for (i = 0; i < n; i++)
    {
        scanf("%d", &L->data[i]);
    }
    L->Length = i;
}

int GetElem(SeqList* L, int i, DataType* x)
{
    if (i<1 || i>L->Length)
    {
        return 0;
    }
    else
    {
        *x = L->data[i - 1];
        return 1;
    }
}
int Locate(SeqList* L, DataType x)
{
    int i = 0;
    while (i < L->Length && L->data[i] != x)
    {
        i++;
    }
    if (i >= L->Length)
    {
        return 0;
    }
    else
    {
        return i + 1;
    }
}

int InsElem(SeqList* L, int i, DataType x)
{
    int j = 0;
    if (L->Length >= MAXLEN)
    {
        printf("顺序表已满!");
        return -1;
    }
    if (i<1 || i>L->Length+1)
    {
        printf("插入位置出错");
        return 0;
    }
    if (i == L->Length + 1) //插入位置为表尾时
    {
        L->data[i - 1] = x;
        L->Length++;
        return 1;
    }
    for (j = L->Length - 1; j >= i - 1; j--)//插入位置为表中时
    {
        L->data[j + 1] = L->data[j];
    }
    L->data[i - 1] = x;
    L->Length++;
    return 1;
}

int DelElem(SeqList* L, int i, DataType* x)
{
    int j = 0;
    if (L->Length == 0)
    {
        printf("顺序表为空");
        return 0;
    }
    if (i<1 || i>L->Length)
    {
        printf("不存在第i个元素");
        return 0;
    }
    *x = L->data[i - 1];
    for (j = i; j < L->Length; j++)
    {
        L->data[j - 1] = L->data[j];
    }
    L->Length--;
    return 1;
}
void DispList(SeqList* L)
{
    int i = 0;
    for (i = 0; i < L->Length; i++)
    {
        printf("%d ", L->data[i]);
    }
}
void  Menu()
{
    printf("                  顺序表的各种操作\n");
    printf("==================================================\n");
    printf("|              1——建立顺序表                   |\n");
    printf("|              2——插入元素                     |\n");
    printf("|              3——删除元素                     |\n");
    printf("|              4——按位置查找元素               |\n");
    printf("|              5——按元素值查找其在表中位置     |\n");
    printf("|              6——求顺序表的长度               |\n");
    printf("|              0——返回                         |\n");
    printf("==================================================\n");
    printf("请输入菜单号(0-6):");
}
int main()
{
    SeqList L;
    DataType x;
    int n, i, loc;
    char  ch1, ch2, a;
    ch1 = 'y';
    while (ch1 == 'y' || ch1 == 'Y')
    {
        Menu();
        scanf("%c", &ch2);
        getchar();
        switch (ch2)
        {
            case  '1':
                InitList(&L);
                printf("请输入建立线性表的个数:");
                scanf("%d", &n);
                CreateList(&L, n);
                printf("建立的线性表为:");
                DispList(&L);
                break;
            case  '2':
                printf("请输入要插入的位置:");
                scanf("%d", &i);
                printf("请输入要插入的元素值:");
                scanf("%d", &x);
                if (InsElem(&L, i, x))
                {
                    printf("已成功在第%d的位置上插入%d,插入后的线性表为:\n", i, x);
                    DispList(&L);
                }
                else
                    printf("输入插入的参数错误!");
                break;
            case  '3':
                printf("请输入要删除元素的位置:");
                scanf("%d", &i);
                if (DelElem(&L, i, &x))
                {
                    printf("已成功在第%d的位置上删除%d,删除后的线性表为:\n", i, x);
                    DispList(&L);
                }
                else
                    printf("\n输入删除的参数错误!");
                break;
            case  '4':
                printf("请输入要查看表中元素位置(从1开始):");
                scanf("%d", &i);
                if (GetElem(&L, i, &x))
                    printf("当前线性表第%d个元素的值为:%d", i, x);
                else
                    printf("输入的位置错误!");
                break;
            case  '5':
                printf("请输入要查找的元素值为:");
                scanf("%d", &x);
                loc = Locate(&L, x);
                if (loc)
                    printf("查找元素值为%d的位置为:%d", x, loc);
                else
                    printf("该表中无此元素!");
                break;
            case  '6':
                printf("当前线性表的长度为:%d", L.Length);
                break;
            case  '0':
                ch1 = 'n';
                break;
            default:
                printf("输入有误,请输入0-4进行选择!");
        }
        if (ch2 != '0')
        {
            printf("\n按回车键继续,按任意键返回主菜单!\n");
            a = getchar();
            if (a != '\xA')
            {
                getchar(); ch1 = 'n';
            }
        }
    }
}

代码执行效果如图所示:

图片大小有限就不功能就不一一列举出来了。感兴趣的可以自己去试着写一下

总结:

顺序存储结构的优点是节省存储空间,顺序表结构简单便于随机访问表中任意的数据元素;缺点是插入和删除操作需要移动大量的数据元素,特别是当顺序表的而数据元素含有复杂信息是,移动工作量大、程序执行效率低。另外,顺序表的存储空间是连续且预先分配,若顺序表的长度变化较大时,难以预估顺序表的长度,可能会造成空间的浪费,也可能会导致数据溢出。(水平有限,若有错误,还请指正,谢谢!!)

  • 30
    点赞
  • 160
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 11
    评论
数据结构C语言版)》是严蔚敏编著的一本经典教材,主要介绍了数据结构的基本概念、常用算法以及C语言中的实现。 该书共分为9个章节,具体目录如下: 第一章:绪论 本章主要介绍了数据结构的基本概念、逻辑结构与存储结构的关系以及算法复杂度等内容,为后续章节的学习打下了基础。 第二章:线性表 本章讲解了线性表的基本概念及实现方式,包括顺序表和链表等。详细介绍了线性表操作的各种算法和实现方法,并提供相应的C语言代码。 第三章:栈与队列 本章介绍了栈和队列的基本概念、特性以及实现方式。分别介绍了顺序栈、链栈、顺序队列和链队列等的操作和实现方法。 第四章:串 本章讲述了串的概念和各种操作,包括模式匹配、子串查找等。给出了串操作C语言代码实现。 第五章:数组与广义表 本章介绍了数组和广义表的概念、特性以及相关操作,包括数组的插入、删除、查找等操作以及广义表的遍历等。 第六章:树与二叉树 本章详细介绍了树和二叉树的基本概念以及常用的算法和遍历方式,包括树的构建、遍历、二叉树的插入、删除、查找等操作。 第七章:图 本章讲解了图的基本概念、表示方法以及常见的图算法,如深度优先搜索、广度优先搜索等。还介绍了图的最小生成树、最短路径等算法。 第八章:查找 本章围绕查找问题展开,包括静态查找和动态查找两大类,分别介绍了线性表、树和哈希表等不同的查找方法。 第九章:排序 本章介绍了常见的排序算法,包括插入排序、选择排序、归并排序、快速排序等。详细介绍了各种排序算法的原理和实现方式。 《数据结构C语言版)》作为一本经典的教材,具有详细的内容和清晰的讲解,反映了数据结构与算法的基本理论和实践应用。该书适合计算机专业学生、编程爱好者以及从事软件开发等相关工作的人员阅读和学习。
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

比奇堡的天没有云

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值