顺序表分为定长顺序表、不定长顺序表
一、定长顺序表
1、结构体
typedef struct SQList
{
int elem[10];//存放数据,固定长度为10
int length;//有效数据的长度
}SQList, * PSQList;
2、初始化
void InitSqlist(PSQList ps)
{
assert(ps != NULL);
if (ps == NULL)
{
return;
}
ps->length = 0;
}
3、插入数据
先找到要插入的位置pos,将pos之后的数往后移,再将数val插入pos位置,最后将表长++
bool Insert(PSQList ps, int pos, int val)
{
assert(ps != NULL);
if (ps == NULL)
{
return false;
}
if (pos<0 || pos>ps->length || Full(ps))
{
return false;
}
//将pos后面的数往后移,找到pos位置
for (int i = ps->length-1 ; i >= pos; i--)
{
ps->elem[i + 1] = ps->elem[i];
}
//插入数据
ps->elem[pos] = val;
//顺序表长度++
ps->length++;
return true;
}
4、删除数据val
先找到val的位置,再将其删除
//在ps中查找第一个key值,找到返回下标,没有找到返回-1
int Search(PSQList ps, int key)
{
assert(ps != NULL);
if (ps == NULL)
{
return -1;
}
//找到key
for (int i = 0; i < ps->length - 1; i++)
{
if (ps->elem[i] == key)
{
return i;
}
}
return -1;
}
//删除pos位置的值
bool DelPos(PSQList ps, int pos)
{
assert(ps != NULL);
if (ps == NULL)
{
return false;
}
if (pos<0 || pos>ps->length || IsEmpyt(ps))
{
return false;
}
//将pos位置后面的数往前移动一位
for (int i = pos; i < ps->length - 1; i++)
{
ps->elem[i] = ps->elem[i + 1];
}
ps->length--;
return true;
}
//删除第一个val的值
bool DelVal(PSQList ps, int val)
{
int tmp = Search(ps, val);
if (tmp < 0)
{
return false;
}
else
{
return DelPos(ps, tmp);
}
}
5、完整代码
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<math.h>
#include <string.h>
#include<ctype.h>
#include<assert.h>
//定义与声明
typedef struct SQList
{
int elem[10];//存放数据,固定长度为10
int length;//有效数据的长度
}SQList, * PSQList;
//初始化
void InitSqlist(PSQList ps)
{
assert(ps != NULL);
if (ps == NULL)
{
return;
}
ps->length = 0;
}
static bool Full(PSQList ps)
{
return ps->length == 10;
}
//插入数据,在ps顺序表的pos位置插入val;
bool Insert(PSQList ps, int pos, int val)
{
assert(ps != NULL);
if (ps == NULL)
{
return false;
}
if (pos<0 || pos>ps->length || Full(ps))
{
return false;
}
//将pos后面的数往后移,找到pos位置
for (int i = ps->length-1 ; i >= pos; i--)
{
ps->elem[i + 1] = ps->elem[i];
}
//插入数据
ps->elem[pos] = val;
//顺序表长度++
ps->length++;
return true;
}
//判空
bool IsEmpyt(PSQList ps)
{
return ps->length == 0;
}
//在ps中查找第一个key值,找到返回下标,没有找到返回-1
int Search(PSQList ps, int key)
{
assert(ps != NULL);
if (ps == NULL)
{
return -1;
}
//找到key
for (int i = 0; i < ps->length - 1; i++)
{
if (ps->elem[i] == key)
{
return i;
}
}
return -1;
}
//删除pos位置的值
bool DelPos(PSQList ps, int pos)
{
assert(ps != NULL);
if (ps == NULL)
{
return false;
}
if (pos<0 || pos>ps->length || IsEmpyt(ps))
{
return false;
}
//将pos位置后面的数往前移动一位
for (int i = pos; i < ps->length - 1; i++)
{
ps->elem[i] = ps->elem[i + 1];
}
ps->length--;
return true;
}
//删除第一个val的值
bool DelVal(PSQList ps, int val)
{
int tmp = Search(ps, val);
if (tmp < 0)
{
return false;
}
else
{
return DelPos(ps, tmp);
}
}
//返回key的前驱下标,如果不存在返回-1
int GetPrio(PSQList ps, int key)
{
int tmp = Search(ps, key);
if (tmp < 0)
{
return -1;
}
else
{
return tmp-1;
}
}
//返回key的后继下标,如果不存在返回-1
int GetNext(PSQList ps, int key)
{
int tmp = Search(ps, key);
if (tmp < 0)
{
return -1;
}
else
{
return tmp + 1;
}
}
//输出
void Show(PSQList ps)
{
assert(ps != NULL);
if (ps == NULL)
{
return ;
}
for (int i = 0; i < ps->length; i++)
{
printf("%d ", ps->elem[i]);
}
printf("\n");
}
//清空数据
void Clear(PSQList ps)
{
ps->length = 0;
}
//销毁整个内存
void Destroy(PSQList ps)
{
Clear(ps);
}
int main()
{
SQList ps;
InitSqlist(&ps);
for (int i = 0; i < 9; i++)
{
Insert(&ps, i, i);
}
Show(&ps);
DelVal(&ps, 5);
Show(&ps);
Insert(&ps, 6, 10);
Show(&ps);
Clear(&ps);
Show(&ps);
}
二、不定长顺序表
1、结构体
typedef struct DSQList
{
int* elem;//动态内存的地址
int length;//有效数据长度
int listsize;//总容量
}DSQList,*DSQ;
2、初始化
void Initlist(DSQ ps)
{
assert(ps != NULL);
if (ps == NULL)
{
return;
}
ps->elem = (int*)malloc(INITSIZE * sizeof(int));
ps->length = 0;
ps->listsize = INITSIZE;
}
3、插入数据
先判断是否还有空间,若有则将pos之后的数据往后移
//在pos插入数据val
bool Insert(DSQ ps, int pos, int val)
{
assert(ps != NULL);
if (ps == NULL)
{
return NULL;
}
if (IsFull(ps))//判满
{
Roc(ps);
}
if (pos<0 || pos>ps->length)
{
return false;
}
//移动数据
for (int i = ps->length - 1; i >= pos; i--)
{
ps->elem[i + 1] = ps->elem[i];
}
//插入数据
ps->elem[pos] = val;
ps->length++;
return true;
}
4、删除数据val
//查找val并返回其下标
int Search(DSQ ps, int val)
{
assert(ps != NULL);
if (ps == NULL)
{
return -1;
}
for (int i = 0; i < ps->length - 1; i++)
{
if (ps->elem[i] == val)
{
return i;
}
}
return -1;
}
//删除pos位置的值
bool Delkey(DSQ ps, int pos)
{
assert(ps != NULL);
if (ps == NULL)
{
return false;
}
if (pos<0 || pos>ps->length)
{
return NULL;
}
for (int i = pos; i < ps->length - 1; i++)
{
ps->elem[i] = ps->elem[i + 1];
}
ps->length--;
return true;
}
//删除第一个val
bool Delval(DSQ ps, int val)
{
assert(ps != NULL);
if (ps == NULL)
{
return false;
}
int tmp = Search(ps, val);
if (tmp < 0)
return false;
else
return Delkey(ps, tmp);
}
5、完整代码
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<math.h>
#include <string.h>
#include<ctype.h>
#include<assert.h>
#include<malloc.h>
#define INITSIZE 10
typedef struct DSQList
{
int* elem;//动态内存的地址
int length;//有效数据长度
int listsize;//总容量
}DSQList,*DSQ;
//初始化
void Initlist(DSQ ps)
{
assert(ps != NULL);
if (ps == NULL)
{
return;
}
ps->elem = (int*)malloc(INITSIZE * sizeof(int));
ps->length = 0;
ps->listsize = INITSIZE;
}
//判满
static bool IsFull(DSQ ps)
{
return ps->length == ps->listsize;
}
//扩容
static bool Roc(DSQ ps)
{
ps->elem = (int*)realloc(ps->elem, 2 * sizeof(int) * ps->listsize);
assert(ps->elem != NULL);
ps->listsize *= 2;
return true;
}
//在pos插入数据val
bool Insert(DSQ ps, int pos, int val)
{
assert(ps != NULL);
if (ps == NULL)
{
return NULL;
}
if (IsFull(ps))//判满
{
Roc(ps);
}
if (pos<0 || pos>ps->length)
{
return false;
}
//移动数据
for (int i = ps->length - 1; i >= pos; i--)
{
ps->elem[i + 1] = ps->elem[i];
}
//插入数据
ps->elem[pos] = val;
ps->length++;
return true;
}
//判空
static bool IsEmpty(DSQ ps)
{
return ps->length == 0;
}
//查找val并返回其下标
int Search(DSQ ps, int val)
{
assert(ps != NULL);
if (ps == NULL)
{
return -1;
}
for (int i = 0; i < ps->length - 1; i++)
{
if (ps->elem[i] == val)
{
return i;
}
}
return -1;
}
//删除pos位置的值
bool Delkey(DSQ ps, int pos)
{
assert(ps != NULL);
if (ps == NULL)
{
return false;
}
if (pos<0 || pos>ps->length)
{
return NULL;
}
for (int i = pos; i < ps->length - 1; i++)
{
ps->elem[i] = ps->elem[i + 1];
}
ps->length--;
return true;
}
//删除第一个val
bool Delval(DSQ ps, int val)
{
assert(ps != NULL);
if (ps == NULL)
{
return false;
}
int tmp = Search(ps, val);
if (tmp < 0)
return false;
else
return Delkey(ps, tmp);
}
//返回val的前驱下标
int Qindex(DSQ ps, int val)
{
assert(ps != NULL);
if (ps == NULL)
{
return -1;
}
int tmp = Search(ps, val);
if (tmp < 0)
return -1;
else
return tmp-1;
}
//返回val的后继下标
int Bindex(DSQ ps, int val)
{
assert(ps != NULL);
if (ps == NULL)
{
return -1;
}
int tmp = Search(ps, val);
if (tmp < 0)
return -1;
else
return tmp + 1;
}
//输出
void Show(DSQ ps)
{
assert(ps != NULL);
if (ps == NULL)
{
return;
}
for (int i = 0; i < ps->length; i++)
{
printf("%d ", ps->elem[i]);
}
printf("\n");
}
//清空数据
void Clear(DSQ ps)
{
ps->length = 0;
}
//销毁整个内存
void Destroy(DSQ ps)
{
free(ps->elem);
ps->elem = NULL;
ps->length = 0;
ps->listsize = 0;
}
int main()
{
DSQList ps;
Initlist(&ps);
for (int i = 0; i < 9; i++)
{
Insert(&ps, i, i);
}
Show(&ps);
Delval(&ps, 5);
Show(&ps);
Insert(&ps, 6, 10);
Show(&ps);
Insert(&ps, 9, 100);
Show(&ps);
printf("请找到10的前驱下标:%d", Qindex(&ps, 10));
}
三、顺序表的特点
①插入数据的时间复杂度是O(n),如果是尾插时间复杂度是O(1);
②删除数据的时间复杂度是O(n),如果是尾删时间复杂度是O(1);
③通过下标访问数据时间复杂度是O(1);
顺序表逻辑上相邻的元素物理上也相邻,所以插入和删除操作需要移动大量元素;存储密度大(高),每个结点只存储数据元素(对比链表);
补充:
随机访问:顺序表是一种支持随机存取的存储结构,根据起始地址加上元素的序号,可以在O(1)时间内找到指定的元素。