- 线性表的基本操作
//线性表的基本操作 /* Status,自定义的一个枚举类型, enum Status{ success(成功),fail(失败),fatal(内存分配失败),range_error(连续空间访问失败越界) } */ Status List_Init(SqListPtr L);//初始化线性表 void List_Clear(SqListPtr L);//清空线性表 void List_Destory(SqListPtr L);//销毁线性表 bool List_Empty(SqListPtr L);//判断线性表是否为空 int List_Size(SqListPtr L);//线性表中元素的个数或线性表的长度 Status List_Retrival(SqListPtr L,int pos,ElemType *elem);//在线性表L中的pos那个位置取出数据放在elem指针中 Status List_Locate(SqListPtr L,ElemType elem,int *pos);//在线性表L中找出元素elem的位置放在pos指针中 Status List_Prior(SqListPtr L,int pos,ElemType *elem);//在线性表L中求出pos那个位置元素的直接前驱放在elem指针中 Status List_Next(SqListPtr L,int pos,ElemType *elem);//在线性表L中求出pos那个位置元素的直接后继放在elem指针中 //以上函数的参数是指针类型的,通常是指:我们希望通过函数所获得结果放到指针当中 Status List_Insert(SqListPtr L,int pos,ElemType elem);//在线性表中插入一个元素 Status List_Delete(SqListPtr L,int pos)://在线性表中删除一个元素
- 定义线性表结构体(空间分配,静态:数组;动态:指针)
//定义线性表的结构体 #define LIST_TNIT_SIZE 100 //线性表初始大小100 #define LIST_INCREAMENT 10 //增量 typedef int ElemType; typedef struct SqList{ ElemType *elem;//elem指针,指向ElemType数据元素类型,连续存储空间的首地址的指针 int length=0;//线性表的长度,初始线性表的长度为0 int list_size;//线性表内存空间的大小 }SqList,*ptr; typedef ptr SqListPtr;
一、线性表的顺序存储结构
1、初始化—创建线性表
//初始化,创建线性表 Status List_Init(SqListPtr L){ Status s=success;//状态初始假设是成功的 L->list_size=LIST_INIT_SIZE; L->length=0;//没有数据元素,线性表的初始长度为0 L->elem=(ElemType*)malloc(sizeof(ElemType)*L->list_size); if(L->elem==NULL) s=fatal;//内存分配失败,创建线性表失败 return s; //返回函数状态 }
2、线性表顺序存储结构上的查找(按位置查找值、按值查找位置)
- 按位置查找值,首先确保位置是合法的,若查找成功,返回位置元素的详细信息,否则返回错误信息
//按位置查找 Status List_Retrival(SqListPtr L,int pos,ElemType *elem){//查找在线性表pos位置的元素,放在elem指针中,该函数实现查找是否成功的状态信息 Status s=range_error;//假设初始状态,找不到,发生越界错误 if(L){//如果线性表存在 if((pos-1)>=0&&(pos-1)<L->length){//判断位置的合法性,逻辑位置与实际位置差1 *elem=L->elem[pos-1];//将查找pos位置的元素放在elem指针中 s=success//函数状态返回查找成功 } else s=fatal;//查找失败 return s;//返回函数状态 }
- 按值查找位置,需要将线性表中的每一个元素进行比较,从第一个元素开始,一直比较到最后一个元素,时间复杂度根据差找的元素位置不同而有所,若查找的元素在线性表的前面,则查找速度快些,若在后面,则查找的速度慢些。
//按值查找 Status List_Locate(SqListPtr L,ElemType elem,int *pos){//找elem在线性表L当中的位置放在pos指针中 Status s=range_error; if(L){//如果线性表存在 for(int i=0;i<L->length;i++){//对线性表中每一个元素和elem比较是否相等,如果相等则查找成功,否则查找失败 if(L->elem[i]==elem){ *pos=i+1; s=success; break; } } } else s=fatal;//查找失败 return s;//返回函数的状态 }
注:如果找到了就不找到需要再往后面找了,break跳出for循环,该按值查找的时间复杂度,最好的情况就是在第一个位置就找到,只需要比较1次,最坏的情况所查元素在最后一个或没有,需要比较n次,平均比较n/2次,时间复杂度是O(n)。
3、线性表的顺序存储—插入操作
- 检查插入位置是否合法,如果合法则继续,否则退出。
- 判断表是否占满,因为事先分配空间,可能存在所分配的存储空间全部被占用的情况,此时也不能事先插入。
- 若前面检查通过,则数据元素依次向后移动一个位置,为避免覆盖源数据,应从最后一个依次向前移动。
- 新的数据元素放到恰当的位置。
- 表长加1。
//线性表的顺序存储—插入操作 Status List_Insert(SqListPtr L,int pos,ElemType elem){//在线性表中pos位置插入新元素elem Status s=range_error; if((pos-1)>=0&&(pos-1)<L->length-1){//如果插入位置合法 if(L&&L->length<L->List_Size){//如果线性表存在 for(int i=L->length-1;i>=pos-1;i--) L->elem[i+1]=L->elem[i];//从最后一个元素开始向后移动 L->elem[pos-1]=elem;//将元素插入指定的pos位置 L->length++;//最后表长加1 s=success; } } else s=fail;//插入失败 return s; //返回函数状态 }
注:顺序表上实现插入操作需要移动表中一办的数据元素。时间复杂度为O(n),最坏的情况是在第一个元素插入(i=1),需要向后移动n个元素。这种顺序存储结构需要移动大量的数据元素,而每个数据元素可能是占据很大的内存空间,所以这种方法的效率是很低的。
4、线性表的顺序存储—删除操作
- 检查删除位置是否合法,同时判断线性表是否为空,因为空的线性表不能进行删除操作
- 若检查通过,数据元素依次向前移动一个位置
- 表长减1
//线性表的顺序存储—删除操作 Status List_Delete(SqListPtr L,int pos){//在线性表L中的pos位置删除元素 Status s=range_error; if((pos-1)>=0&&(pos-1)<L->length){//判断删除位置是否合法 if(L&&L->length>0){//判断线性表是否存在,且不为空 for(int i=pos-1;i<L->length;i++) L->elem[i]=L->elem[i+1];//移动 L->length--;//表长减1 s=success;//修改状态 } } else s=fail;//删除失败 return s; //返回函数状态 }
注:插入和删除的基本操作就是移动数据元素,最好的情况下,删除最后一个,移动一个元素;最差的情况下,删除第一个元素,移动n-1个元素;平均情况下:删除第i个元素,需要移动第n-i个元素
5、销毁线性表
//销毁线性表 void List_Destry(SqListPtr L){ if(L->elem) free(L->elem);//释放指针 L->length=0;//表长置0 }
6、清空线性表
void List_Clear(SqListPtr L){ L->length=0; }
7、判断线性表是否为空
//判断线性表是否为空 bool List_Empty(SqListPtr L){ if(L->length==0) return true; else return false; } //或者用下面的函数也可以判断 bool List_Empty(SqListPtr L){ return L->length==0; }
8、求线性表的前驱
Status List_Prior(SqListPtr L,int pos,ElemType *elem){//求线线表pos位置元素的前驱,将结果存放在elem指针中 Ststus s=fail; if(pos>=2&&pos<=L->length){//判断pos位置是否合法 *elem=L->elem[pos-2]; s=success; } else s=fail; return s; }
9、求线性表长度
//求线性表长度 int List_Length(SqListPtr L){ return L->length; }
10、求线性表的后继
//求线性表的后继 Status List_Next(SqListPtr L,int pos,ElemType *elem){//求线性表pos位置元素的后继,将结果存放在elem指针中 Status s=fail; if(pos>=1&&pos<L->length){//判断pos位置是否合法 *elem=L->elem[pos]; s=successs; } else s=fail; return s; }