顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储。在数组上完成数据的增删查改。
顺序表一般可以分为:
- 静态顺序表:使用定长数组存储。
- 动态顺序表:使用动态开辟的数组存储。
问题:
- 中间/头部的插入删除,时间复杂度为O(N)
- 增容需要申请新空间,拷贝数据,释放旧空间。会有不小的消耗。
- 增容一般是呈2倍的增长,势必会有一定的空间浪费。例如当前容量为100,满了以后增容到200,
我们再继续插入了5个数据,后面没有数据插入了,那么就浪费了95个数据空间。
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
//定义一个顺序表
typedef struct seqlist{
int* array; //顺序表中存的值
int capacity; //容量
int size; //有效个数
}seqlist;
//顺序表初始化
void seqlist_Init(seqlist* seq){
assert(seq != NULL); //传进来的顺序表不为空
seq->capacity = 10; //先设置一个容量为10的顺序表(可以随意设置)
seq->array = (int*)malloc(sizeof(int)*seq->capacity); //申请内存空间
seq->size = 0; //有效个数为0
}
//销毁
void seqlist_destory(seqlist* seq){
assert(seq!=NULL);
free(seq->array);
}
//判断+扩容
void seqlist_enlarge(seqlist* seq){
if (seq->size < seq->capacity){ //有效个数小于容量,不扩容
return;
}
else if (seq->size == seq->capacity){ //有效个数等于容量,扩容,大小为原容量的两倍
int newcapacity = seq->capacity * 2; //两倍是一个经验数值,不做定量要求
int* newarray = (int*)malloc(sizeof(int)*newcapacity);
for (int i = 0; i < seq->size; i++){ //搬原数据到新扩容的地方
newarray[i] = seq->array[i];
}
free(seq->array); //搬完后,释放原容量
seq->array = newarray;
seq->capacity = newcapacity;
}
}
//插入都要考虑扩容问题
//头插
void head_insert(seqlist* seq, int value){
seqlist_enlarge(seq);
if (seq->size == 0){ //原顺序表为空时,要插入的数做为第一个
seq->array[seq->size] = value;
seq->size++;
}
else{
for (int i = seq->size; i > 0; i--){ //原顺序表不为空,先将原顺序表的值向后移一位
seq->array[i] = seq->array[i - 1];
}
seq->array[0] = value; //再把要插入的数给顺序表第一个
seq->size++; //有效个数加一
}
}
//尾插
void tail_insert(seqlist* seq, int value){
seqlist_enlarge(seq);
seq->array[seq->size] = value;
seq->size++;
}
//随机插入
void random_insert(seqlist* seq, int pos, int value){
seqlist_enlarge(seq);
if (pos > seq->size||pos < 0){
printf("%d越界,插入失败!\n",pos);
return;
}
else{
for (int i = seq->size; i>=pos; i--){
seq->array[i] = seq->array[i - 1];
}
seq->array[pos - 1] = value;
seq->size++;
}
}
//头删
void head_delete(seqlist* seq){
assert(seq->size > 0);
for (int i = 0; i < seq->size; i++){
seq->array[i] = seq->array[i + 1];
}
seq->size--;
}
//尾删
void tail_delete(seqlist* seq){
assert(seq->size>0);
seq->size--;
}
//随机删除
void random_delete(seqlist* seq, int pos){
assert(seq->size > 0);
if (pos > seq->size||pos < 0){
printf("%d越界,删除失败!\n",pos);
return;
}
else{
for (int i = pos; i < seq->size; i++){
seq->array[i - 1] = seq->array[i];
}
seq->size--;
}
}
//按下标查找
int seqlist_search1(seqlist* seq, int pos){
assert(seq->size>0);
if (pos<0 || pos>seq->size){
printf("越界,查找失败!\n");
return -1;
}
else{
return seq->array[pos - 1];
}
}
//按照值查找
int seqlist_search2(seqlist* seq, int value){
assert(seq->size > 0);
int i = 0;
for (i = 0; i < seq->size; i++){
if (seq->array[i] == value){
return i+1;
}
}
return -1;
}
//打印
void seqlist_print(seqlist* seq){
assert(seq->size > 0);
for (int i = 0; i < seq->size; i++){
printf("%d ", seq->array[i]);
}
}
//void seqlist_Init(seqlist* seq) 初始化
//void seqlist_destory(seqlist* seq) 销毁
//void seqlist_enlarge(seqlist* seq) 扩容
//void head_insert(seqlist* seq, int value) 头插
//void tail_insert(seqlist* seq, int value) 尾插
//void random_insert(seqlist* seq, int pos, int value) 随机插入
//void head_delete(seqlist* seq) 头删
//void tail_delete(seqlist* seq) 尾删
//void random_delete(seqlist* seq, int pos) 随机删除
//int seqlist_search1(seqlist* seq, int pos) 按下标查找
//int seqlist_search2(seqlist*seq, int value) 按值查找
//void seqlist_print(seqlist* seq) 打印
//下面是对一些函数功能的验证
int main(){
seqlist P;
seqlist_Init(&P);
head_insert(&P,2);
head_insert(&P, 3);
tail_insert(&P, 7);
seqlist_print(&P);
system("pause");
return 0;
}