顺序表
简而言之,用数组表示线性关系
基本结构
//函数结果状态代码
#define TRUE 1
#define FALUSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
typedef int DataType; /*数据类型*/
typedef int ElemType; /*元素类型*/
//--------------线性表的动态顺序存储结构------------
#define LIST_INIT_SIZE 100 //线性表存储空间的初始分配量
#define LISTINCREMENT 10 //线性表存储空间的分配增量
typedef struct
{
ElemType *elem; //存储空间地址,动态改变所指内存的大小
int length; //当前长度
int listsize; //当前分配的存储容量
}SqList;
函数
- 初始化
void InitList(SqList *L)
//给链表分配初始内存空间,并对长度,大小进行初始化
{
L->elem = (ElemType *)malloc(LIST_INIT_SIZE*sizeof(ElemType));//分配空间
if(!L->elem)
exit(OVERFLOW); //存储分配失败
L->length = 0; //空表的长度为0
L->listsize = LIST_INIT_SIZE; //初始容量
}
void* realloc(void* ptr, unsigned newsize);
参数说明:
给一个已经分配了地址的指针重新分配空间,参数ptr为原有的空间地址,newsize是重新申请的地址长度.
理解:
realloc可以对给定的指针所指的空间进行扩大或者缩小,无论是扩张或是缩小,原有内存的中内容将保持不变.当然,对于缩小,则被缩小的那一部分的内容会丢失.realloc并不保证调整后的内存空间和原来的内存空间保持同一内存地址.相反,realloc返回的指针很可能指向一个新的地址
- 插入元素
void ListInsert(SqList *L, int i, ElemType e)
//在第i位置处插入e
//最小插入表头,位置为第i个
//最大插入表位,位置为第L.length+1
{
if(L->length >= L->listsize) //当前存储空间已满,扩容
{
ElemType *newbase = (ElemType*)realloc(L->elem,
(L->listsize+LISTINCREMENT)*sizeof(ElemType));
if(!newbase)
exit(OVERFLOW);
L->elem = newbase; //新基址
L->listsize += LISTINCREMENT; //增加容量
}
ElemType *q = &(L->elem[i-1]); //插入位置地址
ElemType *p = &(L->elem[L->length-1]);//最后一个位置的地址
while(p >= q) //插入位置及之后的元素向后移动
{
*(p+1) = *p;
p--;
}
*q = e;
++L->length;
}
- 删除元素
void ListDelete(SqList *L, int i, ElemType *e)
//删除第i个元素,并用e返回值
//最小插入表头,位置为第i个
//最大插入表位,位置为第L.length
{
ElemType *p = &(L->elem[i-1]);
ElemType *q = L->elem+L->length-1; //表尾位置
*e = *p;
for(++p; p <= q; ++p) //插入位置之后像左移动
{
*(p-1) = *p;
}
--L->length;
}
- 寻找元素
int cmp(ElemType a, ElemType b)
//判断两个元素是否相等
{
return a == b;
}
int LocateElem(SqList *L, ElemType e, int(*cmp)(ElemType, ElemType))
//查找第1个值与e相同cmp()的元素的位序
//若找到,则返回e在L中的位序,否则返回0
{
int i = 1; //初值为第一个元素的位序
ElemType *p = L->elem; //初值为第一个元素的地址
while(i <= L->length && !cmp(*p++, e))
++i;
if(i <= L->length)
return i;
else
return 0;
}
- 归并有序表
void ListMerge(SqList *La, SqList *Lb, SqList *Lc)
//La, Lb的元素按值非递减排列
//归并La,Lb得到Lc,按非递减排列
{
ElemType *pa = La->elem;
ElemType *pb = Lb->elem;
Lc->listsize = Lc->length = La->length+Lb->length;
ElemType *pc = Lc->elem = (ElemType*)malloc(Lc->listsize*sizeof(ElemType));
if(!Lc->elem)
exit(OVERFLOW);
ElemType *pa_last = La->elem+La->length-1;
ElemType *pb_last = Lb->elem+Lb->length-1;
while(pa <= pa_last && pb <= pb_last) //归并
{
if(*pa <= *pb)
*pc++ = *pa++;
else
*pc++ = *pb++;
}
while(pa <= pa_last) //插入La的剩余部分
*pc++ = *pa++;
while(pb <= pb_last) //插入Lb的剩余部分
*pc++ = *pb++;
}
测试代码
#include <stdio.h>
#include <stdlib.h>
//函数结果状态代码
#define TRUE 1
#define FALUSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
typedef int DataType; /*数据类型*/
typedef int ElemType; /*元素类型*/
//--------------线性表的动态顺序存储结构------------
#define LIST_INIT_SIZE 100 //线性表存储空间的初始分配量
#define LISTINCREMENT 10 //线性表存储空间的分配增量
typedef struct
{
ElemType *elem; //存储空间基址
int length; //当前长度
int listsize; //当前分配的存储容量
}SqList;
void InitList(SqList *L)
//初始化
{
L->elem = (ElemType *)malloc(LIST_INIT_SIZE*sizeof(ElemType));//分配空间
if(!L->elem)
exit(OVERFLOW); //存储分配失败
L->length = 0; //空表的长度为0
L->listsize = LIST_INIT_SIZE; //初始容量
}
void ListInsert(SqList *L, int i, ElemType e)
//在第i位置处插入e
//最小插入表头,位置为第i个
//最大插入表位,位置为第L.length+1
{
if(L->length >= L->listsize) //当前存储空间已满,扩容
{
ElemType *newbase = (ElemType*)realloc(L->elem,
(L->listsize+LISTINCREMENT)*sizeof(ElemType));
if(!newbase)
exit(OVERFLOW);
L->elem = newbase; //新基址
L->listsize += LISTINCREMENT; //增加容量
}
ElemType *q = &(L->elem[i-1]); //插入位置地址
ElemType *p = &(L->elem[L->length-1]);//最后一个位置的地址
while(p >= q) //插入位置及之后的元素向后移动
{
*(p+1) = *p;
p--;
}
*q = e;
++L->length;
}
void ListDelete(SqList *L, int i, ElemType *e)
//删除第i个元素,并用e返回值
//最小插入表头,位置为第i个
//最大插入表位,位置为第L.length
{
ElemType *p = &(L->elem[i-1]);
ElemType *q = L->elem+L->length-1; //表尾位置
*e = *p;
for(++p; p <= q; ++p) //插入位置之后像左移动
{
*(p-1) = *p;
}
--L->length;
}
int cmp(ElemType a, ElemType b)
//判断两个元素是否相等
{
return a == b;
}
int LocateElem(SqList *L, ElemType e, int(*cmp)(ElemType, ElemType))
//查找第1个值与e相同cmp()的元素的位序
//若找到,则返回e在L中的位序,否则返回0
{
int i = 1; //初值为第一个元素的位序
ElemType *p = L->elem; //初值为第一个元素的地址
while(i <= L->length && !cmp(*p++, e))
++i;
if(i <= L->length)
return i;
else
return 0;
}
void ListMerge(SqList *La, SqList *Lb, SqList *Lc)
//La, Lb的元素按值非递减排列
//归并La,Lb得到Lc,按非递减排列
{
ElemType *pa = La->elem;
ElemType *pb = Lb->elem;
Lc->listsize = Lc->length = La->length+Lb->length;
ElemType *pc = Lc->elem = (ElemType*)malloc(Lc->listsize*sizeof(ElemType));
if(!Lc->elem)
exit(OVERFLOW);
ElemType *pa_last = La->elem+La->length-1;
ElemType *pb_last = Lb->elem+Lb->length-1;
while(pa <= pa_last && pb <= pb_last) //归并
{
if(*pa <= *pb)
*pc++ = *pa++;
else
*pc++ = *pb++;
}
while(pa <= pa_last) //插入La的剩余部分
*pc++ = *pa++;
while(pb <= pb_last) //插入Lb的剩余部分
*pc++ = *pb++;
}
void ListTraverse(SqList *L)
{
int n = L->length, i;
for(i = 0; i < n; i++)
printf("%d ", L->elem[i]);
printf("\n");
}
int main()
{
SqList La, Lb, Lc;
InitList(&La);
InitList(&Lb);
ListInsert(&La, 1, 1);
ListInsert(&La, 2, 2);
//ListInsert(&La, 3, 3);
ListInsert(&La, 3, 4);
ListTraverse(&La);
ListInsert(&Lb, 1, 1);
ListInsert(&Lb, 2, 2);
ListInsert(&Lb, 3, 3);
ListInsert(&Lb, 4, 4);
ListTraverse(&Lb);
int e;
ListInsert(&La, 3, 3);
ListDelete(&La, 2, &e);
ListTraverse(&La);
ListMerge(&La, &Lb, &Lc);
ListTraverse(&Lc);
printf("%d",LocateElem(&Lc, 2,cmp));
return 0;
}