数据结构C语言版线性表的动态分配顺序存储结构表示和实现文库.txt爱空空情空空,自己流浪在街中;人空空钱空空,单身苦命在打工;事空空业空空,想来想去就发疯;碗空空盆空空,生活所迫不轻松。
总之,四大皆空!/*数据结构C语言版线性表的动态分配顺序存储结构表示和实现P22-26编译环境:Dev-C++ 4.9.9.2日期:2011年2月9日*/#include <stdio.h>#include <malloc.h>#include <stdlib.h>typedef int ElemType; // 定义数据结构元素的数据类型#define LIST_INIT_SIZE 10 // 线性表存储空间的初始分配量#define LISTINCREMENT 5 // 线性表存储空间的分配增量// 线性表的动态分配顺序存储结构typedef struct{ElemType *elem; // 存储空间基址int length; // 当前长度int listsize; // 当前分配的存储容量(以sizeof(ElemType)为单位)}SqList;// 算法2.3,P23// 构造一个空的顺序线性表即对顺序表结构体中的所有元素// 进行初始化。
int InitList(SqList *L){// 分配指定大小的存储空间给顺序表(*L).elem = (ElemType*)malloc(LIST_INIT_SIZE * sizeof(ElemType));if( !(*L).elem ) // 存储分配失败exit(0);(*L).length = 0; // 当前长度初始化为0// 指定分配的存储容量(*L).listsize = LIST_INIT_SIZE;return 1;}// 销毁顺序线性表L即将顺序表结构体中的所有成员销毁(空间释放,// 数值置0)。
int DestroyList(SqList *L){// 先释放空间,然后置空free( (*L).elem );(*L).elem = NULL;(*L).length = 0;(*L).listsize = 0;return 1;}// 将L重置为空表(当前长度为0即是空表)。
int ClearList(SqList *L){(*L).length = 0;return 1;}/*若L为空表,则返回1,否则返回0。
如何判断是否为空表呢?结构体中已经包含一个可以说明的元素,那就是length,表示当前顺序表的长度,根据当前的长度就可以判断了,为0就是空表,不为0就不是空表了。
*/int ListEmpty(SqList L){if(0 == L.length)return 1;elsereturn 0;}// 返回L中数据元素个数。
int ListLength(SqList L){// L.length刚好记录了当前顺序表的长度,直接返回return L.length;}// 用e返回L中第i个数据元素的值,第i个数据元素就是L.elem[i-1]。
int GetElem(SqList L,int i,ElemType *e){// 首先进行异常处理if(i < 1 || i > L.length)exit(0);/*注意顺序表基址L.elem[0] 表示第一个数,而第i个数则是用基址L.elem + i - 1来表示,也可以用L.elem[i-1]表示。
为什么可以那样表示呢?因为l.elem是基地址,相当于数组头一样,指示了一个首地址,然后对地址进行加减,形成不同元素的地址。
*是取地址所指的内容,所以*(L.elem+i-1)就是第i个数据的值了。
*/*e = *(L.elem + i - 1);// *e = L.elem[i-1];return 1;}/* 算法2.6,P26返回L中第1个与e满足关系compare()的数据元素的位序。
若这样的数据元素不存在,则返回值为0。
*/int LocateElem(SqList L,ElemType e,int(* compare)( ElemType, ElemType)){ElemType *p;int i = 1; // i的初值为第1个元素的位序p = L.elem; // p的初值为第1个元素的存储位置即地址// 循环比较,直到找到符合关系的元素while(i <= L.length && !compare(*p++, e) )++i;if(i <= L.length)return i;elsereturn 0;}#if 0/* 算法2.7 与算法2.2区别已知顺序线性表La和Lb的元素按值非递减排列。
归并La和Lb得到新的顺序线性表Lc,Lc的元素也按值非递减排列。
算法的时间复杂度为O(La.length + Lb.length).*/void MergeList(SqList La, SqList Lb, SqList *Lc){ElemType *pa, *pa_last, *pb, *pb_last, *pc;pa = La.elem; //pa指向线性表La的头结点pb = Lb.elem; //pb指向线性表Lb的头结点/* 不用InitList()创建空表Lc */(*Lc).listsize = (*Lc).length = La.length + Lb.length;// pc指向线性表Lc的头结点pc = (*Lc).elem =(ElemType *)malloc((*Lc).listsize*sizeof(ElemType));if( !(*Lc).elem ) /* 存储分配失败 */exit(0);pa_last = La.elem + La.length - 1; //pa_last指向线性表La的尾结点pb_last = Lb.elem + Lb.length - 1; //pb_last指向线性表Lb的尾结点while(pa <= pa_last && pb <= pb_last) /* 表La和表Lb均非空 */{ /* 归并 */if(*pa <= *pb) //*pa更小接到pc后*pc++ = *pa++;else //*pb更小接到pc后*pc++ = *pb++;}while(pa <= pa_last) /* 表La非空且表Lb空 */*pc++ = *pa++; /* 插入La的剩余元素 */while(pb <= pb_last) /* 表Lb非空且表La空 */*pc++ = *pb++; /* 插入Lb的剩余元素 */}#endif// 若cur_e是L的数据元素,且不是第一个,则用pre_e返回它的前驱,否// 则返回0。
int PriorElem(SqList L, ElemType cur_e, ElemType *pre_e){int i = 2;// 因为第一个数据元素无前继,从第二个数据元素开始ElemType *p = L.elem + 1;// 找到该cur_e对应的元素并赋给pwhile(i <= L.length && *p != cur_e){p++;i++;}if(i > L.length)return 0;else{/*将该cur_e的前驱赋给*pre_e.对等式说明下:* 和 --是同优先级的,且它们的结合性是自右向左的,所以先p自减1,p指向其前驱,然后将p所指向的地址的内容赋给*pre_e。
从这里要明白为什么用指针进行传值,我给你一个地址,你把内容放进去,然后我就知道其中的值了。
这就是使用指针的用处。
*/*pre_e = *--p;return 1;}}/*若cur_e是L的数据元素,且不是最后一个,则用next_e返回它的后继,否则返回0*/int NextElem(SqList L,ElemType cur_e,ElemType *next_e){int i = 1;ElemType *p = L.elem;while(i < L.length && *p != cur_e){i++;p++;}if(i == L.length)return 0;else{/*对这个等式说明下:* 和 --是同优先级的,且它们的结合性是自右向左的,所以先p自加1,然后将p所指向的地址的内容赋给*next_e*/*next_e = *++p;return 1;}}// 算法2.4 P24// 在L中第i个位置之前插入新的数据元素e,L的长度加1.int ListInsert(SqList *L,int i,ElemType e){ElemType *newbase, *q, *p;// 输入的i不合法if(i < 1 || i > (*L).length + 1)return 0;// 当前存储空间已满,增加分配if( (*L).length >= (*L).listsize){// realloc改变(*L).elem所指内存的大小,原始所指内存中的// 数据不变。
newbase = (ElemType *)realloc((*L).elem,((*L).listsize + LISTINCREMENT) * sizeof(ElemType));if( !newbase )exit(0);(*L).elem = newbase; // 新基址(*L).listsize += LISTINCREMENT; // 增加存储容量}// 指定插入的位置q = (*L).elem + i - 1;// q之后的元素右移一步,以腾出位置for(p = (*L).elem + (*L).length - 1; p >= q; --p)*(p+1) = *p;*q = e; // 插入e++(*L).length; // 表长增1return 1;}/* 算法2.5 P25删除L的第i个数据元素,并用e返回其值,L的长度减1.*/int ListDelete(SqList *L,int i,ElemType *e){ElemType *p,*q;// i值不合法if( i < 1 || i > (*L).length)return 0;p = (*L).elem + i - 1; // p为被删除元素的位置*e = *p; // 被删除元素的值赋给eq = (*L).elem + (*L).length-1; // 表尾元素的位置for(++p; p <= q; ++p) // 被删除元素之后的元素左移*(p-1) = *p;(*L).length--; // 表长减1return 1;}// 依次对L的每个数据元素调用函数vi()。