文章目录
- 前言
- 一. 线性表插入和删除
- 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;}
三. 优缺点
优点:读取快
缺点:插入和删除需要移动大量元素; 存储空间会有浪费的情况