首页 > 其他分享 >【数据结构】顺序表

【数据结构】顺序表

时间:2023-03-31 20:03:59浏览次数:43  
标签:顺序 线性表 int ElemType elem length 数据结构

线性表的定义和特点

线性表是具有相同特性的数据元素的一个有限序列 $$ (a_1,a_2,…a_(i-1),a_i,a_(i+1),…,a_n)$$ image.png 线性表(Linear List): 由n(n>=0)个数据元素(结点) $$ a_1,a_2,…,a_n$$ 组成的有限序列 其中数据元素的个数n定义为表的长度 当n为0时称为空表 将非空的线性表记作: $$ a_1,a_2,…,a_n$$ 这里的数据元素 $$ a_i(1<=i<=n)$$ 只是一个抽象的符号,其具体含义在不同的情况下可以不同。

线性表的例子

image.png 同一线性表中的元素必定具有相同特性,数据元素间的关系是线性关系

线性表的逻辑特征

image.png 线性表是一种典型的线性结构

案例引入

image.png image.png image.png image.png image.png image.png 线性表A=((7,0),(3,1),(9,8),(5,17)) 线性表B=((8,1),(22,7),(-9,8)) 创建一个新的数组c 分头从头遍历比较a和b的每一项 指数相同,对应系数相加,若其和不为0,则在c中增加一个新项 指数不相同,则将指数较小的项复制到c中 一个多项式已遍历完毕时,将另一个剩余项一次复制到c中即可 image.png image.png 需要的功能 查找 插入 删除 修改 排序 计数 图书表抽象为线性表,表中每本图书抽象线性表中数据元素 image.png 总结 线性表中数据元素的类型可以为简单类型,也可以为复杂类型。 许多实际应用问题所涉及的基本操作有很大相似性,不应为每个具体应用单独编一个程序。 从具体应用中抽象出共性的逻辑结构和基本操作(抽象数据类型),然后实现其存储结构和基本操作。

线性表的类型定义

image.png

基本操作(一)

image.png

基本操作(二)

image.png

基本操作(三)

image.png

基本操作(四)

image.png

基本操作(五)

image.png

基本操作(六)

image.png image.png

线性表的顺序表示和实现

线性表的顺序表示又称为顺序存储结构或顺序映像

image.png 例如:线性表(1,2,3,4,5,6)的存储结构: image.png

顺序表中元素存储位置的计算

image.png image.png image.png

顺序表的顺序存储表示

顺序表元素的特点:地址连续、依次存放、随即存取、类型相同,类似于数组,可用一维数组表示顺序表。 线性表长度可变,而数组长度不可动态定义 解决办法:用一变量表示顺序表的长度属性

#define LIST_INIT_SIZE 100 //线性表存储空间的初始分配量
#defien LISTINCREMENT 10//线性表存储空间的分配增量
typedef struct
{
	ElemType *elem;//存储空间的基地址

	int length;//当前长度
	int listsize;//当前分配的存储容量
}SqList;

顺序表的初始化

顺序表的初始化操作就是为顺序表分配一个预定义大小的数组空间,并将线性表的当前长度设为0

Status InitList_Sq(SqList &L)
{
	L.elem=(ElemType *)malloc(LIST_INIT_SIZE*sizeof(ElemType));
	if(!L.elem) exit(OVERFLOW);//存储分配失败
	L.length=0;
	L.listsize=LIST_INIT_SIZE;
	return OK;
}

image.png image.png

类C语言有关操作

image.png image.png image.png image.png 传地址方式————指针变量作参数 传地址方式————数组名作参数 传递的是数组的首地址,对形参数组所做的任何改变都将反映到实参数组中 传地址方式————引用类型作参数(C++的语法) 引用就是用来给一个对象提供一个替代的名字 引用类型作形参的三点说明 (1)传递引用给函数与传递指针的效果是一样的,形参变化实参也发生变化。 (2)引用类型作形参,在内存中并没有产生实参的副本,它直接对实参操作;而一般变量作参数,形参与实参就占用不同的存储单元,所以形参变量的值是实参变量的副本。因此,当参数传递的数据量较大时,用引用比一般变量传递参数的时间和空间效率都好。 (3)指针参数虽然也能达到与使用引用的效果,但在被调函数中需要重复使用“指针变量名”的形式进行运算,这很容易产生错误且程序的阅读性较差;另一方面,在主调函数的调用点处,必须用变量的地址作为实参。

顺序表的插入

