大话数据结构与算法-程杰
线性表的定义
零个或多个数据元素的有限序列。
这里需要强调几个关键的地方:
线性表的顺序存储结构
#define MAXSIZE 20 // 存储空间出事分配量
typedef int ElmType; // ElmType类型根据实际情况而定,这里假设为int
typedef struct
{
ElmType data[MAXSIZE]; // 数据存储数据元素,最大值为MAXSIZE
int length; // 线性表当前长度
}SqList;
这里,我们发现描述顺序存储结构需要的三个属性:
<1> 存储空间的起始位置:数据data,它的存储位置就是存储空间的存储位置;
<2> 线性表的最大存储容量:数组长度MAXSIZE;
<3> 线性表的当前长度:length
3. 数据长度与线性表长度区别
数组的长度是存放线性表的存储空间的长度,存储分配后这个量一般是不变的。有个别人可能会问,数组的大小一定不可以变吗?我怎么看有些书中谈到可以动态分配的一维数组。是的,一般高级语言,比如C、C++、VB都可以用编程手段实现分配数组,不过会带来性能上的损耗。
线性表的长度是线性表中数据元素的个数,随着线性表插入和删除操作的进行,这个量是改变的。
任意时刻,线性表的长度应该小于等于数组的长度。
4. 顺序存储结构的基本操作
ADT 线性表(List)
Data
线性表的数据对象集合为{a1, a2, …, an},每个元素的类型为DataType。其中,除第一个元素a1外,每一个元素有且只有一个前驱元素,除了最后一个元素an外,每一个元素有且只有一个直接后继元素。数据元素之间的关系是一对一的关系。
Operation
int InitList (SqList *L); /** 初始化一个顺序表 **/
bool ListEmpty (L); /** 若线性表为空,返回true,否则返回false **/
int printList (SqList L); /** 打印线性表中的每一个元素 **/
int getlength (SqList L); /** 返回线性表元素的个数 **/
/** 创建一个链表长度为length的线性表 **/
int createList (SqList *L,int length);
/** 在线性表的第pos个位置插入 一个新元素elem **/
int insertList (SqList *L, int pos,ElemType elem);
/** 将线性表中第pos个位置的元素返回,保存在*e中 **/
int getElem (SqList L, int pos, ElemType *e);
/** 在线性表中查找与给定元素e相等的元素,如果有相同的返回状态值1,
如果没有,返回状态值0 **/
int locateElem (SqList L, ElemType e);
/** 从线性表中删除pos位置处的元素,并将其存放在elem中; **/
int deleteList (SqList *L, int pos,ElemType *elem);
int clearList (SqList L,SqList *pL); /** 清空顺序表 **/
<一> 初始化一个顺序表
int initList (SqList *L)
{
L->length=0;
return 1;
}
<二> 判断线性表是否为空
bool ListEmpty (L)
{
if (L.length == 0)
return false;
return true;
}
<三> 打印线性表中的每一个元素
int printList (SqList L)
{
// 线性表是否为空
if (L.length==0)
return 0;
for (int i=0; i
<四> 返回线性表元素的个数
int getlength (SqList L)
{
return L.length;
}
<五> 创建一个链表长度为length的线性表
int createList (SqList *L,int length)
{
srand(time(0));
int i;
for (i=0;idata[i]=rand()%100;// 插入随机数
L->length++;
}
return 1;
}
<六> 指定位置pos处插入一个新的元素elem
插入算法思路:
A. 如果插入元素不合理,抛出异常;
B. 如果线性表长度大于数组长度,则抛出异常或动态增加容量;
C. 从最后一个元素开始遍历到第i个位置,分别将它们都向后移动一个位置;
D. 将要插入元素填入第i个位置;
E. 表长度加1。
int insertList (SqList *L, int i,ElemType elem)
{
if (L->length == MAXSIZE) // 顺序表已满
return 0;
if (pos<1 || pos>L->length) // 当pos不在范围内
return 0;
if (poslength)
{
for (int i=L->length-1;i>=pos-1;i--)
{// 将要插入位置后数据往后移动一个位置
L->data[i+1]=L->data[i];
}
}
L->data[pos-1] = elem; // 将新元素插入
L->length++;
return 1;
}
<七> 获取顺序表中指定位置处的元素值
int getElem (SqList L, int pos, ElemType *e)
{
if (pos<1 || pos>L.length)
return 0;
*e = L.data[pos-1];
return 1;
}
<八> 查找在线性表中是否含有指定元素
int locateElem (SqList L, ElemType e)
{
for (int i=0;i
<九> 删除顺序表中指定位置处的元素
删除算法的思路:
A. 如果删除位置不合理,抛出异常;
B. 取出要删除的元素;
C. 从删除元素位置开始遍历到最后一个元素,分别将它们都向前移动一个位置;
D. 表长度减去1.
int deleteList (SqList *L, int pos,ElemType *elem)
{
if (L->length == 0) //线性表为空
return 0;
if (pos<1 || pos>L->length) // 删除位置不合理
return 0;
*elem = L->data[pos-1];
if (poslength) // 如果删除不是最后位置
{
for (int i=pos;ilength;i++)
{
L->data[i-1]=L->data[i]; // 将删除位置后继元素前移
}
}
L->length --;
return 1;
}
<十> 清空一个顺序表,将顺序表的length置为0
int clearList (SqList L,SqList *pL)
{
L.length=0;
pL->length=0;
return 1;
}
顺序表的优点为:随机访问较快,创建简单。
缺点为:插入和删除需要移动大量的元素;表的容量难以确定;造成存储空间的“碎片”等。