一、概念
线性结构的特点是:在数据元素的非空有限集中,(1)存在唯一的一个被称做“第一个”的数据元素;(2)存在唯一的一个被称作“最后一个”的数据元素;(3)除第一个之外,集合中的每个数据元素均只有一个前驱;(4)除最后一个数据之外,集合中每个数据元素均只有一个后继。
二、线性表的应用实例
例1:假设利用两个线性表LA和LB分别表示两个集合A和B(即:线性表中的数据元素即为集合中的成员,聚合中没有相同的元素),求一个新的集合A=AUB。
void Union(List &LA,List &LB)
{
int iLenA = ListLen(LA);int iLenB = ListLen(LB);//求线性表的长度
for(int i = 0; i < iLenB; ++i)
{
GetElem(LB, i, e);//依次获取LB中的元素
if(!LocateElem(La, e, equal))ListInsert(LA, ++iLenA, e);//将LB中的元素与LA中元素进行比较,如果在LA中不存在,则插入到LA中
}
}
时间复杂度为:O(T) = O(iLenA*iLenB)
例二:归并LA和LB到LC中。(LA、LB中的数据按值非递减有序排列,里面可能有重复的值,要求LC也一样)
void MergeList(LA, LB, LC)
{
InitList(LC);
i = j = 0; k = 0;
iLenA = ListLength(LA);iLenB = ListLength(LB);
while(i < iLenA-1 && j < iLenB-1)
{
GetElem(LA, i , a);GetElem(LB, j, b);
if(a < b){ ListInsert(LC, ++k, a);++i; }
else{ListInsert(LC, ++k; b);++j; }
}
while(i < LA-1)
{GetElem(LA, i++ , a); ListInsert(LC, ++k, a);}
while(j < LB-1)
{GetElem(LB, j++ , b); ListInsert(LC, ++k,b); }
}
时间复杂度为O(T) = O(iLenA+iLenB);
三、线性表的顺序表示和实现
线性表的顺序表示指的是用一组地址连续的存储单元依次存储线性表的数据元素。线性表的这种机内表示称作线性表的顺序存储结构或顺序映象,反之,称这种存储结构的线性表为顺序表。
3.1 顺序存储线性表:
线性表的动态分配顺序存储结构的表示:
#define LIST_INIT_SIZE 100//线性表存储空间的初始分配量
#defime LISTINCREMENT 10 //线性表存储空间的分配增量
typedef struct {
ElemType *elem; //存储空间基地址
int iLength; //当前长度
int iListSize; //当前分配的存储容量(以sizeof(ElemType)为单位)
}
常见操作的复杂度:
插入、删除的时间复杂度都为O(length)
求表长、取第i个数据元素的时间复杂度为O(1)
LocateElem的时间复杂度为O(length),查找某个元素是否在线性表中
转自http://blog.csdn.net/agul_/article/details/8634619
1.线性表的定义:零个或多个相同类型的数据元素的有限序列。若元素为多个,则第一个元素无前驱,最后一个元素无后继,其他的每个元素都有且只有一个前驱和后继。线性表中的每个数据元素可以由若干个数据项组成,这时,数据元素称为记录record,线性表称为文件file。
2.线性表的抽象数据类型:
线性表是一种数据结构,其元素之间存在一一对应的逻辑关系{D,S}。D表示数据元素,S表示数据元素之间的关系。
线性表的抽象数据类型{D,S,P},其中{D,S}表示数据结构,P表示数据结构上的一组操作。
3.线性表的物理结构
3.1顺序存储结构:用一段地址连续的存储单元一次存储线性表的数据元素。C语言中用数组为例。
(1)描述线性表需要三个属性:存储空间的起始位置,线性表的最大存储容量(数组长度,即总的存储空间的长度),线性表的当前长度(线性表中数据元素的个数)。
(2)随机存取结构:LOC(ai)=LOC(a1)+(i-1)c;存取操作的时间复杂度为O(1)。
(3)插入:检验当前的list的长度是否超过定义的数组最大长度,检验插入的位置是否合理(插入第i个之前,因此i可以取length+1),移位(若插入的不在表尾),插入,表长加1。
(4)删除:检验list是否为空表,检验删除的位置是否合理,赋值,(若删除的不在表尾)移位,表长-1。
(5)时间复杂度:存取操作O(1),插入删除O(n)。插入平均移动次数为n/2,删除平均移动次数为(n-1)/2。
(6)顺序存储优点:无需表示元素之间的逻辑关系而额外增加存储空间。可以快速存取。
顺序存储缺点:删除插入操作需要大量移动元素。当线性表长度变化较大时,难以确定存储空间的容量。造成存储空间的碎片。
适用:元素个数不太变化,更多是存取数据的应用。
线性表的顺序存储结构用一维数据实现。
优点:
1.无须为表示表中元素之间的逻辑关系而增加额外的存储空间
2.可以快速地存取表中任意位置的元素
缺点:
1.插入和删除操作需要移动大量的元素。
2.当线性表长度变化较大时,难以确定存储空间的容量。
3.造成存储空间的“碎片”
"Common.h"
- #ifndef COMMON_H_INCLUDED
- #define COMMON_H_INCLUDED
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <stdarg.h>
- #define TRUE 1
- #define FALSE 0
- #define OK 1
- #define ERROR 0
- #define INFEASIBLE -1
- #define OVERFLOW -2
- typedef int Status;
- typedef int ElemType;
- #endif // COMMON_H_INCLUDED
"List_Seq.h"
- //链表的顺序存储
- #ifndef LIST_SEQ_H_INCLUDED
- #define LIST_SEQ_H_INCLUDED
- #include "Common.h"
- #define LIST_INIT_SIZE 100
- #define LISTINCREMENT 10
- typedef struct {
- ElemType * elem;//存储空间基址
- int length;//当前长度
- int listsize;//当前分配的存储容量,以sizeof(ElemType)为单位
- }SqList;
- Status InitList_Seq(SqList * list);
- Status DestroyList_Seq(SqList * list);
- Status ClearList_Seq(SqList * list);
- Status ListEmpty_Seq(SqList * list);
- Status ListLength_Seq(SqList * list);
- void GetElem_Seq(SqList * list, int i, ElemType * e);
- int LocateElem_Seq(SqList * list, ElemType e);
- void PriorElem_Seq(SqList * list, ElemType cur_e, ElemType * pre_e);
- void NextElem_Seq(SqList * list, ElemType cur_e, ElemType * next_e);
- Status ListInsert_Seq(SqList * list, int i, ElemType e);
- Status ListDelete_Seq(SqList * list, int i, ElemType * e);
- void ListTraverse(SqList * list);
- #endif // LIST_SEQ_H_INCLUDED
"List_Seq.c"
- #include "List_Seq.h"
- Status InitList_Seq(SqList * list)
- {
- list->elem = (ElemType *)malloc(LIST_INIT_SIZE * sizeof(ElemType));
- if(!list->elem)
- exit(OVERFLOW);
- list->length = 0;
- list->listsize = LIST_INIT_SIZE;
- return OK;
- }
- Status DestroyList_Seq(SqList * list)
- {
- if(!list->elem)
- exit(ERROR);
- free(list->elem);
- list->elem = NULL;
- list->length = 0;
- list->listsize = 0;
- return OK;
- }
- Status ClearList_Seq(SqList * list)
- {
- if(!list->elem)
- exit(ERROR);
- list->length = 0;
- //list->listsize = LIST_INIT_SIZE;
- return OK;
- }
- Status ListEmpty_Seq(SqList * list)
- {
- if(!list->elem)
- exit(ERROR);
- if(list->length == 0)
- return TRUE;
- else
- return FALSE;
- }
- Status ListLength_Seq(SqList * list)
- {
- if(!list->elem)
- exit(ERROR);
- return list->length;
- }
- void GetElem_Seq(SqList * list, int i, ElemType * e)
- {
- if(!list->elem || i>list->length || i<1)
- exit(ERROR);
- *e = list->elem[i-1];
- }
- //返回与e相等的元素的位序
- int LocateElem_Seq(SqList * list, ElemType e)
- {
- if(!list->elem)
- exit(ERROR);
- int i;
- for(i=0; i<ListLength_Seq(list); i++)
- {
- if(list->elem[i] == e)
- return i+1;
- }
- return 0;
- }
- //返回cur_e的前驱,保存在pre_e中
- void PriorElem_Seq(SqList * list, ElemType cur_e, ElemType * pre_e)
- {
- if(!list->elem)
- exit(ERROR);
- int i;
- for(i=0; i<ListLength_Seq(list); i++)
- {
- if(cur_e == list->elem[i] && i!=0)
- *pre_e = list->elem[i-1];
- }
- }
- //返回cur_e的后继,保存在next_e中
- void NextElem_Seq(SqList * list, ElemType cur_e, ElemType * next_e)
- {
- if(!list->elem)
- exit(ERROR);
- int i;
- for(i=0; i<ListLength_Seq(list); i++)
- {
- if(cur_e == list->elem[i] && i!=ListLength_Seq(list)-1)
- *next_e = list->elem[i+1];
- }
- }
- Status ListInsert_Seq(SqList * list, int i, ElemType e)
- {
- if(!list->elem)
- exit(ERROR);
- if(i<1 || i>ListLength_Seq(list)+1)
- return ERROR;
- if(list->length == list->listsize)
- {
- ElemType * newbase = (ElemType *)realloc(list->elem, (list->listsize + LISTINCREMENT)*sizeof(ElemType));
- if(!newbase)
- exit(OVERFLOW);
- list->elem = newbase;
- list->listsize += LISTINCREMENT;
- }
- int j;
- for(j=ListLength_Seq(list); j>i-1; j--)
- {
- list->elem[j] = list->elem[j-1];
- }
- list->elem[i-1] = e;
- list->length++;
- return OK;
- }
- Status ListDelete_Seq(SqList * list, int i, ElemType * e)
- {
- if(!list->elem)
- exit(ERROR);
- if(i<1 || i>ListLength_Seq(list))
- return ERROR;
- int j;
- *e = list->elem[i-1];
- for(j=i-1; j<ListLength_Seq(list)-1; j++)
- {
- list->elem[j] = list->elem[j+1];
- }
- list->length--;
- return OK;
- }
- void ListTraverse(SqList * list)
- {
- if(!list->elem)
- exit(ERROR);
- int i;
- for(i=0; i<ListLength_Seq(list); i++)
- {
- printf("%d ", list->elem[i]);
- }
- printf("\n");
- }
http://blog.csdn.net/ggxxkkll/article/details/8660949
线性表的顺序存储结构称为顺序表。
图解:
下面来看下顺序表的C++实现:
SeqList.h文件
- //SeqList.h 声明类SeqList,文件名为SeqList.h
- #ifndef SeqList_H
- #define SeqList_H
- const int MaxSize=100; //100只是示例性的数据,可以根据实际问题具体定义
- template <class T> //定义模板类SeqList
- class SeqList
- {
- public:
- SeqList( ); //无参构造函数
- SeqList(T a[], int n); //有参构造函数
- ~SeqList(); //析构函数为空
- int 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(); //遍历线性表,按序号依次输出各元素
- private:
- T data[MaxSize]; //存放数据元素的数组
- int length; //线性表的长度
- };
- #endif
SeqList.cpp文件
- //SeqList.cpp
- #include "SeqList.h"
- /*
- *前置条件:顺序表不存在
- *输 入:无
- *功 能:构建一个顺序表
- *输 出:无
- *后置条件:构建一个顺序表
- */
- template <class T>
- SeqList<T>:: SeqList( )
- {
- length=0;
- }
- /*
- *前置条件:顺序表不存在
- *输 入:顺序表信息的数组形式a[],顺序表长度n
- *功 能:将数组a[]中元素建为长度为n的顺序表
- *输 出:无
- *后置条件:构建一个顺序表
- */
- template <class T>
- SeqList<T>:: SeqList(T a[], int n)
- {
- if (n>MaxSize) throw "参数非法";
- for (int i=0; i<n; i++)
- data[i]=a[i];
- length=n;
- }
- /*
- *前置条件:无
- *输 入:无
- *功 能:无
- *输 出:无
- *后置条件:无
- */
- template <class T>
- SeqList<T>:: ~SeqList( )
- {
- }
- /*
- *前置条件:顺序表存在
- *输 入:插入元素x,插入位置i
- *功 能:将元素x插入到顺序表中位置i处
- *输 出:无
- *后置条件:顺序表插入新元素
- */
- template <class T>
- void SeqList<T>::Insert(int i, T x)
- {
- int j;
- if (length>=MaxSize) throw "上溢";
- if (i<1 || i>length+1) throw "位置";
- for (j=length; j>=i; j--)
- data[j]=data[j-1]; //注意第j个元素存在数组下标为j-1处
- data[i-1]=x;
- length++;
- }
- /*
- *前置条件:顺序表存在
- *输 入:要删除元素位置i
- *功 能:删除顺序表中位置为i的元素
- *输 出:无
- *后置条件:顺序表删除元素
- */
- template <class T>
- T SeqList<T>::Delete(int i)
- {
- int x,j;
- if (length==0) throw "下溢";
- if (i<1 || i>length) throw "位置";
- x=data[i-1];
- for (j=i; j<length; j++)
- data[j-1]=data[j]; //注意此处j已经是元素所在的数组下标
- length--;
- return x;
- }
- /*
- *前置条件:顺序表存在
- *输 入:无
- *功 能:输出顺序表长度
- *输 出:顺序表长度
- *后置条件:顺序表不变
- */
- template <class T>
- int SeqList<T>::Length()
- {
- return length;
- }
- /*
- *前置条件:顺序表存在
- *输 入:查询元素位置i
- *功 能:按位查找位置为i的元素并输出值
- *输 出:查询元素的值
- *后置条件:顺序表不变
- */
- template <class T>
- T SeqList<T>::Get(int i)
- {
- if (i<1 && i>length) throw "查找位置非法";
- else return data[i-1];
- }
- /*
- *前置条件:顺序表存在
- *输 入:查询元素值x
- *功 能:按值查找值的元素并输出位置
- *输 出:查询元素的位置
- *后置条件:顺序表不变
- */
- template <class T>
- int SeqList<T>::Locate(T x)
- {
- for (int i=0; i<length; i++)
- if (data[i]==x)
- return i+1 ; //下标为i的元素等于x,返回其序号i+1
- return 0; //退出循环,说明查找失败
- }
- /*
- *前置条件:顺序表存在
- *输 入:无
- *功 能:顺序表遍历
- *输 出:输出所有元素
- *后置条件:顺序表不变
- */
- template <class T>
- void SeqList<T>::PrintList()
- {
- for(int i=0;i<length;i++)
- cout<<data[i]<<endl;
- }