一、线性表描述
线性结构是最常用、最简单的一种数据结构。而线性表是一种典型的线性结构。其基本特点是线性表中的数据元素是有序且是有限的。
在这种结构中:
①存在一个唯一的被称为“第一个”的数据元素;
②存在一个唯一的被称为“最后一个”的数据元素;
③除第一个元素外,每个元素均有唯一一个直接前驱;
④除最后一个元素外,每个元素均有唯一一个直接后继。
二、线性表定义
线性表(Linear List):是由n(n≧0)个数据元素(结点)a1,a2,…an组成的有限序列。该序列中的所有结点具有相同的数据类型。其中数据元素的个数n称为线性表的长度。
当n=0时,称为空表。
当n>0时,将非空的线性表记作: (a1,a2,…an)
a1称为线性表的第一个(首)结点,an称为线性表的最后一个(尾)结点。
a1,a2,…ai-1都是ai(2≦i≦n)的前驱,其中ai-1是ai的直接前驱;
ai+1,ai+2,…an都是ai(1≦i≦n-1)的后继,其中ai+1是ai的直接后继。
三、线性表的逻辑结构
线性表中的数据元素ai所代表的具体含义随具体应用的不同而不同,在线性表的定义中,只不过是一个抽象的表示符号。
◆ 线性表中的结点可以是单值元素(每个元素只有一个数据项)。
例2 :某校从1978年到1983年各种型号的计算机拥有量的变化情况:(6,17,28,50,92,188)
例3 :一副扑克的点数 (2,3,4,…,J,Q,K,A)
◆ 线性表中的结点可以是记录型元素,每个元素含有多个数据项,每个项称为结点的一个域 。每个元素有一个可以唯一标识每个结点的数据项组,称为关键字。
例4 :某校2001级同学的基本情况:{(‘2001414101’,‘张里户’,‘男’,06/24/1983), (‘2001414102’,‘张化司’,‘男’,08/12/1984)…, (‘2001414102’,‘李利辣’,‘女’,08/12/1984)}
◆若线性表中的结点是按值(或按关键字值)由小到大(或由大到小)排列的,称线性表是有序的。
◆线性表是一种相当灵活的数据结构,其长度可根据需要增长或缩短。
◆对线性表的数据元素可以访问、插入和删除。
四、线性表的抽象数据类型定义
ADT List{
数据对象:D = { ai | ai∈ElemSet, i=1,2,…,n, n≧0 }
数据关系:R = {<ai-1, ai> | ai-1, ai∈D, i=2,3,…,n }
基本操作:
InitList( &L )
操作结果:构造一个空的线性表L;
ListLength( L )
初始条件:线性表L已存在;
操作结果:若L为空表,则返回TRUE,否则返回FALSE;
….
GetElem( L, i, &e )
初始条件:线性表L已存在,1≦i≦ListLength(L);
操作结果:用e返回L中第i个数据元素的值;
ListInsert ( L, i, &e )
初始条件:线性表L已存在,1≦i≦ListLength(L) ;
操作结果:在线性表L中的第i个位置插入元素e;
…
} ADT List
五、线性表的顺序存储结构
顺序存储:把线性表的结点按逻辑顺序依次存放在一组地址连续的存储单元里。用这种方法存储的线性表简称顺序表。
顺序存储的线性表的特点:
◆ 线性表的逻辑顺序与物理顺序一致;
◆ 数据元素之间的关系是以元素在计算机内“物理位置相邻”来体现。
设有非空的线性表:(a1,a2,…an)。顺序存储如图2-1所示。
六、实现代码(顺序表操作示例):
sequenceList.h
#ifndef __CHelloWorld__sequenceList__
#define __CHelloWorld__sequenceList__
#include <iostream>
#include <string.h>
#define MAXLEN 100 //定义顺序表的最大长度
typedef struct
{
char key[10]; //结点的关键字
char name[20];
int age;
}DATA; //结点类型
typedef struct
{
DATA ListData[MAXLEN + 1]; //保存顺序表的结构数组
int ListLen; //顺序表已存结点的数量
}SLType;
class SequenceList
{
public:
void SLInit(SLType* SL); //初始化
int SLLength(SLType* SL); //返回顺序表的元素数量
int SLInsert(SLType* SL,int n,DATA data); //插入数据
int SLAdd(SLType* SL,DATA data); //增加数据
int SLDelete(SLType* SL,int n); //删除数据
DATA *SLFindByNum(SLType *SL,int n); //按序号查询数据
int SLFindByCout(SLType *SL,char *key); //按key查询数据
int SLAll(SLType *SL); //遍历结点
};
#endif /* defined(__CHelloWorld__sequenceList__) */
sequenceList.cpp
#include "sequenceList.h"
using namespace std;
void SequenceList::SLInit(SLType *SL)
{
SL->ListLen = 0;
}
int SequenceList::SLLength(SLType *SL)
{
return (SL->ListLen);
}
int SequenceList::SLInsert(SLType *SL, int n, DATA data)
{
int i;
if(SL->ListLen >= MAXLEN)
{
cout<<"顺序表已满,不能插入结点!"<<endl;
return 0;
}
if (n<1 || n>SL->ListLen - 1)
{
cout<<"插入元素序号错误,不能插入元素!"<<endl;
return 0;
}
for (i = SL->ListLen; i >= n; i--)
{
SL->ListData[i+1] = SL->ListData[i];
}
SL->ListData[n] = data;
SL->ListLen++;
return 1;
}
int SequenceList::SLAdd(SLType *SL, DATA data)
{
if (SL->ListLen >= MAXLEN)
{
cout<<"顺序表已满,不能再添加结点!"<<endl;
return 0;
}
SL->ListData[++SL->ListLen] = data;
return 1;
}
int SequenceList::SLDelete(SLType *SL, int n)
{
int i;
if (n<1 || n>SL->ListLen+1)
{
cout<<"删除结点序号错误,不能删除结点!"<<endl;
return 0;
}
for (i = n; i < SL->ListLen; i++)
{
SL->ListData[i] = SL->ListData[i+1];
}
SL->ListLen--;
return 1;
}
DATA *SequenceList::SLFindByNum(SLType *SL, int n)
{
if (n<1 || n>SL->ListLen+1)
{
cout<<"结点序号错误,不能返回结点!"<<endl;
return NULL;
}
return &(SL->ListData[n]);
}
int SequenceList::SLFindByCout(SLType *SL, char *key)
{
int i;
for (i = 1; i<= SL->ListLen;i++)
{
if (strcmp(SL->ListData[i].key, key))
{
return i;
}
}
return 0;
}
int SequenceList::SLAll(SLType *SL)
{
int i;
for (i = 1; i<=SL->ListLen; i++)
{
printf("(%s,%s,%d)\n",SL->ListData[i].key,SL->ListData[i].name,SL->ListData[i].age);
}
return 0;
}
main.cpp
#include "sequenceList.h"
using namespace std;
int main(int argc, const char * argv[])
{
int i;
SLType SL;
DATA data;
DATA *pdata;
char key[10];
std::cout << "顺序表操作演示\n";
SequenceList *myList = new SequenceList();
myList->SLInit(&SL);
std::cout << "初始化完成\n";
do
{
std::cout << "输入添加的结点(学号 姓名 年龄):";
fflush(stdin); //清空输入缓冲区
scanf("%s%s%d",&data.key,&data.name,&data.age);
if (data.age) //年龄不能为0
{
if (!myList->SLAdd(&SL, data))
{
break;
}
}
else
{
break;
}
} while (1);
std::cout << "\n顺序表中的结点顺序为:\n";
myList->SLAll(&SL);
fflush(stdin);
std::cout << "\n要取出结点的序号:\n";
scanf("%d",&i);
pdata = myList->SLFindByNum(&SL, i);
if (pdata)
{
printf("第%d个结点为:(%s,%s,%d)\n",i,pdata->key,pdata->name,pdata->age);
}
delete myList;
// insert code here...
std::cout << "Hello, World!\n";
return 0;
}
运行结果:
参考书籍:《C/C++常用算法手册》 《数据结构-清华大学严蔚敏》