image.png image.png 算法思想 1.判断插入位置是否合法,数组元素是否在1~n+1,下标是否在0~n 2.判断顺序表的存储空间是否已满,若已满返回ERROR 3.将第n至第i位的元素依次向后移动一个位置,空出第i个位置 4.将要插入的新元素e放入第i个位置。 5.表长加1,插入成功返回OK 算法:

Status ListInsert_Sq(Sqlist &L,int i,ElemType e)
{//在顺序表L中的第i个元素之前插入元素e
//判断插入位置的合法性
if(i<1||i>length+1) return ERROR;
//判断顺序表的存储空间是否已满,已满则扩容
if(L.length>=L.listsize)//当前存储空间已满,增加分配
{
newbase=(ElemType *)realloc(L.elem,(L.listsize+LISTINCREMENT)*sizeof(ElemType))
if(!newbase) exit(OVERFLOW);//存储分配失败
L.elem=newbase;//分配新基址
L.listsize+=LISTINCREMENT;//增加存储容量
}
q=&(L.elem[i-1]);//插入位置
for(&(L.elem[length-1]);p>=q;p--)
*(p+1)=*p;//插入位置及之后的元素后移
*q=e;//插入e
++length;//表长加1
return OK;
}

顺序表的删除

image.png image.png

Status ListDelete_Sq(SqList* L, int i, ElemType* e)
{
	//判断删除位置i是否合法
	if ((i < 1) || (i > L->length))
		return ERROR;
	p = &(L.elem[i - 1]);//p为被删除元素的位置
	e = *p;//被删除元素的值赋给e
	q = L.elem + L->length - 1;//表尾元素的位置
	for (++p; p <= q; ++p)//被删除元素之后的元素左移
		*(p - 1) = *p;
	--L.length;
	return OK;

顺序表的查找

image.png

算法实现

int LocateElem_Sq(SqList L,ElemType e,Status(*compare)(ElemType,ElemType))
{
//在顺序线性表中查找第一个值与e满足compare()的元素的位序
//若找到,则返回其在L中的位序,否则返回0
i;//i的初值为第一个元素的位序
p=L.elem//p的初值为第一个元素的存储位置
while(i<=L.length&&!(*compare)(*p++,e))
++i;
if(i<=L.length)
return i;
else
return 0;
}

补充:函数指针

image.png

插入、删除、查找C语言实现

#define LIST_INIT_SIZE 100
#define LISTINCREMENT 10
#define TRUE 1
#define ERROR 0
#define FALSE 0
#define OVERFLOW -2
#define OK 1
typedef int Status;
typedef int ElemType;
#include<stdio.h>
#include<stdlib.h>
typedef struct
{
	ElemType* elem;
	int length;
	int listsize;
}SqList;
Status InitList_Sq(SqList *L)
{
	L->elem = (ElemType*)malloc(sizeof(ElemType));
	if (!L->elem)
		exit(OVERFLOW);
	L->length = 0;
	L->listsize = LIST_INIT_SIZE;
	int n;
	printf("输入顺序表的长度:\n");
	scanf_s("%d", &n);
	printf("输入数据:\n");
	for (int i = 0; i < n; i++)
	{
		scanf_s("%d", &L->elem[i]);
		L->length++;
	}
	printf("顺序表为:\n");
	for (int i = 0; i < L->length; i++)
	{
		printf("%d ", L->elem[i]);
	}
	printf("\n");
	return OK;
}
Status ListInsert_Sq(SqList* L, int i, ElemType e)
{
	ElemType* p=NULL,* q=NULL;
	
	if (i<1 || i>L->length + 1)
		return ERROR;
	if (L->length >= L->listsize)
	{
		ElemType* newbase;
		newbase = (ElemType*)realloc(L->elem, (L->listsize + LISTINCREMENT) * sizeof(ElemType));
		if (!newbase)
			exit(OVERFLOW);
		L->elem = newbase;
		L->listsize += LISTINCREMENT;
	}
	q = &(L->elem[i - 1]);
	for (p = &(L->elem[L->length - 1]); p >= q; p--)
		*(p + 1) = *p;
	*q = e;
	++L->length;
	return OK;
}
Status ListDelete_Sq(SqList* L, int i, ElemType* e)
{
	ElemType* p, * q;
	if (i<1 || i>L->length)
		return ERROR;
	p = &(L->elem[i - 1]);
	e = *p;
	q = L->elem + L->length - 1;
	for (++p; p <= q; ++p)
		*(p - 1) = *p;
	--L->length;
	return OK;
}
int LocateElem_Sq(SqList L, ElemType  e,Status(*compare)(ElemType, ElemType))
{
	int i = 1;
	ElemType* p = L.elem;
	while (i <= L.length && !(*compare)(*p++, e))
		++i;
	if (i <= L.length)
		return i;
	else
		return 0;
}
Status fun2(ElemType x, ElemType e)
{
	if (x == e)
		return 1;
	else
		return 0;
}
int main()
{
	SqList L;
	InitList_Sq(&L);
	int ipos;
	ElemType e;
	printf("\n请输入插入元素及插入位置:\n");
	scanf_s("%d %d", &e, &ipos);
	ListInsert_Sq(&L,ipos,e);
	printf("\n插入后的顺序表为:\n");
	for (int i= 0; i< L.length; i++)
		printf("%d ", L.elem[i]);
	printf("\n请输入要删除元素的位置:\n");
	int delpos;
	scanf_s("%d", &delpos);
	printf("删除后的顺序表为:\n");
	ListDelete_Sq(&L, delpos, &e);
	for (int i = 0; i < L.length; i++)
		printf("%d ", L.elem[i]);
	printf("\n请输入要查找的元素:\n");
	int locate;
	scanf_s("%d", &locate);
	int i=LocateElem_Sq(L, locate, fun2);
	printf("查找元素位序为%d\n", i);
	return 0;
}

标签:顺序,线性表,int,ElemType,elem,length,数据结构
From: https://blog.51cto.com/heliotopekxy/6162247

相关文章

  • 2023-03-31-顺序队列SqQueue的基本操作
    //基本顺序队列#include<stdio.h>#include<stdbool.h>#defineMAXSIZE50typedefstruct{intdata[MAXSIZE];intfront,rear;}SqQueue;voidinitSqQueue(SqQueue*Q)//进行队的初始化{Q->front=0;Q->rear=0;}boolisEmpty(SqQueue......
  • 力扣---剑指 Offer 21. 调整数组顺序使奇数位于偶数前面
    输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有奇数在数组的前半部分,所有偶数在数组的后半部分。 示例:输入:nums= [1,2,3,4]输出:[1,3,2,4]注:[3,1,2,4]也是正确的答案之一。 提示:0<=nums.length<=500000<=nums[i]<=10000来源:力扣(LeetCode)链接:ht......
  • 第8章 数据结构算法专题二
    线索二叉树与哈夫曼树线索二叉树线索二叉树的概念采用某种方法遍历二叉树的结果是一个结点的线性序列。修改空链域改为存放指向结点的前驱和后继结点的地址。这样的指向该线性序列中的”前驱“和”后继“的指针,称作线索(thread)。创建线索的过程称为线索化。线索化的二叉......
  • 【LabVIEW】程序结构-顺序结构
    LabVIEW学习笔记汇总链接【LabVIEW】小白入门学习笔记-汇总目录1.基本使用2.加法小程序图示3.labview的编程特点4.平铺式顺序结构5.整理程序6.快捷键1.基本使用返回顶部目录END......
  • 跟着查老四学Python Day 3:数据结构与函数
    老猫:请您扮演一个python讲师,帮助一个没有代码经验的人自学python,以下是此前你设置的学习计划制定学习计划:将学习过程分为四个阶段,每个阶段关注不同的内容。第一周:掌握Python基础语法、数据类型、控制结构等。同时,学会如何在本地搭建Python开发环境。第二周:学习函数、模块、文件操......
  • C语言的函数原型(执行顺序问题)
    以下面一段代码为参考:像这样把sum()写在上面是因为:C语言的编译器是从上往下执行代码的,当他看到sum(1,10);sum(1,100);时,要知道sum()是个什么东西,也就是sum()要几个参......
  • 力扣26.删除有序数组中的重复项【顺序表】
    ......
  • 循环队列(顺序)的实现:舞伴问题
    一、问题引入舞伴配对问题:假设在周末舞会上,男士们和女士们进入舞厅时,各自排成一队。跳舞开始时,依次从男队和女队的队头各出一人配成舞伴。若两队初始人数不相同,则较长的......
  • 【数据结构与算法】算法学习大纲
    前言排序算法查找算法二叉树算法图算法分治算法回溯算法贪心算法动态规划算法......
  • sql 执行顺序
    https://mp.weixin.qq.com/s?__biz=MjM5NzEyMzg4MA==&mid=2649468111&idx=6&sn=a87a37d675039f92dfd1df76a65c8a5f&chksm=bec1ce8889b6479ef314f7ea1aa4204eb9b1d4037847bf......