文章目录
- 前言
- 一. 线性表插入和删除
- 1. 元素的插入
- 2. 元素的删除
- 二. 代码
- 三. 优缺点
前言
线性表的顺序存储结构,指的是用一段地址连续的存储单元依次存储线性表的数据结构
一. 线性表插入和删除
1. 元素的插入
插入位置之后的数据都向后移一位,上图中元素98、208、999、789都向后移一位。元素666插入到第5个位置。
2. 元素的删除
待删除元素之后所有的元素都向前移一位,上图中,元素209,999,789都向前移一位
二. 代码
#include <stdio.h>
#include <stdlib.h>
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define LIST_INIT_SIZE 20 /* 线性表初始空间 */
#define LIST_INCREMENT 10 /* 线性表每次的扩展空间大小 */
typedef int Status; /* 状态码,函数返回的状态码 */
typedef int ElemType; /* 元素类型,根据需要可以任意修改ElemType的原始类型,此处使用int型 */
typedef struct
{
ElemType* elem ; /*线性表数据, 使用数组实现顺序存储线性表的数据 */
int length; /*线性表长度*/
int listSize;
} SqList;
Status InitList(SqList * list); /*初始化线性表list*/
void DestoryList(SqList * list); /*销毁线性表list*/
void ClearList(SqList * list); /*清空线性表list*/
Status ListEmpty(SqList list); /*判断线性表是否为空表,空表返回TRUE,非空返回FALSE*/
int ListLength(SqList list); /*返回list的元素个数*/
Status GetElem(SqList list,int i, ElemType * elemPtr); /*从list中获取第i个元素,并将获取到的元素放到 elemPtr指针中,
获取到返回OK,否则返回ERROR */
int LocateElem(SqList list,ElemType elem); /*在list中查找数据元素elem的位置*/
Status PriorElem(SqList list ,ElemType elem, ElemType * elemPtr); /*在list中查找元素elem的前一个元素,并将找到的元素存放到elemPtr指针中*/
Status NextElem(SqList list, ElemType elem, ElemType * elemPtr); /*在list中查找元素elem的后一个元素,并将找到的元素存放到elemPtr指针中*/
Status ListInsert(SqList * list,int i,ElemType elem); /*在list的第i个位置插入元素elem*/
Status ListDelete(SqList * list,int i,ElemType * elemPtr); /*在list中删除第i个元素,并将第i个元素存放到elemPtr指针中*/
Status Visit(ElemType elem); /*对elem操作 */
Status ListTraverse(SqList list,Status (*visit)(ElemType)); /* 遍历表 */
Status ListUnion(SqList * listA,SqList listB); /* 将listB 中的数据合并到listA中 */
int main()
{
int i,j;
SqList list,listA,listB;
ElemType elem;
InitList(&list);
InitList(&listA);
InitList(&listB);
if(!ListTraverse(list,Visit))
printf("list没有数据打印!\n");
for(i=0;i<9;i++){
ListInsert(&list,i+1,i+100);
ListInsert(&listA,i+1,i+200);
}
for(i=5;i<30;i++)
ListInsert(&listB,i+1,i+200);/* i=26的时候,listB的数量超过20个,会将存储空间扩容*/
printf("list的数据:\t");
ListTraverse(list,Visit);
if(PriorElem(list,103,&elem))
printf("103前面的一个数字为;%d\n",elem);
if(NextElem(list,103,&elem))
printf("103后面的一个数字为:%d\n",elem);
printf("在第2个位置插入999\n");
ListInsert(&list,2,999);
printf("list的数据:\t");
ListTraverse(list,Visit);
ListDelete(&list,5,&elem);
printf("删除第5个数字:%d\n",elem);
printf("list的数据:\t");
ListTraverse(list,Visit);
i=ListUnion(&listA,listB); /*将listB数据合并到listA中*/
j=4;
printf("listA的数据为:\n");
ListTraverse(listA,Visit);
DestoryList(&listA); /*销毁listA,释放地址*/
DestoryList(&listB);
DestoryList(&list);
return 0;
}
/*初始化线性表list*/
Status InitList(SqList *list)
{
list->elem = (ElemType*) malloc(LIST_INIT_SIZE*sizeof(ElemType));
if(list->elem == NULL)
return ERROR;
list->length = 0;
list->listSize = LIST_INIT_SIZE;
return OK;
}
/*销毁线性表list*/
void DestoryList(SqList * list)
{
free(list->elem);
list->elem = NULL;
list->length = 0;
list->listSize = 0;
}
/*清空线性表list*/
void ClearList(SqList * list){
list->length=0;
}
/*判断线性表是否为空表,空表返回TRUE,非空返回FALSE*/
Status ListEmpty(SqList list){
if(list.length>0)
return FALSE;
else
return TRUE;
}
/*返回list的元素个数*/
int ListLength(SqList list){
return list.length;
}
/*从list中获取第i个元素,并将获取到的元素放到 elemPtr指针中, 获取到返回OK,否则返回ERROR */
Status GetElem(SqList list,int i,ElemType * elemPtr){
if(list.length==0 || i<1 || i>list.length)
return ERROR;
*elemPtr= list.elem[i-1];
return OK;
}
/*在list中查找第一个和elem相等的元素的位置,如果没有找到,返回ERROR,即0 */
int LocateElem(SqList list,ElemType elem)
{
int i=0;
for(; i<list.length; i++)
if(list.elem[i]==elem)
return i+1;
return ERROR;
}
/*在list中查找元素elem的前一个元素,并将找到的元素存放到elemPtr指针中*/
Status PriorElem(SqList list,ElemType elem,ElemType * elemPtr){
int i;
for(i=1 ; i<list.length; i++)/*第一个元素i=0没有前导,所以从第二个元素i=1开始*/
{
if(list.elem[i]==elem ){
*elemPtr=list.elem[i-1];
return OK;
}
}
return ERROR;
}
/*在list中查找元素elem的后一个元素,并将找到的元素存放到elemPtr指针中*/
Status NextElem(SqList list, ElemType elem, ElemType * elemPtr)
{
int i;
for( i=0; i<list.length-1; i++)/*最后一个元素没有后驱元素,所以查找到倒数第二个元素就结束(下标为list.length-2)*/
{
if(list.elem[i]==elem && i<list.length-1){
*elemPtr=list.elem[i+1];
return OK;
}
}
return ERROR;
}
/*在list的第i个位置插入元素elem*/
Status ListInsert(SqList * list,int i,ElemType elem){
int j;
ElemType * base;
if(i<1)
return ERROR;
if(list->length==list->listSize)/*list满了,需要对list扩容*/{
base=(ElemType *) realloc(list->elem,(list->listSize+LIST_INCREMENT)*sizeof(ElemType));
if(base!=NULL){ /*扩容成功,将新的基地址赋值给list->elem,并更新list的存储空间listSize*/
list->listSize += LIST_INCREMENT;
list->elem=base;
}
else
return ERROR;
}
for(j=list->length-1; j>=i-1; j--) /* 从第i个数据开始,所有元素向后移一位 */
list->elem[j+1]=list->elem[j];
list->elem[j+1]=elem; /*在第i个位置的值更新为新值elem, 此时的j=i-2, j+1=i-1,data[j+1]的位置就是第i个元素位置 */
list->length++;
return OK;
}
/*在list中删除第i个元素,并将第i个元素存放到elemPtr指针中*/
Status ListDelete(SqList * list,int i,ElemType * elemPtr)
{
int j;
if(i<1 || i>list->length)
return ERROR;
*elemPtr=list->elem[i-1];
for(j=i-1; j<list->length-1; j++)
list->elem[j]=list->elem[j+1];
list->length--;
return OK;
}
/*对elem操作,具体什么操作可以根据需要修改,本示例中是打印elem的值*/
Status Visit(ElemType elem){
printf("%d\t",elem);
}
/*遍历线性表,并对每一个元素调用Visit函数,一旦Visit()失败,这遍历失败 */
Status ListTraverse(SqList list, Status(*Visit) (ElemType elem) ){
int i;
if(list.length==0)
return ERROR;
for(i=0;i<list.length;i++)
(*Visit)(list.elem[i]);
printf("\n");
return OK;
}
/* 将listB 中的数据合并到listA中,B的元素已经在A中存在,不重复插入 */
Status ListUnion(SqList * listA,SqList listB){
int i ;
ElemType elem;
for(i=1; i<=listB.length; i++) /*循环listB所有元素 */
{
if( GetElem(listB,i,&elem) && !LocateElem(*listA,elem))/*在获取listB的元素,存放到变量elem中,在 listA中查找elem,不存在插入*/
ListInsert(listA,listA->length+1,elem);
}
return OK;
}
三. 优缺点
优点:读取快
缺点:插入和删除需要移动大量元素; 存储空间会有浪费的情况