您的位置:首页 > 理论基础 > 数据结构算法

数据结构之线性表(一)

2014-01-12 20:24 323 查看
做为一个菜鸟,到今天才知道数据结构的重要性,这个是基础中的基础 。所以,决定立刻开始学习一下,经过一番搜索之后,自己还是从严蔚敏的《数据结构》C语言版入手。对于一个非计算机专业的学生来讲,补上这门课还是非常有必要的。如果单纯的看书,感觉自己可能学的东西比较肤浅,而且很快也会忘掉。因此,自己决定在看书的同时把书中的例子用程序全部实现,另一方面,也通过博客的形式来记录自己学习的脚步。当然,能够给大家提供一些帮助更好不过了。

首先来看线性表,线性表是最基础的。什么是线性表呢?线性表是n个数据元素的有限序列。n 被定义为线性表的长度,这里还要提到一个位序的概念,如果ai表示的是第i个数据元素,那么i称为ai在元素中的位序。 线性表其实是一种相当灵活的数据结构,它的长度可以根据需要增长或者缩短,即我们可以根据需要来对线性表删除或插入操作。

这一篇首先来讲顺序表,即最简单的一种表。线性表的顺序表示指的是用一组地址连续的存储单元依次存储线性表的数据元素。 线性表中数据之间的逻辑关系通过计算机内屋里位置相邻来表示,这个很容易让我们联想到数组,所以很容易被接受。由于是在物理空间中是连续存储的,所以,我们只需要知道顺序表的首地址,顺序表的长度,我们就可以表示出所有的元素。 学习数据结构,离不开抽象数据类型,下面将抽象数据类型的具体实现给出,供大家参考。对于线性表来说,下面是它的抽象数据类型:首先,我们必须要对数据对象(即线性表)进行定义,如下:

#define OK 1

#define OVERFLOW -2

#define ERROR 0

#define TRUE 1

#define FALSE 0

typedef int ElemType; typedef int Status;

#define LIST_INIT_SIZE 20 //the initial storage space

#define LISTINCREMENT 10 //the increment of the storage space

typedef struct

{

ElemType *elem; // the base address

int length; // the current length

int listsize; // the current storage space

}SqList;

然后,是基本操作的一些声明,如下:

Status InitList(SqList &List); //初始化线性表,获取一段内存

int ListLength(SqList List); //获取线性表的长度

Status GetElem(SqList &List, int i, int &e); //获取线性表中i所指向的位置的元素

//返回线性表中第一个与e满足compare()关系的位序
int LocateElem(SqList &List, int e, Status(*compare)(ElemType,ElemType));
Status ListInsert(SqList &List, int i, int e); //向线性表中位序为i的位置插入e
Status ListDelete_Sq(SqList &List, int i, ElemType &e);//删除线性表中位序为i的位置的元素
Status DestroyList(SqList &List); //删除线性表,删除线性表占用的内存
Status ClearList(SqList &List); //清空线性表,只是清空数据,但是内存没有被释放
Status ListEmpty(SqList List); //检测线性表是否为空表
Status PriorElem(SqList List, int cur_e, int &pre_e); // 返回线性表中cur_e元素的前一个元素,赋值给pre_e
Status NextElem(SqList List, int cur_e, int *next_e);//返回线性表中cur_e元素的后一个元素,赋值给next_e
Status ListTraverse(SqList &List, Status (*visit)(ElemType));//遍历整个线性表,对每个数据元素调用visit()函数

最后,是这些基本操作的实现,如下:
//初始化线性表
Status InitList(SqList &List)

{
List.elem = (ElemType *)malloc(LIST_INIT_SIZE * sizeof(ElemType));
if(!List.elem)
{
exit(OVERFLOW);
}
List.length = 0;
List.listsize = LIST_INIT_SIZE; //the initial storage capacity
return OK;
}
//插入操作
Status ListInsert(SqList &List, int i, int e)
{
ElemType *newbase,*q,*p;
//the valid i is 1=< i <= List.length+1
if(i < 1 || i > (List.length + 1))
{
return ERROR;
}/*end if(i<1 || i> List.length + 1)*/
//the current storage capacity is full
if(List.length >= List.listsize)
{
newbase = (ElemType *)realloc(List.elem,(List.listsize+LISTINCREMENT)*sizeof(ElemType));
if(!newbase)
{
exit(OVERFLOW);
}/*end if(!newbase)*/
List.elem = newbase;
List.listsize += LISTINCREMENT;
}/*end if(List.length >= List.listsize)*/
q = &(List.elem[i-1]);
for(p=&(List.elem[List.length-1]); p>=q;p--)
{
*(p+1) = *p;
}
*q = e;
List.length++; //notice that the current list length will not increase with the listsize, it depends on the actual elements
return OK;
}

//获取线性表的长度
int ListLength(SqList List)
{
return List.length;
}

//获取线性表中制定位序的元素
Status GetElem(SqList &List, int i, int &e)
{
//the valid i is 1=< i <= List.length+1
if(i<1 || i> List.length + 1)
{
return ERROR;
}/*end of if(i<1 || i> List.length + 1)*/
e = List.elem[i-1];
return OK;
}

//获得线性表中和e满足compare()关系的元素
int LocateElem(SqList &List, int e, Status(*compare)(ElemType,ElemType))
{
ElemType *p;
int i = 1;
p = List.elem;
while(i<=List.length && !compare(*p++,e))
{
i++;
}/*end of while(i<=List.length && !compare(*p,e))*/
if(i<=List.length)
{
return i;
}
else
{
return FALSE;
}
}

// 删除指定位序的元素
Status ListDelete_Sq(SqList &List, int i, ElemType &e)
{
ElemType *p,*q;
//judge the validation of i
if(i<1 || i>List.length)
{
return ERROR;
}
p = &(List.elem[i-1]);
e = *p;
q = List.elem+List.length-1; //get the position of the last element
for(p++;p<=q;p++)
{
*(p-1) = *p;
}
List.length--;
return OK;
}

//销毁线性表
Status DestroyList(SqList &List)
{
free(List.elem);
List.elem = NULL;
List.length = 0;
List.listsize = 0;
return OK;
}

//清空线性表,不释放内存
Status ClearList(SqList &List)
{
List.length = 0;
return OK;
}

//查看线性表是否为空表
Status ListEmpty(SqList List)
{
if(List.length == 0)
{
return TRUE;
}
else
{
return FALSE;
}
}

//获取线性表中cur_e的前一个元素
Status PriorElem(SqList List, int cur_e, int &pre_e)
{
int i;
for(i=1;i<=List.length;i++)
{
if((i!=1) && (List.elem[i-1] == cur_e))
{
pre_e = List.elem[i-2];
return OK;
}
}
return ERROR;
}

//获取线性表中cur_e的后一个元素
Status NextElem(SqList List, int cur_e, int *next_e)
{
int i = 1;
// notice that i should not be greater than the list's length
while((i<List.length)&&(List.elem[i-1] != cur_e))
{
i++;
}
if(i == List.length)
{
return ERROR;
}
else
{
(*next_e) = List.elem[i];
return OK;
}
}
//遍历线性表,对每个数据元素调用函数visit()
Status ListTraverse(SqList &List, Status(*visit)(ElemType))
{
int i = 1;
while(i<=List.length)
{
visit(i);
i++;
}
return OK;
}


至此,顺序表的抽象数据类型基本操作就全部完成了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: