考研复习之数据结构笔记(三)线性表(上)(包含基本概念、顺序表及其部分相关实现、线性表的链式表示见(下))

本文详细介绍了线性表的定义及其逻辑特性,包括线性表的基本操作如初始化、查找、插入和删除。重点讲解了线性表的顺序存储结构,通过C语言实现了顺序表的创建、打印、扩容及查找、插入、删除等操作,并分析了顺序表的优缺点,强调了其随机存取和存储密度高的特点,但也指出插入删除效率低和扩容成本高的问题。
摘要由CSDN通过智能技术生成

目录

一、线性表的定义、基本操作

1.1 线性表相关定义

(1)基本概念:

(2)相关特性:

1.2 线性表的基本操作

二、线性表的顺序表示

2.1 顺序表相关定义

(1)基本概念

2.2 顺序表C语言简单实现

1.相关定义实现

2.顺序表的初始化、打印、扩容

3.顺序表的查找

4.顺序表的插入

5.顺序表的删除

 2.3 顺序表的优缺点

2.3.1 优点:

2.3.2 缺点:


一、线性表的定义、基本操作

1.1 线性表相关定义

(1)基本概念:

        线性表是具有相同数据类型的n(n > 0)个数据元素的有限序列,其中n为表长,当n = 0 时线性表是一个空表。

        线性表中有唯一的“第一个”数据元素(又称表头元素)以及唯一的“最后一个”数据元素(又称表尾元素)。除第一个元素外,每个元素有且仅有一个直接前驱。除最后一个元素外,每个元素 有且仅有一个直接后继。以上就是线性表的逻辑特性。

图1.1-1 经典线性表实例(顺序表实现)

 图1.1-2 经典线性表实例(循环链表实现)

(2)相关特性:

线性表的特点如下:

表中元素的个数有限。(存在唯一一个被称为第一个和最后一个的元素)

表中元素具有逻辑上的顺序性。(有先后顺序)

表中元素都是数据元素,每个元素都是单个元素。

表中元素的数据类型都相同,这意味着每个元素占有相同大小的存储空间。(同构)

      •表中元素具有抽象性,即仅讨论元素间的逻辑关系,而不考虑元素究竟表示什么内容。

简单来说就是:有限、序列、同构

注意:线性表是一种逻辑结构,表示元素之间一对一的协构,两者属于不同层面的概念。

1.2 线性表的基本操作

线性表的主要操作如下(在最后会有部分相关实现):

InitList( &L );           初始化线性表,构造空的线性表L

DestroyList( &L );    销毁已有线性表L。

ListEmpty( L );         判断线性表L是否为空,返回true/false。

ListLength( L );        求线性表L中的元素个数。

ClearList( &L );        将已有线性表L置为空表。

GetElem( L, i, &e );     用e返回线性表L中第i个元素值。

LocateElem( L, e );      在线性表L中查找元素e的位置。

PriorElem( L, cur_e, &pre_e );     用pre_e返回线性表L中元素cur_e的前驱。

NextElem( L, cur_e, &next_e );    用next_e返回线性表L中元素cur_e的后继。

ListInsert( &L, i, e );     在线性表L第i个元素之前插入e。

ListDelete(&L, i, &e);    删除线性表L中第i个元素

PutElem( &L, i, &e );    将线性表L中第i个元素赋值为e

二、线性表的顺序表示

2.1 顺序表相关定义

(1)基本概念

        线性表的顺序存储又称顺序表。它是用一组地址连续的存储单元依次存储线性表中的数据元素,从而使得逻辑上相邻的两个元素在物理位置上也相邻特点是表中元素的逻辑顺序与其物理顺序相同。(数组就是一种典型的顺序表)

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

注意:线性表中元素的位序是从1开始的,而数组中元素的下标是从0开始的。线性表是1个元素存储在线性表的起始位置, 第i个元素的存储位置后面紧接着存储的是第i+1个元素,第i个元素的位序是i。

2.2 顺序表C语言简单实现

1.相关定义实现

假定线性表的元素类型为ElemType,则线性表的顺序存储类型描述为

