线性表:唯一的头,唯一的尾,除了头结点,剩下其它节点都有前驱,除了尾结点,剩余其它节点都有后即
顺序表可分为定长顺序表和不定长顺序表。
顺序表的特点:
顺序表特点:(插入删除操作较少,随机访问数组中值这个操作较多)
1.逻辑简单,实现简单
2.插入操作时间复杂度O(n),因为需要向前覆盖数据,但是尾插不需要挪动数据(尾删除时间复杂度O(1))
3.删除操作时间复杂度O(n),因为需要向前覆盖数据,但是尾删除不需要挪动数据(尾删时间复杂度O(1))
4.随机访问时间复杂度O(1),因为顺序表可以通过下标之间访问数组中的元素值
顺序表: 数据和数据之间,逻辑相邻,物理也相邻
定长顺序表
由静态数组实现,功能主要包括数组的增删改查。
结构体中有两个成员,一个静态数组保存数据,
一个整型数据保存当前数组的中数据的有效长度
//定长顺序表
typedef struct sqlist
{
int arr[MAX_SIZE]; //存放有效数据
int length; //存放有效数据长度
}sqlsit, * Psqlist;
按位置插入操作
挪动数据 让值空出来,再将值放进去,
//按位置插入
bool Insert_pos(Psqlist p, int pos, int val)
{
//判空
assert(p != NULL);
if (NULL == p)
{
return false;
}
//判断插入位置 是否合法
assert(pos > 0 && pos <= p->length); //插入的时候pos ==p->length 合法
//判满操作
if (Is_Full(p))
return false; //没有扩容的定长顺序表 不需要执行扩容函数
// 首先挪动数据 让值空出来,再将值val放进去即可
//插入,挪动数据
for (int i = p->length; i >= pos; i--)
{
p->arr[i + 1] = p->arr[i];
}
//此时,挪动数据完成 标志着挪动数据完成 现在只需要 将插入的值val放进去
p->arr[pos] = val;
//修改length
p->length++;
return true;
}
按位置删除操作:
首先删除数据 让值空出来,将删除位置后面的有效值一次向前挪动一位,将删除位置覆盖掉即可
bool Del_pos(Psqlist p,int pos)
{
//判空 判断定长顺序表是否存在
assert(p != NULL);
if (NULL == p)
{
return false;
}
//判断删除位置 是否合法
assert(pos > 0 && pos < p->length);
//判空操作
if (Is_Empty(p))
return false;
// 首先删除数据 让值空出来,将删除位置后面的有效值一次向前挪动一位,将删除位置覆盖掉即可
//删除,向前覆盖数据,离待删除位置最近的元素先挪动
for (int i =pos+1; i <= p->length-1; i++)
{
p->arr[i-1] = p->arr[i];
}
//此时,删除数据完成 标志着数据向前覆盖完成
//修改length
p->length--;
return true;
}
其它功能不一一列举,程序源码如下:
首先构建头文件sqlist.h,定义结构体以及函数声明
#define MAX_SIZE 100
//定长顺序表
typedef struct sqlist
{
int arr[MAX_SIZE]; //存放有效数据
int length; //存放有效数据长度
}sqlsit, * Psqlist;
//增删改查
//初始化
void Init_sqlist(Psqlist p);
//按位置插入
bool Insert_pos(Psqlist p, int pos, int val);
//按位置删除
bool Del_pos(Psqlist p,int pos);
//按值删除
bool Del_val(Psqlist p, int val);
// 获取 其有效长度
bool Get_length(Psqlist p);
// 获取值所在下标 (如果数据重复,则返回第一次出现的位置)
int Search(Psqlist p, int val);
//判空
bool Is_Empty(Psqlist p);
//判满
bool Is_Full(Psqlist p);
//清空
void Clear(Psqlist p);
//销毁
void Destroy(Psqlist p);
//打印
void Show(Psqlist p);
其次在 sqlist.cpp文件中将函数功能一一实现
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include"sqlist.h"
//初始化---将普通的成员变量初始化
void Init_sqlist(Psqlist p)
{
assert(p != NULL);
if (p == NULL)
{
return;
}
//p->arr; 数组不需要赋值 因为里面值有没有效根据length来判断
p->length = 0;
}
//按位置插入
bool Insert_pos(Psqlist p, int pos, int val)
{
//判空
assert(p != NULL);
if (NULL == p)
{
return false;
}
//判断插入位置 是否合法
assert(pos > 0 && pos <= p->length); //插入的时候pos ==p->length 合法
//判满操作
if (Is_Full(p))
return false; //没有扩容的定长顺序表 不需要执行扩容函数
// 首先挪动数据 让值空出来,再将值val放进去即可
//插入,挪动数据
for (int i = p->length; i >= pos; i--)
{
p->arr[i + 1] = p->arr[i];
}
//此时,挪动数据完成 标志着挪动数据完成 现在只需要 将插入的值val放进去
p->arr[pos] = val;
//修改length
p->length++;
return true;
}
//按位置删除
bool Del_pos(Psqlist p,int pos)
{
//判空 判断定长顺序表是否存在
assert(p != NULL);
if (NULL == p)
{
return false;
}
//判断删除位置 是否合法
assert(pos > 0 && pos < p->length);
//判空操作
if (Is_Empty(p))
return false;
// 首先删除数据 让值空出来,将删除位置后面的有效值一次向前挪动一位,将删除位置覆盖掉即可
//删除,向前覆盖数据,离待删除位置最近的元素先挪动
for (int i =pos+1; i <= p->length-1; i++)
{
p->arr[i-1] = p->arr[i];
}
//此时,删除数据完成 标志着数据向前覆盖完成
//修改length
p->length--;
return true;
}
//按值删除
bool Del_val(Psqlist p, int val)
{
//assert
int index = Search(p, val);
if (index == -1)
return false;
return Del_pos(p, index);
}
// 获取 其有效长度
bool Get_length(Psqlist p)
{
return p->length;
}
//扩容 定长顺序表不需要实现
// 获取值所在下标 (如果数据重复,则返回第一次出现的位置)
int Search(Psqlist p, int val)
{
//判空
assert(p!=NULL);
for (int i = 0; i < p->length; i++)
{
if (p->arr[i] == val)
{
return i;
}
}
return -1;
}
//判空
bool Is_Empty(Psqlist p)
{
return p->length == 0;
}
//判满
bool Is_Full(Psqlist p)
{
return MAX_SIZE == p->length;
}
//清空
void Clear(Psqlist p)
{
//assert
p->length = 0;
}
//销毁 释放动态内存 ,防止内存泄漏
void Destroy(Psqlist p)
{
//assert
Clear(p);
//定长顺序表不用 存放数据使用的是静态顺序表 系统开辟系统释放
}
//打印
void Show(Psqlist p)
{
//assert
for (int i = 0; i < p->length; i++)
{
printf("%d ", p->arr[i]);
}
printf("\n");
}