第二章 线性表
2.1线性表的逻辑结构
2.2线性表的顺序存储结构及实现
2.3线性表的链式存储结构及实现
2.4顺序表和单链表的比较
2.5线性表的其他存储方法
2.1线性表的逻辑结构
线性表( Linear List )的定义
线性表是零个或多个具有相同类型的数据元素的有限序列。
数据元素的个数定义为线性表的长度 。长度等于零时称为空表,一个非空表通常记为
L = ( a 1 , a 2 ,……, a n )
其中, a i ( 1 ≤ i ≤ n )称为数据元素
下标 i 表示该元素在线性表中的位置或序号, 称元素 a i 位于表的第 i 个位置,或称 a i 是表中的第 i 个元素。
2.2线性表的顺序存储结构及实现
顺序表
特点:线性表的顺序存储是指用一组地址连续的存储单元依次存储线性表中的各个元素,
作用:线性表中在逻辑结构上相邻的数据元素存储在相邻的物理存储单元中,即通过数据元素物理存储的相邻关系来反映数据元素之间逻辑上的相邻关系。
顺序存储的实现:一维数组存储顺序表中的数据。
顺序表的实现
const int Maxsize=100;
template <class T>
class SeqList{
private:
T data[MaxSize]; // 存放数据元素的数组
int length; // 线性表的长度
public:
SeqList ( ) ;// 无参构造函数
SeqList ( T a[ ], int n ) ; // 有参构造函数
~SeqList( ) { } // 析构函数为空
int Length ( ) {return length;} // 求线性表的长度
T Get ( int i ); // 按位查找,取线性表的第 i 个元素
int Locate ( T x ) ; // 按值查找,求线性表中值为 x 的元素序号
void Insert ( int i, T x ) ; // 在线性表中第 i 个位置插入值为 x 的元素
T Delete ( int i ) ; // 删除线性表的第 i 个元素
void PrintList ( ) ; // 遍历线性表,按序号依次输出各元素
};
2.3线性表的链式存储结构及实现
链式存储分配的特点:根据线性表的长度动态的申请存储空间,以解决顺序存储中存在的存储空间难以确定的问题。
链式存储结构的实现
单链表
双向链表
循环链表等
单链表的实现
template <class T>
class LinkList {
public:
LinkList ( ) {first=new Node<T>; first -> next= NULL ;}
LinkList ( T a[ ], int n ) ;
~LinkList ( ) ;
int Length ( ) ;
T Get ( int i ) ;
int Locate ( T x ) ;
void Insert ( int i, T x ) ;
T Delete ( int i ) ;
void PrintList ( ) ;
private:
Node<T> *first; // 单链表的头指针 , <T>可以省略
};
头插法尾插法
//头插法
template <class T>
LinkList<T>:: LinkList(T a[ ], int n) {
first=new Node<T>; //生成头结点
first->next=NULL;
Node<T> *s;
for (int i=0; i<n; i++){
s=new Node<T>;
s->data=a[i]; //为每个数组元素建立一个结点
s->next=first->next;
first->next=s;
}
}
//尾插法
template <class T>
LinkList<T>:: LinkList(T a[ ], int n) {
Node<T> *r,*s; //尾指针
first=new Node<T>; //生成头结点
r=first;
for (int i=0; i<n; i++) {
s=new Node<T>;
s->data=a[i]; //为每个数组元素建立一个结点
r->next=s; r=s; //插入到终端结点之后
}
r->next=NULL; //单链表建立完毕,将终端结点的指针域置空
}
2.4顺序表和单链表的比较
1.顺序表是由向量实现的,它是一种随机存取结构,对表中任一结点都可以在O(1)时间内直接地存取,
而链表中的结点, 需从头指针起顺着链找才能取得。
结论: 若线性表的操作主要是进行查找,很少做插入和删除时,宜采用顺序表做存储结构。
2.在链表中的任何位置上进行插入和删除,都只需要修改指针。
而在顺序表中进行插入和删除,平均要移动表中近一半的结点,尤其是当每个结点的信息量较大时,移动结点的时间开销就相当可观。
结论:因此,对于频繁进行插入和删除的线性表, 宜采用链表做存储结构。
2.5 线性表的其他存储方法
1.循环链表
template <class T>
class CycleLinkList{
public:
CycleLinkList( );
CycleLinkList(T a[ ], int n);
CycleLinkList(T a[ ], int n,int i);
~CycleLinkList();
int Length();
T Get(int i);
void Insert(int i, T x);
T Delete(int i);
void PrintList( );
private:
Node<T> *first;
};
2.双链表
template <class T>
class DoubleLink {
private:
Node<T> *head;
public:
DoubleLink() ;
~DoubleLink();
void Append(T data);
void Display();
void Insert(int locate , T data);
T Get(int locate);
T Delete(int locate);
};
3.静态链表
//静态链表同样可以借助一维数组来描述:
#define Maxsize=链表可能达到的最大长度
template<class T>
structNode{
ElemType data;
int next;
};
间接寻址
线性表的顺序存储的优点:支持随机访问。
线性表的链式存储的优点:插入和删除数据时不需要移动数据。
间接寻址:将指针和数组结合起来的一种方法,它将数组中的存储数据元素的单元改为存储指向该元素的指针。