学习教程为华清创客学院,秦老师的《数据结构全攻略》
定义:零个或多个相同数据元素的有限序列。
表示:
8种基本操作:
1. 建立空表
2. 置空一个表
3. 判断是否为空
4. 求表长
5. 取表中元素
6. 定位元素位置
7. 插入
8. 删除
合并运算和去重运算:
C语言中,顺序表的实现是用的一维数组。因为二者都是连续存储的。
顺序存储结构的特点:
-(1)逻辑上相邻的元素ai,ai+1,其存储位置也是相邻的;
-(2)对数据元素ai的存取为随机存取或按地址存取。
-(3)存储密度高。存储密度D=(数据结构中元素所占存储空间)/(整个数据结构所占空间)。
顺序存储结构的不足:
-对表的插入和删除等运算的时间复杂度较差。
对顺序表的各种操作是用指针来实现的。
last为指向表尾的指针,置为-1表示当前表为空表。
下面是代码实现,首先要建立头文件,对这些函数进行声明。
#ifndef __SEQLIST_H__
#define __SEQLIST_H__
#define MAXSIZE 100
typedef int data_t;
typedef struct{
data_t data[MAXSIZE];
int last;
}seqlist_t; //建立结构体,包含表尾指针和一维数组
seqlist_t *create_seqlist(void); //建立顺序表,申请一段存储空间
void clear_seqlist(seqlist_t *L); //释放顺序表,返还存储空间
int is_empty_seqlist(seqlist_t *L); //判断是否为空
int is_full_seqlist(seqlist_t *L); //判断是否为满
void set_empty_seqlist(seqlist_t *L); //清空顺序表
int get_lenth_seqlist(seqlist_t *L); //求表长度
void show_seqlist(seqlist_t *L); //打印顺序表
int insert_seqlist(seqlist_t *L, data_t x, int pos); //插入一个元素
int delete_seqlist(seqlist_t *L, int pos); //删除一个元素
int change_seqlist(seqlist_t *L, data_t x, int pos); //修改某个元素
int search_seqlist(seqlist_t *L, data_t x); //查找某个元素位置
#endif
头件的中的#ifndef,这是一个很关键的东西。
需要注意的是,#ifndef起到的效果是防止一个源文件两次包含同一个头文件,而不是防止两个源文件包含同一个头文件。在编译时,这两个C文件要一同编译成一个可运行文件,会产生大量的声明冲突。
把头文件的内容都放在#ifndef和#endif中间,不管你的头文件会不会被多个文件引用,都要加上这个。
声明完成后,编写C文件来实现
#include<stdio.h>
#include<stdlib.h>
#include"seqlist.h" //自己的项目内的头文件要用双引号
seqlist_t *create_seqlist(void){
seqlist_t *L = NULL; //定义一个空指针
L = (seqlist_t *)malloc(sizeof(seqlist_t)); //申请堆栈空间
//malloc返回是void型,要强制类型转换,给指针L
if(L == NULL){
puts("no memory");
return NULL;
} //申请失败提示信息,后面每个函数都需要判断
L->last = -1; //初始化时last置为-1,因为数组下标是从0开始的
return L; //建表函数返回一个指向表头的指针
}
void clear_seqlist(seqlist_t *L){
if(L == NULL){
puts("seqlist_t *L is NULL");
}
free(L); //释放掉这段空间
return ;
}
int is_empty_seqlist(seqlist_t *L){
if(L==NULL){
puts("seqlist *L is NULL");
return -1;
}
return(L->last == -1); //判断是否为空只要看last是否和初始时的值一样
}
int is_full_seqlist(seqlist_t *L){
if(L == NULL){
puts("seqlist_t *L is NULL");
return -1;
}
return (L->last == MAXSIZE-1); //比较last指针的值和表最大长度,注意下标从0开始
}
void set_empty_seqlist(seqlist_t *L){
if(L==NULL){
puts("seqlist *L is NULL");
return;
}
L->last = -1;
//置空时不用管现存元素,直接把last置为-1,后面再插入的时候就从data[0]开始重写了
return;
}
int get_lenth_seqlist(seqlist_t *L){
if(L==NULL){
puts("seqlist *L is NULL");
return -1;
}
return(L->last+1); //获取表长,直接last+1
}
void show_seqlist(seqlist_t *L){
int i;
if(L == NULL){
puts("seqlist_t *L is NULL");
return ;
}
for(i = 0; i<=L->last; i++) //for循环依次打印即可
printf("L->data[%d] = %d\n", i, L->data[i]);
return ;
}
int insert_seqlist(seqlist_t *L, data_t x, int pos){
int i;
if((is_full_seqlist(L))||(pos<0)||(pos>L->last+1)){
puts("input pos is invalid");
return -1;
} //首先判断表是否为满,或者插入位置pos的值是否正确
for(i = L->last; i>=pos; i--) //从最后的元素开始往下一个移动,否则会删除原有数据
L->data[i+1] = L->data[i]; //这一个数据来覆盖后面一个位置个位置
L->data[pos] = x; //然后把中间pos空出来的位置赋上数值x
L->last++; //注意把表尾指针往后移一格
return 0;
}
int delete_seqlist(seqlist_t *L, int pos){ //参数pos,删除该位置的数据
if(pos<0||pos>L->last){
puts("input pos is invalid");
return -1;
} //判断pos是否正确
int i;
for(i = pos; i <= get_lenth_seqlist(L); i++){ //从pos开始,把后面的数据往前移一格
L->data[i] = L->data[i+1];
}
L->last--; //移动完成后,将last也往前移一格
return 0;
}
int change_seqlist(seqlist_t *L, data_t x, int pos){
if(pos<0||pos>L->last){
puts("input pos is invalid");
return -1;
} //还是先判断pos合理性
L->data[pos] = x; //修改pos位置的数据
return 0;
}
int search_seqlist(seqlist_t *L, data_t x){
int i;
for(i = 0; i <= L->last; i++){
if(L->data[i] == x)
return i;
} //从data[0]开始遍历,返回匹配的下标
return -1; //如果没有匹配的,返回-1
}
最后编写测试程序来验证上述函数结果:
#include<stdio.h>
#include<stdlib.h>
#include"seqlist.h"
int main(int argc, const char * argv[]){
int i = 0;
seqlist_t *L = NULL;
L = create_seqlist();
for(i = 0; i<=4; i++)
insert_seqlist(L, i, 0); //写入数值
show_seqlist(L); //打印出当前线性表
printf("===============================\n");
printf("data 3 pos is %d\n", search_seqlist(L, 3));
printf("seqlist L lenth is %d\n", get_lenth_seqlist(L));
puts("===============================");
puts("delete data=3");
delete_seqlist(L, search_seqlist(L, 3)); //pos位置参数用search函数返回值来表示
show_seqlist(L);
puts("===============================");
puts("change data[2] = 99");
change_seqlist(L, 99, 2);
show_seqlist(L);
clear_seqlist(L);
return 0;
}
运行结果:
stephen@subuntu:~/Desktop/Data Stru/line/seqlist$ ./test
L->data[0] = 4
L->data[1] = 3
L->data[2] = 2
L->data[3] = 1
L->data[4] = 0
===================================
data 3 pos is 1
seqlist L lenth is 5
===================================
delete data=3
L->data[0] = 4
L->data[1] = 2
L->data[2] = 1
L->data[3] = 0
===================================
change data[2] = 99
L->data[0] = 4
L->data[1] = 2
L->data[2] = 99
L->data[3] = 0