本章的基本内容是:
2.1 线性表的逻辑结构
(一)线性表的定义其中,ai(1≤i≤n)称为数据元素;
下角标 i 表示该元素在线性表中的位置或序号 。
(二)线性表的特性1. 有限性:线性表中数据元素的个数是有穷的。
2、相同性:线性表中数据元素的类型是同一的。
3. 顺序性:线性表中相邻的数据元素ai-1和ai之间存在序偶关系(ai-1, ai),即ai-1是ai的前驱, ai是ai-1的后继;a1无前驱,an无后继,其它每个元素有且仅有一个前驱和一个后继。
(三)线性表的抽象数据类型定义ADT List
Data
线性表中的数据元素具有相同类型,
相邻元素具有前驱和后继关系
Operation
InitList
前置条件:表不存在
输入:无
功能:表的初始化
输出: 无
后置条件:建一个空表
DestroyList
前置条件:表已存在
输入:无
功能:销毁表
输出:无
后置条件:释放表所占用的存储空间
Length
前置条件:表已存在
输入:无
功能:求表的长度
输出:表中数据元素的个数
后置条件:表不变
lf�lcpc9�1or-index:1;mso-font-kerning:12.0pt;language:zh-CN;font-weight:bold'>无后继,其它每个元素有且仅有一个前驱和一个后继。Get
前置条件:表已存在
输入:元素的序号i
功能:在表中取序号为i的数据元素
输出:若i合法,返回序号为i的元素值,否则抛出异常
后置条件:表不变
Locate
前置条件:表已存在
输入:数据元素x
功能:在线性表中查找值等于x的元素
输出:若查找成功,返回x在表中的序号,否则返回0
后置条件:表不变
Insert
前置条件:表已存在
输入:插入i;待插x
功能:在表的第i个位置处插入一个新元素x
输出:若插入不成功,抛出异常
后置条件:若插入成功,表中增加一个新元素
Delete
前置条件:表已存在
输入:删除位置i
功能:删除表中的第i个元素
输出:若删除成功,返回被删元素,否则抛出异常
后置条件:若删除成功,表中减少一个元素
Empty
前置条件:表已存在
输入:无
功能:判断表是否为空
输出:若是空表,返回1,否则返回0
后置条件:表不变
ADT
(四)存储结构和存取结构
1、存储结构是数据及其逻辑结构在计算机中的表示;
存取结构是在一个数据结构上对查找操作的时间性能的一种描述。
2、“顺序表是一种随机存取的存储结构”的含义为:在顺序表这种存储结构上进行的查找操作,其时间性能为O(1)。
2.2 线性表的顺序存储结构及实现
顺序表类的声明constintMaxSize=100;
template<class DataType> //模板类
classSeqList
{
public:
SeqList( ) ; //构造函数
SeqList(DataType a[ ], int n);
~SeqList( ) ; //析构函数
int Length( );
DataType Get(inti);
int Locate(DataType x );
void Insert(inti, DataType x);
DataType Delete(inti);
private:
DataType data[MaxSize];
int length;
};
(一)顺序表的实现——无参构造函数操作接口:SeqList( )
算法描述:
SeqList<DataType>::SeqList( )
{
length = 0;
}(二)顺序表的实现——有参构造函数
操作接口:SeqList(DataType a[ ], int n)
算法描述:
template <class DataType>
SeqList<DataType> ::SeqList(DataType a[ ], int n)
{
if (n > MaxSize) throw "参数非法";
for (i = 0; i < n; i+ +)
data[i] = a[i];
length = n;
}
(三)顺序表的实现——插入
操作接口: void Insert(int i, DataType x)
算法描述——伪代码
1. 如果表满了,则抛出上溢异常;
2. 如果元素的插入位置不合理,则抛出位置异常;
3. 将最后一个元素至第i个元素分别向后移动一个位置;
4. 将元素x填入位置i处;
5. 表长加1;
算法描述——C++描述
template<class DataType>
void SeqList<DataType>::Insert(int i, DataType x)
{
if (length >= MaxSize) throw "上溢";
if (i < 1 || i > length + 1) throw "位置";
for (j = length; j >= i; j--)
data[j] = data[j-1];
data[i-1] = x;
length++;
}
时间性能分析
最好情况( i=n+1):
基本语句执行0次,时间复杂度为O(1)。
最坏情况( i=1):
基本语句执行n+1次,时间复杂度为O(n)。
平均情况(1≤i≤n+1):时间复杂度为O(n)。
(四)顺序表的实现——删 除
操作接口: DataType Delete(int i)
(五)顺序表的实现——按位查找
操作接口: DataType Get(inti)
算法描述:
template <class DataType>
DataType SeqList<DataType>::Get( int i )
{
if (i >= 1 && i <= length)return a[i-1];
}
(六)顺序表的实现——按值查找
操作接口: int Locate(DataType x )
算法描述:
template <class DataType>
int SeqList<DataType>::Locate(DataType x)
{
for (i = 0; i < length; i++)
if (data[i] == x) return i + 1;
return 0;
}
(七)顺序表的优缺点
⑴无需为表示表中元素之间的逻辑关系而增加额外的存储空间;
⑵随机存取:可以快速地存取表中任一位置的元素。
⑴ 插入和删除操作需要移动大量元素;
⑵ 表的容量难以确定,表的容量难以扩充;
⑶ 造成存储空间的碎片。
2.3 线性表的链接存储结构及实现
单链表
单链表:线性表的链接存储结构。
存储思想:用一组任意的存储单元存放线性表的元素。
单链表是由若干结点构成的;
单链表的结点只有一个指针域。
(一)单链表的结点结构:
template<class DataType>
struct Node
{
DataType data;
Node<DataType>*next;
};
头指针:指向第一个结点的地址。
尾标志:终端结点的指针域为空。
(二)单链表类的声明:
template<class DataType>
classLinkList
{
public:
LinkList( );
LinkList(DataType a[ ], int n);
~LinkList( );
int Length( );
DataType Get(inti);
int Locate(DataType x);
void Insert(inti, DataType x);
DataType Delete(inti);
void PrintList( );
private:
Node<DataType>*first;
};
(三)单链表的实现——遍历操作
操作接口:void PrintList( );
template <class DataType>
void LinkList<DataType> :: PrintList( )
{
p =first->next;
while (p != NULL)
{
cout << p->data;
p =p->next;
}
}
(四)单链表的实现——按位查找
操作接口:DataType Get(inti);
算法描述——C++描述
template <class T>
T LinkList<T>::Get(int i)
{
Node<T> *p; int j;
p=first->next; j=1; //或p=first; j=0;
while (p &&j<i)
{
p=p->next; //工作指针p后移
j++;
}
if (!p) throw "位置";
else returnp->data;
}
(五)单链表的实现——按值查找
算法描述——C++描述
template <class DataType>
int LinkList<DataType>:: Locate(DataType x)
{
p =first->next; count = 1;
while (p != NULL)
{
if (p->data== x) return count; //查找成功,返回序号
p =p->next;
count++;
}
return 0; //退出循环表明查找失败
}
-kj�n:ps�nguage:zh-CN;font-weight:bold'>位置";else returnp->data;
}
(六)单链表的实现———插入
操作接口:voidInsert(inti, DataType x);
算法描述:
template <class DataType>
void LinkList<DataType> :: Insert(int i, DataType x)
{
p = first ; count= 0; //工作指针p应指向头结点
while (p != NULL && count < i - 1) //查找第i – 1个结点
{
p =p->next;
count++;
}
if (p == NULL)throw "位置"; //没有找到第i – 1个结点
else {
s = newNode; s->data = x; //申请一个结点s
s->next =p->next; p->next = s; //结点s插入结点p之后
}
}
(七)单链表的实现———构造函数
操作接口:LinkList(DataType a[ ], int n)
头插法:将待插入结点插在头结点的后面 。
算法描述:
template <class DataType>
LinkList<DataType> :: LinkList(DataType a[ ], int n)
{
first = new Node;first->next = NULL;
for (i = 0; i < n; i++)
{
s = new Node;s->data = a[i];
s->next = first->next;
first->next= s;
}
}
尾插法:将待插入结点插在终端结点的后面。
算法描述:
template <class DataType>
LinkList<DataType> :: LinkList(DataType a[ ], int n)
{
first = newNode; //生成头结点
r = first; //尾指针初始化
for (i = 0; i < n; i++)
{
s = new Node;s->data = a[i];
r->next = s; r = s;
}
r->next =NULL;
}
(八)单链表的实现———删除
操作接口:DataType Delete(inti);
算法描述:
template <class DataType>
DataType LinkList<DataType>:: Delete(int i)
{
p = first ; count= 0;
while (p != NULL && count < i - 1)
{
p =p->next;
count++;
}
if (p == NULL ||p->next == NULL) throw "位置";
else {
q =p->next; x = q->data;
p->next =q->next;
delete q;return x;
}
}
(九)单链表的实现——析构函数
操作接口:~LinkList( );
算法描述:
template <class DataType>
LinkList<DataType> :: ~LinkList( )
{
while (first !=NULL)
{
q =first;
first = first->next;
delete q;
}
}
循环链表
(一)循环链表——插入
算法描述:
template <class DataType>
void LinkList<DataType> ::Insert(int i, DataType x)
{
p = first ; count = 0;
while (p!= first && count < i - 1)
{
p =p->next;
count++;
}
if (p == NULL)throw "位置";
else {
s = newNode<DataType>;s->data = x;
s->next =p->next; p->next = s;
}
}
双链表
双链表:在单链表的每个结点中再设置一个指向其前驱结点的指针域。
结点结构:
data:数据域,存储数据元素;
prior:指针域,存储该结点的前趋结点地址;
next:指针域,存储该结点的后继结点地址。
(一)双链表的操作——插入
操作接口:voidInsert(DulNode<DataType> *p,DataType x);
(二)双链表的操作——删除
操作接口:DataType Delete(DulNode<DataType>*p);
2.4 顺序表和链表的比较
(一)存储分配方式比较
(二)时间性能比较
时间性能是指实现基于某种存储结构的基本操作(即算法)的时间复杂度。
按位查找:
插入和删除:
(三)空间性能比较
空间性能是指某种存储结构所占用的存储空间的大小。
定义结点的存储密度:
结点的存储密度:
静态链表
静态链表:用数组来表示单链表,用数组元素的下标来模拟单链表的指针。
data:存储放数据元素;
next:也称游标,存储该元素的后继在数组的下标。
静态链表的存储结构定义如下:
const int MaxSize = 100; //100只是示例数据
template <class DataType>
struct SNode
{
DataType data; // DataType表示不确定的数据类型
int next; //指针域(也称游标)
} SList[MaxSize];