1.顺序表
1 线性表
线性表(linear list) 是数据结构中最简单,同时也是最常用的一种结构
线性表是由相同数据类型的n个元素 a0, a1, a2…an-1 组成的有序序列,一个数据元素可以右若干个数据项组成。用L命名线性表 L = (a0, a1, a2…an-1) 其中,a0是唯一的"第一个"数据元素,又称为表头元素;an-1是唯一的"最后一个"数据元素,又称为表尾元素。
1.1 线性表的分类
1. 顺序表
顺序表是在计算机内存中以数组形式保存的线性表,是指用一组地址连续的储存单元依次储存数据元素的线性结构
2. 链表
1.2 线性表的性质
- 线性表受储存空间限制,线性表不能无限存储
- 从逻辑上看,线性表中的元素是按顺序依次排列的
- 线性表受空间限制,元素个数是有限的。
- 线性表中所有元素的数据类型都是相同的
- 线性表中的元素具有逻辑上的顺序性.
2 顺序表
线性表是逻辑结构,表示元素之间一对一的相邻关系;而顺序表是存储结构,是指用一组地址连续的存储单元,依次存储线性表中的数据元素,从而使得逻辑上相邻的两个元素在物理位置也相邻。
设顺序表的第一个元素a0的存储地址为Loc(a0),每个元素占d个存储空间,
则第i个元素的地址为Loc(ai-1) = Loc(a0)+(i-1) × d
顺序表通常用一维数组实现,一维数组可以静态分配也可以动态分配
静态分配
数组的大小和空间是固定的,一旦空间占满,就无法再新增数据,否则会导致数据溢出。
动态分配
储存数组的空间在程序执行过程中会动态调整大小,当空间占满时,可以另行开辟更大的存储空间来存储数据。
2.1 顺序表的特点
顺序表的特点是可以进行随机访问,即可以通过表头元素的地址和元素的标号,在o(1)的时间复杂度内查找到指定的元素.
顺序表的不足之处是插入和删除操作需要移动大量的元素,从而保持逻辑上和物理上的连续性。
2.2 顺序表的性质
- 顺序表示存储结构,用一组地址连续的存储单元依次存储数据元素。如果两个元素逻辑上是相邻的,则物理地址上也是相邻的。
- 为了保持逻辑上和物理上的连续性,顺序表在插入和删除操作时,会进行大量元素的移动,这会增加操作的时间复杂度。
- 顺序表占用的存储空间大小与元素的存储顺序无关,而与存储元素的个数有关。
- 顺序表在访问元素时,可以通过表头元素的地址和元素的编号(下标),在O(1)时间内访问到它。
- 第一个元素的起始地址为0,每个元素大小为4,则第i个元素的起始地址为(i-1) × 4,则第101个元素的起始地址为(101 - 1) × 4 = 400.
- 在顺序表中,元素都是一个挨一个存储,元素都集中在一段区间内,相对存储密度大。
2.3 顺序表实现所需函数
1. insert(loc,value); //将value插入到顺序表中下标为loc的位置
/*
1. 判断插入位置是否合法。
2. 判断顺序表是否已满。
3. 将目标位置及之后的所有元素后移一位。
4. 将待插入的元素值插入到目标位置。
*/
2. expand(); //扩大顺序表的容量
/*
1. 将原来的元素存储到临时存储空间。
2. 扩大原来的存储空间。
3. 将临时存储空间里的数据元素复制到新的存储空间里。
4. 释放临时的存储空间。
*/
3. search(value); //查找顺序表中值为value的元素
/*
1. 从下标为 0 的元素开始依次枚举顺序表中的所有元素。
2. 发现和目标值相等的元素则返回它的下标。
3. 枚举结束没有找到目标元素则返回 -1。
*/
4. remove(index);//将顺序表中下标为index的元素移除
/*
1. 判断传入的参数是否合法,即下标是否在顺序表的范围内。
2. 将目标下标之后所有的元素前移一位。
3. 更新顺序表的长度。
*/
6. print();//输出顺序表中所有元素
/*
1. 从下标为 0 的元素开始遍历顺序表。
2. 输出所有元素的值。
*/
顺序表的构造
int insert(Vector *vector, int loc, int value) {
/*
vector:要插入元素的顺序表
loc:表示将要插入的位置
value:插入的元素值
当插入完成后data[loc]的值为value
当插入第i个位置后,需要将data[loc]后面的所有元素向后顺次移动,并将总长度+1
成功返回OK,失败返回ERROR
*/
if(loc< 0 || loc> vector->length)//判断插入位置是否越界
{
return ERROR;
}
if(vector->length >= vector->size)//判断数组长度是否已满
{
return ERROR;
}
for(int i = vector->length;i>loc;i--)//顺序向后移动
{
vector->data[i]= vector->data[i-1];
}
vector->data[loc] = value;
vector->length++;
return OK;
}
顺序表的扩容
// 请在下面实现扩容函数 expand
void expand(Vector *vector)
{
/*
每次扩容都将容量修改为之前的2倍,扩容时,要重新开辟一块空间,将原有的数据依次拷贝过去
将原来的空间释放掉.
*/
int* old_data = vector->data;
vector->size = vector->size*2;
vector->data = (int*)malloc(sizeof(int)*vector->size);
for(int i= 0 ;i<vector->length;i++)
{
vector->data[i] = old_data[i];
}
free(old_data);
}
练习题
#include <stdio.h>