线性表
线性表是具有相同数据类型的n(n>=0)个数据元素的有序序列。当n=0shi ,该线性表为空表。
对于线性表内元素,除了第一个元素外,每个元素有且只有一个直接前驱;除了最后一个元素外,每个元素有且仅有一个直接后继。
线性表具有三个特性:
- 线性表中的所有数据元素类型都相同;
- 线性表是由有限个数据元素构成;
- 线性表中的数据元素是与位置相关的,每个元素都有一个对应的序号。
注;线性表是逻辑结构,表示元素之间一对一的相邻关系。顺序表和链表是存储结构。
顺序表:
顺序存储的线性表称之为顺序表,他是用一组地址连续的存储单元,一次存储线性表中的数据元素,从而使得逻辑上相邻的两个元素在物理位置上也相邻,即表中元素的逻辑顺序和物理顺序相同;
对于数组可以静态分配,也可以动态分配。
在静态分配时,由于数组的大小和空间已经固定,一旦空间占满,再加入新的数据将产生溢出,便会导致程序崩溃;
在动态分配时,数组的空间是在程序执行过程中通过动态存储分配语句进行分配,一旦空间占满,便可以另外再开辟一块更大的存储空间,用一替换原来的空间,从而达到扩充数组空间的目的。
顺序表的特点是可以进行随机存取。即可以通过首地址和元素序号,在O(1)的时间内找到指定的元素。顺序表的密度相对较高,每个节点只存储数据元素。但是由于顺序表逻辑上元素相邻,所以插入和删除操作需要移动大量的元素。
/************************************************************************************************
优点:
1,无须为表中元素之间的逻辑关系而增加额外的空间
2,可以随意的存取表中任意位置的元素
缺点:
1,插入和删除操作需要移动大量的元素
2,当线性表长度变化较大时,难以确定存储空间的容量
3,容易造成存储空间的“碎片”
************************************************************************************************/
#define MAXSIZE 20 //存储空间初始分配量
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
typedef int ElemType; //ElemType 数据类型
typedef int Status;
typedef struct
{
ElemType data[MAXSIZE]; //数组存储数据元素,最大值MAXSIZE
int length; //线性表当前长度
}SqList;
// 线性表 获得元素操作 O(1)
Status GetElem(SqList L, int i, ElemType *e)
{
if(L.length == 0 || i<1 || i>L.length)
return ERROR;
*e = L.data[i-1];
return OK;
}
//线性表 插入元素操作 O(n)
/************************************************************************************************
错误处理:
1,如果插入位置不合理,抛出异常
2,如果线性表长度大于等于数组长度,抛出异常或者动态增加容量
开始插入:
3,从最后一个元素开始向前遍历到第i个位置,分别把他们向后移动一个位置
4,将要插入的元素插入第i个位置
5,表的长度增加一个
最好情况:表尾插入,元素后移不执行,时间复杂度O(1);
最坏情况:表头插入,元素语句将执行n次,时间复杂度O(n);
************************************************************************************************/
Status ListInsert(SqList *L, int i, ElemType e)
{
int k;
if(L->length == MAXSIZE) //顺序表已经满
return ERROR;
if(i<1 || i>L->length+1) //当i不在范围内
return ERROR;
if(i<=L->length) //i的位置合理,并且不在表尾
{
for(k=L->length - 1; k>=i-1; k--) //将插入位置后的元素向后移动(包括i位置原有的元素)
L->data[k+1] = L->data[k];
}
L->data[i-1] = e; //插入新的元素
L->length++; //表长增加
return OK;
}
//线性表 删除元素操作 O(n)
/************************************************************************************************
1,如果删除位置不合理,抛出异常
2,去除要删除的元素;
3,从要删除的元素位置开始向后一直遍历到最后一个元素,分别将他们都向前移动一个位置
4,表长减1
最好情况:表尾删除,无需移动元素,时间复杂度O(1);
最坏情况:表头删除,需要移动除第一个元素外的所有元素。时间复杂度O(n);
************************************************************************************************/
Status ListDelete(SqList *L, int i, ElemType *e)
{
int k;
if(L->length == 0) //表为空不能删除
return ERROR;
if(i<1 || i>L->length) //输入位置不正确
return ERROR;
*e = L->data[i-1]; //取出相应元素
if(i<L->length) //删除的不是最后一位
{
for(k = i; k<L->length; k++) //将删除位置后面的元素前移
L->data[k-1] = L->data[k];
}
L->length--; //长度减一
return OK;
}