线性表的定义
注:数据结构三要素一一逻辑结构、数据的运算、存储结构(物理结构);储存的方式不同,运算实现的方式不同
小节回顾
chp2-2顺序表
定义
顺序表一一用顺序存储(一般使用数组)的方式实现线性表顺序存储。把逻辑上相邻的元素存储在物理
位置上也相邻的存储单元中,元素之间的关系由存储单元的邻接关系来体现。而在数组分配上又可再进一步的分为动态数组分配与静态数组分配。
顺序表的特点
小节总结
2-2.1实现–静态\动态数组分配
代码实现
#include<stdio.h>
#include<stdlib.h>
#define MaxiSize 10 //默认顺序表的最大长度
//使用静态数组分配顺序表
/* Static Arrays*/
typedef struct SAList
{
int data[MaxiSize]; //使用静态数组存放数据
int length; //顺序表当前长度
} SASqList; //顺序表的定义(静态分配方式)
//使用动态分配顺序表
/* Malloc Arrays*/
typedef struct MAList
{
int *data; //指示动态分配数组的指针
int MaxSize; //顺序表的最大容量
int length; //顺序表的当前长度
}MASqList;
//静态数组顺序表初始化函数
void SAInitList(SASqList *L){
printf("<-------静态顺序表初始化函数------->\n");
for (int i = 0; i < MaxiSize; i++)
{
//全部数组赋初值为0
L->data[i] = 0;
}
//顺序表初始长度为0
L->length = 0;
printf("<-------静态顺序表初始化结束------->\n");
}
void MAInitList(MASqList *L){
printf("<-------动态顺序表初始化函数------->\n");
//用malloc申请一片连续的数组空间
L->data = (int *)malloc(MaxiSize * sizeof(int));
//顺序表初始长度为0
L->length = 0;
L->MaxSize = MaxiSize;
printf("<-------静态顺序表初始化结束------->\n");
}
void MAIncreaseSize(MASqList *L,int len){
int *p = L->data; //用一个指针暂存当前顺序表的数组指针
//重新给L顺序表分配空间(变大了)
L->data = (int *)malloc((L->MaxSize + len) * sizeof(int));
for (int i = 0; i < L->MaxSize; i++)
{
L->data[i] = p[i]; //将原来L顺序表中的元素赋值到新的区域
}
L->MaxSize = L->MaxSize + len; //顺序表最大长度增加 len
free(p); //释放原来的内存空间
}
int main(){
SASqList SAL; //声明一个静态顺序表
SAInitList(&SAL); //初始化静态顺序表
MASqList MAL; //声明一个动态顺序表
MAInitList(&MAL);
return 0;
}
2-2.2顺序表的基本功能–插入
功能代码是在静态分配方式下实现的,动态分配也雷同
代码实现
/** 静态顺序表的插入 在L的位序 i 处插入元素 e
* @param L 需要操作的链表
* @param i 需要插入的位置(表L中第i个位置对应于下标i-1)
* @param e 需要插入的元素
* 这里需要注意的是,最后e应该放到 i -1 = 2 的数组下标位置
* 如 i = 2 j最后一进入 for 循环值为 2 则data[2] = data[1]
* 0 1 2 3 4 5 index
* 3 5 7 9 0 values
* 3 5 5 7 9 0 将 下标>=1的元素全部后移一位
* 3 e 5 7 9 0 将元素放置i-1=1处
*/
bool SAListInsert(SASqList *L,int i,int e){
if(i<1||i>(L->length)+1) //判断 i 的合法性
return false;
if(L->length>=MaxiSize) //如果空间已满则也不能插入
return false;
//将第 i 个元素及之后的元素后移
for (int j = L->length; j >= i; j--)
{
L->data[j] = L->data[j - 1];
}
L->data[i - 1] = e; //在位序 i 处放入e
L->length++; //长度+1
return true;
}
时间复杂度分析
2-2.3顺序表的基本功能–删除
代码实现
/** 静态顺序表的删除 将L的位序为 i 的元素删除 并将其赋至e
*@param L 需要操作的表
@param i 需要删除的位序
@param e 对应为删除的元素带回来
* 如 i = 2
* 有 e = data[1] =5
* j第一轮进入 for 循环值为 i=2 则data[1] = data[2]
* j最后一进入 for 循环值为 length-1=5-1=4 则data[3] = data[4]
* 0 1 2 3 4 5 index
* 3 5 7 9 0 values
* 3 7 9 0 0 将 下标>=2的元素全部前移一位
* */
bool SAListDelete(SASqList *L,int i , int *e){
if(i<1||i>L->length) //判断 i 的合法性
return false;
*e = L->data[i-1]; //将需要删除的元素的值赋到e
for (int j = i; j < L->length;j++){
L->data[j - 1] = L->data[j]; //将第 i 各位之后的元素前移
}
L->length--; //线性表长度-1
return true;
}
时间复杂度分析
小节总结
2-2.4顺序表的查找
按位查找
代码实现
/** 获取链表L中位序为 i 的元素
* @param L 需要操作的链表
* @param i 需要取值的位序
* */
int SAGetElem(SASqList *L,int i ){
if(i<1||i>L->length) //判断位序的合法性
return -1;
return L->data[i - 1]; //与数组的使用无异
}
时间复杂度
按值查找
代码实现
/** 按值查找 在顺序表中获取值 e 第一次出现的位序
* @param L 需要操作的链表
* @param e 需要查询的数值
* */
int SALocateElem(SASqList *L,int e){
for (int i = 0; i < L->data;I++){
if(L->data[i]==e) //如果匹配到对应的值
return i + 1; //范围对应的位序
}
return -1; //如果没有查询到,则返回-1
}