线性表的顺序实现/动态数组(C语言实现)
/**
* 线性表的顺序实现
* 逻辑关系上相邻的两个元素物理上也相邻
* 优点在于可以随机存取
* 缺点在于插入或删除元素需要移动大量的元素
*/
/*导入必要的头文件*/
#include "stdlib.h" //malloc, realloc
#include "stdio.h" //printf, scanf
/*通用的定义*/
#define TRUE 1 //真
#define FALSE 0 //假
#define OK 1 //完成
#define ERROR 0 //出错
#define INFEASIBLE -1 //不可能的
#define OVERFLOW -2 //内存溢出
#define INIT_LIST_SIZE 100 //顺序表初始长度
#define LIST_INCREAMENT 10 //顺序表线性增长长度
typedef int Status; //状态
/*顺序表*/
typedef int ElemType_SQL; //顺序表数据类型
typedef struct //顺序表
{
ElemType_SQL* data;
int length;
int listSize;
}SqList;
/*顺序表操作原型*/
Status InitList(SqList *L);
Status DestoryList(SqList *L);
Status ClearList(SqList *L);
Status ListEmpty(SqList *L);
int ListLength(SqList *L);
Status GetElem(SqList *L, int i, ElemType_SQL* e);
int LocateElem(SqList *L, ElemType_SQL e, Status(compare) (ElemType_SQL, ElemType_SQL));
Status PriorElem(SqList *L, ElemType_SQL cur_e, ElemType_SQL* pre_e);
Status NextElem(SqList *L, ElemType_SQL cur_e, ElemType_SQL* next_e);
Status ListInsert(SqList *L, int i, ElemType_SQL e);
Status ListDelete(SqList *L, int i, ElemType_SQL* e);
Status ListTraverse(SqList L, void(Visit)(ElemType_SQL));
Status CmpGreter(ElemType_SQL e, ElemType_SQL data);
void PrintElem(ElemType_SQL e);
/*原型函数实现*/
Status InitList(SqList *L)
/*初始化一个空表*/
{
L->data = (ElemType_SQL *)malloc(INIT_LIST_SIZE * sizeof(ElemType_SQL));
L->length = 0;
if (!(L->data)) return OVERFLOW;
L->listSize = INIT_LIST_SIZE;
return OK;
}
Status DestoryList(SqList *L)
/*销毁顺序表*/
{
if(!(L->data)) return ERROR;
free(L->data);
L->data = NULL;
L->length = 0;
L->listSize = 0;
return OK;
}
Status ClearList(SqList *L)
/*清空顺序表*/
{
if (L->data == 0) return ERROR;
L->length = 0;
return OK;
}
Status ListEmpty(SqList *L)
/*判断顺序表是否为空*/
{
return L->length == 0 ? TRUE : FALSE;
}
int ListLength(SqList *L)
/*返回顺序表长度*/
{
return L->length;
}
Status GetElem(SqList *L, int i, ElemType_SQL* e)
/* i位序元素赋值给*e */
{
if (i<1 || i>L->length) return ERROR;
*e = L->data[i - 1];
return OK;
}
int LocateElem(SqList *L, ElemType_SQL e, Status(* compare) (ElemType_SQL, ElemType_SQL))
/* 返回第一个满足compare的元素的位序 */
{
int i = 1;
ElemType_SQL *p = L->data;
while (i <= L->length && !(*compare)(e, *p++)) i++;
if (i <= L->length) return i;
else
{
printf("Not Found.");
return 0;
}
}
Status PriorElem(SqList *L, ElemType_SQL cur_e, ElemType_SQL* pre_e)
/* 返回cur_e的前驱 */
{
int i = 1;
if (L->data[0] != cur_e)
{
while (i <= L->length && L->data[i-1]!=cur_e) i++;
if (i <= L->length)
{
*(pre_e) = L->data[i - 2];
return OK;
}
}
printf("cur_e not found");
return ERROR;
}
Status NextElem(SqList *L, ElemType_SQL cur_e, ElemType_SQL* next_e)
/* 返回cur_e的后继 */
{
int i = 1;
while (i <= L->length && L->data[i - 1] != cur_e) i++;
if (i < L->length)
{
*(next_e) = L->data[i];
return OK;
}
printf("cur_e not found");
return ERROR;
}
Status ListInsert(SqList *L, int i, ElemType_SQL e)
/*在i位序插入元素e*/
{
ElemType_SQL* newbase, *p, *q;
if (i<1 || i>L->length + 1) return ERROR;
if (L->length >= L->listSize)
{
newbase = (ElemType_SQL*)realloc((*L).data, (L->listSize + LIST_INCREAMENT) * sizeof(ElemType_SQL));
if (!newbase) exit(OVERFLOW);
L->data = newbase;
L->listSize += LIST_INCREAMENT;
}
q = &(L->data[i - 1]);
for (p = &(L->data[L->length - 1]); p >= q; p--) *(p + 1) = (*p);
*q = e;
L->length++;
return OK;
}
Status ListDelete(SqList *L, int i, ElemType_SQL* e)
/* 删除i位序的元素将其赋值给*e */
{
if (i<1 || i>L->length) return ERROR;
*e = L->data[i - 1];
ElemType_SQL* p = &(L->data[i - 1]);
for (int j = i; j < L->length; j++)
{
*p = *(p + 1);
p++;
}
(*L).length--;
return OK;
}
Status ListTraverse(SqList L, void(*Visit)(ElemType_SQL))
/* 遍历顺序表,对其中所有元素调用visit */
{
int i;
for (i = 1; i <= L.length; i++)
Visit(L.data[i - 1]);
return OK;
}
Status CmpGreter(ElemType_SQL e, ElemType_SQL data)
{
return data > e ? TRUE : FALSE;
}
void PrintElem(ElemType_SQL e)
{
printf("%d ", e);
}
int main()
{
SqList L;
int i;
ElemType_SQL e;
printf("InitList测试\n");
printf("初始化顺序表L ...\n");
InitList(&L);
printf("\n");
printf("ListEmpty测试\n");
ListEmpty(&L) ? printf("L为空!!\n") : printf("L不为空!!\n");
printf("\n");
printf("ListInser测试\n");
for (i = 1; i <= 106; i++)
{
printf("在L的第%d位置插入%d\n", i, i*i);
ListInsert(&L, i, i*i);
}
printf("\n");
printf("\n");
printf("ListTraverse测试\n");
printf("L中的元素为:L=");
ListTraverse(L, PrintElem);
printf("\n");
printf("\n");
printf("GetElem测试\n");
GetElem(&L, 4, &e);
printf("L中的第4个元素为%d\n", e);
printf("\n");
printf("LocateElem测试\n");
i = LocateElem(&L, 30, CmpGreter);
printf("L中第一个大于30的元素位于%d\n", i);
printf("\n");
printf("PriorElem测试\n");
PriorElem(&L, 16, &e);
printf("16的前驱是%d\n", e);
printf("\n");
printf("NextElem测试\n");
i=NextElem(&L, 25, &e);
printf("25的后继是%d\n", e);
printf("\n");
printf("ClearList测试\n");
printf("清空前:\n");
ListEmpty(&L) ? printf("L为空!!\n") : printf("L不为空!");
ClearList(&L);
printf("清空后:\n");
ListEmpty(&L) ? printf("L为空!!\n") : printf("L不为空!");
printf("\n");
printf("DestoryList测试\n");
printf("销毁前:\n");
L.data ? printf("L存在!!\n") : printf("L不存在!!\n");
DestoryList(&L);
printf("销毁后:\n");
L.data ? printf("L存在!!\n") : printf("L不存在!!\n");
return 0;
}
运行结果:
InitList测试
初始化顺序表L ...
ListEmpty测试
L为空!!
ListInser测试
在L的第1位置插入1
在L的第2位置插入4
在L的第3位置插入9
在L的第4位置插入16
在L的第5位置插入25
在L的第6位置插入36
在L的第7位置插入49
在L的第8位置插入64
在L的第9位置插入81
在L的第10位置插入100
在L的第11位置插入121
在L的第12位置插入144
在L的第13位置插入169
在L的第14位置插入196
在L的第15位置插入225
在L的第16位置插入256
在L的第17位置插入289
在L的第18位置插入324
在L的第19位置插入361
在L的第20位置插入400
在L的第21位置插入441
在L的第22位置插入484
在L的第23位置插入529
在L的第24位置插入576
在L的第25位置插入625
在L的第26位置插入676
在L的第27位置插入729
在L的第28位置插入784
在L的第29位置插入841
在L的第30位置插入900
在L的第31位置插入961
在L的第32位置插入1024
在L的第33位置插入1089
在L的第34位置插入1156
在L的第35位置插入1225
在L的第36位置插入1296
在L的第37位置插入1369
在L的第38位置插入1444
在L的第39位置插入1521
在L的第40位置插入1600
在L的第41位置插入1681
在L的第42位置插入1764
在L的第43位置插入1849
在L的第44位置插入1936
在L的第45位置插入2025
在L的第46位置插入2116
在L的第47位置插入2209
在L的第48位置插入2304
在L的第49位置插入2401
在L的第50位置插入2500
在L的第51位置插入2601
在L的第52位置插入2704
在L的第53位置插入2809
在L的第54位置插入2916
在L的第55位置插入3025
在L的第56位置插入3136
在L的第57位置插入3249
在L的第58位置插入3364
在L的第59位置插入3481
在L的第60位置插入3600
在L的第61位置插入3721
在L的第62位置插入3844
在L的第63位置插入3969
在L的第64位置插入4096
在L的第65位置插入4225
在L的第66位置插入4356
在L的第67位置插入4489
在L的第68位置插入4624
在L的第69位置插入4761
在L的第70位置插入4900
在L的第71位置插入5041
在L的第72位置插入5184
在L的第73位置插入5329
在L的第74位置插入5476
在L的第75位置插入5625
在L的第76位置插入5776
在L的第77位置插入5929
在L的第78位置插入6084
在L的第79位置插入6241
在L的第80位置插入6400
在L的第81位置插入6561
在L的第82位置插入6724
在L的第83位置插入6889
在L的第84位置插入7056
在L的第85位置插入7225
在L的第86位置插入7396
在L的第87位置插入7569
在L的第88位置插入7744
在L的第89位置插入7921
在L的第90位置插入8100
在L的第91位置插入8281
在L的第92位置插入8464
在L的第93位置插入8649
在L的第94位置插入8836
在L的第95位置插入9025
在L的第96位置插入9216
在L的第97位置插入9409
在L的第98位置插入9604
在L的第99位置插入9801
在L的第100位置插入10000
在L的第101位置插入10201
在L的第102位置插入10404
在L的第103位置插入10609
在L的第104位置插入10816
在L的第105位置插入11025
在L的第106位置插入11236
ListTraverse测试
L中的元素为:L=1 4 9 16 25 36 49 64 81 100 121 144 169 196 225 256 289 324 361 400 441 484 529 576 625 676 729 784 841 900 961 1024 1089 1156 1225 1296 1369 1444 1521 1600 1681 1764 1849 1936 2025 2116 2209 2304 2401 2500 2601 2704 2809 2916 3025 3136 3249 3364 3481 3600 3721 3844 3969 4096 4225 4356 4489 4624 4761 4900 5041 5184 5329 5476 5625 5776 5929 6084 6241 6400 6561 6724 6889 7056 7225 7396 7569 7744 7921 8100 8281 8464 8649 8836 9025 9216 9409 9604 9801 10000 10201 10404 10609 10816 11025 11236
GetElem测试
L中的第4个元素为16
LocateElem测试
L中第一个大于30的元素位于6
PriorElem测试
16的前驱是9
NextElem测试
25的后继是36
ClearList测试
清空前:
L不为空!清空后:
L为空!!
DestoryList测试
销毁前:
L存在!!
销毁后:
L不存在!!
参考资料
严蔚敏 《数据结构(C语言描述)》