目录
3.1、线性表的定义
线性表(List):零个或多个数据元素的有限序列。
- 首先它是个序列。也就是说元素之间是有顺序的,若元素存在多个,则第一个元素无前驱,最后一个元素无后继,其它每个元素都有且只有一个前驱和后继。
- 线性表强调是有限的
- 在复杂的线性表中,一个数据元素可以由若干个数据项组成
3.2、线性表的抽象数据类型
线性表的抽象数据类型定义如下:
ADT 线性表 (List)
Data
线性表的数据对象集合为(a1,a2,......,an),每个元素的类型均为DataType。
其中,除第一个元素a1外,每个元素有且只有一个直接前驱元素,除最后一个元素an外,
每一个元素有且只有一个后继元素。数据元素之间的关系是一对一的关系。
Operation
InitList(*L); 初始化操作,建立一个空的线性表L
ListEmpty(*L) ; 若线性表为空,返回ture,否则返回false。
ClearList(*L) ; 将线性表清空
GetElem(L , i ,*e);将线性表中的第i个位置的元素返回给e
LocateElem(L,e); 在线性表中查找与给定值e相等的元素,如果查找成功,返回该元素在表中序号表示
成功;否则返回0表示失败
ListInerst(*L,i,e); 在线性表L中的第i个位置插入新元素e
ListDelete(*L,i,e);删除线性表L中第i个位置元素,并用e返回其值。
ListLength(L); 返回线性表L的元素个数
endADT
对于不同的应用,线性表的基本操作是不同的上述操作是最基本的操作,对于实际问题中涉及的关于线性表的更复杂ode操作,完全可以用这些基本操作的组合来实现。
3.3、线性表的顺序存储结构
线性表的顺序存储结构,指的是用一段地址连续的存储单元依次存储线性表的数据元素。
3.3.1线性表顺序存储结构C代码的实现
1、头文件sequencelist.h
#ifndef SEQUENCELIST_H
#define SEQUENCELIST_H
#define MAXSIZE 20 /*存储空间初始分配量*/
typedef int ElemType; /* ElemType类型根据实际情况而定,这里假设为int */
typedef struct
{
ElemType data[MAXSIZE]; /* 数组存储数据元素,最大值为MAXSIZE */
int length; /*线性表当前长度*/
}SqList;
typedef enum Bool
{
FALSE,TRUE//枚举默认值从0开始,依次加1
}Bool;
Bool CreatList(SqList* L); //初始化操作,创建一个空的顺序表
Bool UnionList(SqList* L1,SqList* L2,SqList* L); //将所有在线性表L1中但不在L2中的元素插入L2
int LocateElem(SqList L,ElemType e);//成功则返回元素的序号(从1开始),失败则返回0
int ListLength(SqList L);//顺序表的长度
Bool GetElem(SqList L, int i, ElemType e);//查找第i个位置的元素
Bool ListInsert(SqList L,int i,ElemType e);//在第i个位置插入元素
Bool ListDelete(SqList L,int i,ElemType e);//删除第i个位置的元素
Bool ListEmpty(SqList L);//判空
void clearList(SqList L);//清空顺序表
void display(SqList L);//显示当前的顺序表
#endif
2、顺序表的源文件sequencelist.c
#include"sequencelist.h"
#include<stdio.h>
Bool InitList( SqList *L)
{
int i;
printf("请输入插入元素的个数(0 ~ 20):\n");
scanf("%d",&(L->length));
if(L->length < 0 || L->length > MAXSIZE)
return FALSE;
for( i = 0 ; i <= L->length; i++)
{
printf("请输入线性表的第%d个元素\n",i+1);
scanf("%d",&L->data[i]);
}
return TRUE; //构建成功返回TURE
}
//不调用已经构建的函数,直接实现顺序表的合并。
Bool UnionList(SqList* L1,SqList* L2,SqList* L)
{
int i,j,k;
L->length = 0;
for( i = 0 ; i < L1->length; i++) //先将L1中的所有元素依次插入L中
{
L->data[i] = L1->data[i];
}
for(j = 0;j < L2->length; j++) //依次遍历L2中的各个元素
{
for(k = 0; k < L1->length; k++ )
{
if(L2->data[j] == L1->data[k]) //依次判断L2中的元素是否是L1中的元素
break; //若在则跳出当前循环,继续判断L2中的下一个元素是否是L1中的元素。
}
if(k == L1 ->length ) //若L2中第j个元素与L1中的每一个元素都不等,即该元素不在L1中,则可以考虑插入L表的后面
{
if (i >= MAXSIZE ) //判断此线性表L的长度是否超过最大长度
return FALSE;
L->data[i] = L2->data[j]; //没有超过则将L2中的该元素插入L中
i++;
}
}
L->length = i;
return TRUE;
}
//判断数据e在列表L中的位置
int LocateElem(SqList L,ElemType e)
{
int i;
for(i = 1 ; i <= L->lenght; i++ ) //如若从位置0开始则 i= 0;i < L->length
{
if(L->data[i-1] == e)
return i;
}
return 0;
}
//在第i个位置插入元素e
Bool ListInsert(SqList L ,int i,ElemType e)
{
int k ; //辅助变量
if(i<1 || L.length == MAXSIZE || i > L.length+1)//判断插入位置是否合法
return FALSE;
if(i <= L.length)
{
for(k = L.length-1; k >= i-1; k--) //将插入位置后的面的元素依次后移避免覆盖
L.data[k+1] = L.data[k];
}
L.data[i-1] = e; //在第i个位置插入元素 (特别说明:此处的位置是从1开始)
L.length++; //插入元素后表的长度加一
return TRUE;
}
//删除第i个位置的元素
Bool ListDelete(SqList L,int i,ElemType e)
{
int k;
if(i < 1 || L.length == 0 || i > L.length )//判断删除元素的位置是否合法
return FALSE;
e = L.data[i-1]; //取出要删除的元素
if( i <= L.length) //不在表尾
{
//删除位置的后续元素依次前移一位
for(k =i-1;k < L.length-1;k++)
L.data[k] = L.data[k+1];
}
L.length--; //删除元素后整体长度减一
return TRUE;
}
int ListLength(SqList L)
{
return L->length;
}
//判空
Bool ListEmpty(SqList L)
{
if(L.length == 0)
return TRUE;
else
return FALSE;
}
//清空顺序表
void clearList(SqList L)
{
L.length == 0;
}
//显示当前的顺序表
void display(SqList L)
{
int i;
for(i =0 ; i < L.length ; i++)
{
printf("%d ",L.data[i]);
}
printf("\n");
}
3.3.2线性表顺序存储结构C++代码的实现
1.顺序表的头文件sequencelist.h
#ifndef SEQUENCELIST_H
#define SEQUENCELIST_H
#define MAXSIZE 20
typedef int ElemType;
class SqList
{
public:
SqList();
SqList(ElemType elems[],int n); //构造函数
bool CreatList(); // 新建一个顺序表
bool UnionList(SqList L1 , SqList L2);
int LocateElem(ElemType e);//按元素查找;查找成功返回元素序号(从1开始),失败则返回0
int ListLength(); //顺序表的长度
bool GetElem(int i, ElemType& e); // 查找第i个位置的元素
bool ListInsert(int i,ElemType e); //在第i个位置插入元素
bool ListDelete(int i,ElemType& e); //删除第i个位置的元素
bool ListEmpty(); //判断是否为空
void ClearList(); // 清空顺序表
void display(); // 显示当前的顺序表
private:
ElemType data[MAXSIZE]; //下标从0开始,但是对线性表的操作中的下表从1开始:即第1个元素即为下标为0的元素
int length;
};
#endif
2.顺序表的源文件sequencelist.cpp
#include "sequencelist.h"
#include <iostream>
using namespace std;
SqList::SqList() // 初始化
{
length = 0;
}
SqList::SqList(ElemType elems[], int n) //有参构造器
{
if( n > MAXSIZE)
{
cout<<"传入的顺序表长度超过了最大长度,只接收了前"<<MAXSIZE<<"个元素"<<endl;
length = MAXSIZE;
}
else
length = n;
for(int i=0; i <length;i++)
{
data[i] = elems[i];
}
}
bool SqList::CreatList()
{
cout<<"插入多少个元素(0~20)?"<<endl;
cin>>length;
if(length < 0 || length > MAXSIZE)
{
length = 0;
return false;
}
for(int i = 1; i <=length; i++)
{
cout<<"请输入顺序线性表的第"<<i<<"个元素:";
cin >> data[i-1];
}
return true;
}
//按元素查找
int SqList::LocateElem(ElemType e)
{
for(int i = 0; i < length ; i++)
{
if(data[i] == e)
return i+1;
}
return 0;
}
int SqList::ListLength()
{
return length;
}
//查找第i个位置的元素
bool SqList::GetElem(int i,ElemType& e)
{
if(i<1 || length == 0 || i > length ) //判读查找的位置是否合法
return false;
e = data[i-1];
return true;
}
//在第i个位置插入一个元素e
bool SqList::ListInsert(int i,ElemType e)
{
int k;
if(i < 1 || length == 0 || i > length+1)//判断插入位置是否合法
return false;
for(k=length-1;k>=i-1;k--)
{
data[k+1] =data[k]; //将插入位置以后的元素依次后移
}
data[i-1] = e; //将指定位置的元素插入指定位置
length++; //整体长度加一
return true;
}
// 删除第i个位置的元素
bool SqList::ListDelete(int i,ElemType& e)
{
if(length==0 || i<1|| i>length)//线性表满,或者i的范围不在合理范围内时返回错误
return false;
e=data[i-1];//取出元素
if(i<=length)//不在表尾
{
//插入位置的后续元素前移一位
for(int k=i-1;k<length-1;k++)
data[k]=data[k+1];// 倒序挪动位置,避免覆盖问题
}
length--;
return true;
}
//判断是否为空
bool SqList::ListEmpty()
{
if(length == 0)
return true;
else
return false;
}
//清空顺序表
void SqList::ClearList()
{
length == 0;
}
//显示函数
void SqList::display()
{
for(int i=0; i < length ; i++)
cout<<data[i]<<" ";
cout<<endl;
}
bool SqList::UnionList(SqList L1 , SqList L2)
{
int i,j;
for(i=0;i<L1.length;i++)
{
data[i] = L1.data[i];
}
for(j =0;j<L2.length;j++)
if(L1.LocateElem(L2.data[j])==0) //判断L2中的元素是否在L1中
{
if(i >=MAXSIZE) //判断是否超过最大长度
return false;
data[i]=L2.data[j];
i++;
}
length = i;
return true;
}
3.主函数main.cpp
#include <iostream>
#include "sequencelist.h"
using namespace std;
int main(int argc, char** argv) {
SqList list;
ElemType elem,e;
ElemType delet_num;
bool flag;
cout<<" 1.顺序表的创建和显示"<<endl;
if(!list.CreatList())
cout<<"顺序表创建失败!"<<endl;
else
cout<<"顺序表创建成功! "<<endl;
//顺序表的显示
list.display();
cout<<"该顺序表的总长度为:"<< list.ListLength()<<endl;
cout<<endl<<endl;
cout<<" 2.按元素查找在顺序表中的位置"<<endl;
cout<<"请输入你要查找的元素:"<<endl;
cin >> elem;
cout<<"您所查找的元素的位置为:"<<list.LocateElem(elem)<<endl;
cout<<" 3.按位置查找"<<endl;
list.GetElem(4,e);
cout<<"顺序表的第4个元素是:"<<e<<endl<<endl;
cout<<" 4.在指定位置i插入元素"<<endl;
list.ListInsert(3,10);
cout<<"插入元素后的顺序表为:";
list.display();
cout<<" 4.在指定位置i删除元素"<<endl;
list.ListDelete(2,delet_num);
cout<<"删除元素后的序列为:";
list.display();
cout<<"删除的元素为:"<<delet_num<<endl;
cout<<" 7.合并顺序表"<<endl;
ElemType elems1[8]={10,9,8,7,6,5,4,3};
ElemType elems2[9]={5,6,7,8,9,10,11,1,12};
SqList list1(elems1,8);
SqList list2(elems2,9);
SqList list3;
cout<<"合并前的两个表为:"<<endl;
list1.display();
list2.display();
flag=list3.UnionList(list1,list2);
if(!flag)
cout<<"合并后,顺序表的长度超过最大范围"<<endl;
cout<<"该表的长度为: "<<list3.ListLength()<<endl;
list3.display();
return 0;
}
4.主函数的执行结果