typedef int SLDataType;
typedef struct SeqList
{
	SLDataType* num;//存放数据
	int capacity;//记录容量
	int size;//记录存储数据的个数
}SL;

        一维数组可以是静态分配的,也可以是动态分配的。在静态分配时,由于数组的大小和空间 事先已经固定,一旦空间占满,再加入新的数据就会产生溢出,进而导致程序崩溃。

        而在动态分配时,存储数组的空间是在程序执行过程中通过动态存储分配语句分配的,一旦数据空间占满,就另外开辟一块更大的存储空间,用以替换原来的存储空间,从而达到扩充存储数组空间的目的,而不需要为线性表一次性地划分所有空间。

2.顺序表的初始化、打印、扩容

//顺序表的初始化
//顺序表的初始化 相对简单,我们定义了有一个顺序表的指针、 容量、数据的个数
void SeqListInit(SL* pc)
{
    pc->num = NULL;
    pc->capacity = pc->size = 0;
}



//顺序表的打印
void SeqListPrint(SL* pc)
{
    assert(pc);
    for (int i = 0; i < pc->size; ++i)
    {
    	printf("%d ", pc->num[i]);
    }
    printf("\n");
}


//扩容函数
//顺序表在存储数据时,需要空间的使用,我们这里采用的是动态存储,
//我们要保证每次存放数据时顺序表的容量是足够的,就需要动态开辟空间
void SeqListCheckCapacity(SL* pc)
{
    if (pc->size == pc->capacity)
    {
        //当我们第一次插入数据时,顺序表的容量和数据个数都是0,
        //可以采用三目操作符,先给它一块空间
    	int newcapacity = pc->size == 0 ? 4 : pc->capacity * 2;
    	SLDataType* tmp = (SLDataType*)realloc(pc->num, newcapacity * sizeof(SLDataType));
    	if (tmp == NULL)
    	{
    		printf("realloc fail\n");
    		exit(-1);
    	}
    	pc->num = tmp;
    	pc->capacity = newcapacity;
    }
}

注意:动态分配并不是链式存储,它同样属于顺序存储结构,物理结构没有变化,依然是随 机存取方式,只是分配的空间大小可以在运行时动态决定。

补充:顺序表为了避免频繁扩容,一般扩容到原本的两倍。

3.顺序表的查找

 图2.1-1 顺序表查找相关流程

//查找函数
int SeqListFind(SL* pc, SLDataType x)
{
	assert(pc);
	for (int i = 0; i < pc->size; ++i)
	{
		if (pc->num[i] == x)
		{
			return i;
		}
	}
	return -1;
}

4.顺序表的插入

   图2.1-2 顺序表查找相关流程

//顺序表在pos位置插入指定x
void SeqListInsert(SL* pc, int pos, SLDataType x)
{
	assert(pc);
	assert(pos >= 0 && pos <= pc->size);
	SeqListCheckCapacity(pc);//检查是否需要扩容
	int end = pc->size - 1;
	while (end >= pos)
	{
		pc->num[end + 1] = pc->num[end];
		end--;
	}
	pc->num[pos] = x;
	pc->size++;
}

5.顺序表的删除

图2.1-3 顺序表删除相关流程

//顺序表删除pos位置的值
void SeqListErase(SL* pc, int pos)
{
	assert(pc);
	assert(pos >= 0 && pos < pc->size);
	int begin = pos + 1;
	while (begin < pc->size)
	{
		pc->num[begin - 1] = pc->num[begin];
		begin++;
	}
	pc->size--;
}

 2.3 顺序表的优缺点

2.3.1 优点:

1.可随机存取和访问任一元素

顺序表最主要的特点是随机访问,即通过首地址和元素序号可在时间0(1)内找到指定的元素。

2.存储空间使用紧凑

顺序表的存储密度高,每个结点只存储数据元素。

3.逻辑相邻,物理相邻

顺序表逻辑上相邻的元素物理上也相邻。

2.3.2 缺点:

1.要求数据从开始位置储存,插入、删除操作需要移动大量的元素,效率较低。

2.空间不足时需要扩容,异地扩容时代价过高。(不了解异地扩容可以去了解一下malloc函数的工作方式)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

D了一天bug忘了编译

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

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

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

打赏作者

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

抵扣说明:

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

余额充值