<数据结构>循序表
一、循序表基本概念
1.1、线性表基本概念
- 顺序表有且只有一个开始节点和结束节点。除了开始节点,其他有且只有一个直接前驱。除了结束节点,其他有且只有一个直接后驱。
注意事项:
- 循序表:数据节点间,逻辑相邻(一个连接一个)。物理也相邻(地址连续)
- 链表:数据节点间,逻辑相邻(一个连接一个)。物理不一定相邻(地址不一定连续)
1.2、顺序表基本概念
- 顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储。在数组上完成数据的增删查改。
顺序表一般可以分为: - 静态顺序表:使用定长数组存储元素。
typedef int data_t;
#define N 7 //固定数值(可指定)
typedef struct SequenceList{
data_t data[N];//存放顺序表数据,以整型数据为例
int last;//当前尾元素下标
}sqlist, *sqlink;
- 动态顺序表:使用动态开辟的数组存储。
typedef int data_t;
typedef struct SequenceList{
data_t *data;//存放顺序表数据,以整型数据为例
int last;//当前尾元素下标
int cap;//顺序表容量,类似于数组的容量
}sqlist, *sqlink;
2、循序表的实现
采样静态循序表
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
2.1、循序表创建
sqlink SeqList_creat()
{
sqlink L;
L = (sqlink)malloc(sizeof(sqlist));
if(L==NULL)
{
return L;
}
memset(L,0,sizeof(sqlist));
L->last = -1;
return L;
}
2.2、循序表打印
int SeqList_Print(sqlink L)
{
if(L == NULL)
{
return -1;
}
if(L->last == -1 )
{
return -1;
}
for(int i = 0;i<L->last;i++)
{
printf("%d",L->data[i]);
}
puts("");
return 0;
}
2.3、循序表清空
int SeqList_clear(sqlink L)
{
if(L == NULL)//顺序表为空
return -1;
memset(L,0,sizeof(sqlist));
ps->last = -1;
return 0;
}
2.4、循序表销毁
int SeqList_free(sqlink L)
{
if(L == NULL)
return -1;
free(L);
L = NULL;
return 0;
}
2.5、循序表判空
int SeqList_empty(sqlink L)
{
if (L->last == -1)
return 1;
return 0;
}
2.6、循序表判满
int SeqList_length(sqlink L) {
if (L == NULL)
return -1;
if(L->cap==(L->last+1))
{
return 1;
}
return 0;
}
2.7、循序表查找
int SeqList_locate(sqlink L, int value) {
for (int i = 0; i <= L->last; i++) {
if (L->data[i] == value)
return i;
}
return -1;
}
2.8、循序表指定位置插入
int SeqList_insert(sqlink L, data_t value, int pos) {
//full 先判满
if (L->last == N-1) {
printf("list is full\n");
return -1;
}
//check para 0<=pos<=Last+1 [0, last+1]
if (pos < 0 || pos > L->last+1) {
printf("Pos is invalid\n");
return -1;
}
//move
for (int i = L->last; i >= pos; i--) {
L->data[i+1] = L->data[i];
}
//update value last
L->data[pos] = value;
L->last++;
return 0;
}
2.9、循序表指定位置删除
int SeqList_delete(sqlink L, int pos) {
if (L->last == -1) {
printf("list is empty\n");
return -1;
}
//pos [0, last]
if (pos < 0 || pos > L->last) {
printf("delete pos is invalid\n");
return -1;
}
//move [pos+1, last]
for (int i = pos+1; i <= L->last; i++) {
L->data[i-1] = L->data[i];
}
//update
L->last--;
return 0;
}
2.10、两循序表融合
int SeqList_merge(sqlink L1, sqlink L2) {
int i = 0;
int ret;
while (i <= L2->last){
ret = SeqList_locate(L1, L2->data[i]);
if (ret == -1) {
if (SeqList_insert(L1, L2->data[i], L1->last+1) == -1)
return -1;
}
i++;
}
return 0;
}
2.11、删除循序表中重复元素
int SeqList_purge(sqlink L) {
int i;
int j;
if (L->last == 0)
return 0;
i = 1;
while (i <= L->last) {
j = i-1;
while (j >= 0) {
if (L->data[i] == L->data[j]) {
SeqList_delete(L, i);
break;
} else {
j--;
}
}
if ( j < 0) {
i++;
}
}
return 0;
}
3、循序表循序存储的优缺点
3.1、优点
- 线性表的顺序存储结构有存储密度高及能够随机存取等优点
3.2、缺点
- 要求系统提供一片较大的连续存储空间
- 插入、删除等运算耗时,且存在元素在存储器中成片移动的现象