数据结构- -线性表- -顺序表

线性表属于线性结构,是最常用且最简单的一种数据结构,是有n个数据元素的有限序列,同一线性表中的元素必定具有相同特性。长度可根据需要增长或缩短,即对线性表的数据元素可以进行访问,还可以进行插入和删除等。

顺序存储与实现:

把逻辑上相邻的数据元素存储在物理也相邻的存储单元中。用一组地址连续的存储单元依次存储线性表的数据元素。只要确定的存储线性表的起始位置,线性表中任一数据元素都可随机存取,所以线性表的顺序存储是一种随机存取的存储结构。

优点是随机存取,查找速度快,且修改仅需要通过数组的下标便可访问某个特定元素并修改。缺点是插入和删除很耗费时间,效率低。

动态分配顺序存储结构:

#define LIST_INIT_SIZE	100		//线性表存储空间的初始分配量 
#define LISTINCREMENT	10		//初始分配增量 
typedef struct{
	ElemType *elem ;		//线性表存储空间的基地址 
	int length ;			//当前长度 
	int listsize ;			//当前分配的存储容量 
}SqList; 

线性表所实现的一些基础功能:

Status InitList(SqList &L);	//构造一个空的线性表L。 后续操作均在表已存在的基础上进行。 
Status DestroyList(SqList &L);	//销毁线性表 。 
Status ClearList(SqList &L);	//将表重置为空表 。 
Status ListEmpty(SqList L);	//判断是否为空表,是则返回TRUE,否则返回FALSE。 
int ListLength(SqList L);	//获取链表的长度,返回长度值。 
Status GetElem(SqList L,int i,ElemType &e);	//用e返回线性表中第i个位置元素的值。 
Status PriorElem(SqList L,ElemType cur_e,ElemType &pre_e);	//找元素 cur_e的前驱,用pre_e返回其前驱。 
Status NextElem(SqList L,ElemType cur_e,ElemType &next_e);	//找元素 cur_e的后继,用next_e返回其后继。
Status ListInsert(SqList &L,int i,ElemType e);	//在线性表中第i个位置插入新的元素e。 
Status ListDelete(SqList &L,int i,ElemType &e);	//删除线性表中第i个位置的元素,并用e返回其值。 
Status ListTraverse(SqList L);	//对线性表的遍历。 

具体实现:

#include <iostream>
#include <stdlib.h>
#define LIST_INIT_SIZE	100		//线性表存储空间的初始分配量 
#define LISTINCREMENT	10		//初始分配增量
#define TRUE 1
#define FALSE 0 
#define OVERFLOW	-2
typedef int Status ;
typedef int ElemType ; 
typedef struct{
	ElemType *elem ;		//线性表存储空间的基地址 
	int length ;			//当前长度 
	int listsize ;			//当前分配的存储容量 
}SqList; 

Status InitList(SqList &L);	//构造一个空的线性表L。 后续操作均在表已存在的基础上进行。 
Status DestroyList(SqList &L);	//销毁线性表 。 
Status ClearList(SqList &L);	//将表重置为空表 。 
Status ListEmpty(SqList L);	//判断是否为空表,是则返回TRUE,否则返回FALSE。 
int ListLength(SqList L);	//获取链表的长度,返回长度值。 
Status GetElem(SqList L,int i,ElemType &e);	//用e返回线性表中第i个位置元素的值。 
Status PriorElem(SqList L,ElemType cur_e,ElemType &pre_e);	//找元素 cur_e的前驱,用pre_e返回其前驱。 
Status NextElem(SqList L,ElemType cur_e,ElemType &next_e);	//找元素 cur_e的后继,用next_e返回其后继。
Status ListInsert(SqList &L,int i,ElemType e);	//在线性表中第i个位置插入新的元素e。 
Status ListDelete(SqList &L,int i,ElemType &e);	//删除线性表中第i个位置的元素,并用e返回其值。 
Status ListTraverse(SqList L);	//对线性表的遍历。 
void MergeList(SqList La,SqList Lb,SqList &Lc);	//将线性表La和表Lb合并到表Lc中。

using namespace std;
int main(){
	ElemType e , pre_e , next_e;
	SqList L ;
	InitList(L) ;
	ListEmpty(L) ; 
	cout<<"顺序表的长度值为:"<<ListLength(L)<<endl; 
	cout << "输入顺序表的各个元素值:"<<endl; 
	for(int i=1;i<=5;i++){
		int a ;
		cin>>a ;
		ListInsert(L,i,a);
	} 
//	ListInsert(L,1,1);
//	ListInsert(L,2,2);
//	ListInsert(L,3,3);
//	ListInsert(L,4,4);
//	ListInsert(L,5,5); 
	ListTraverse(L) ;cout<<endl;
	ListEmpty(L); 
	cout<<"此时顺序表的长度值为:"<<ListLength(L) <<endl;
	GetElem(L,3,e) ;cout<<"获取第三个位置元素,用e输出:"<<e<<endl;
	PriorElem(L,3,pre_e);
	NextElem(L,3,next_e);
	cout << "删除第3个位置的数据元素."<<endl;
	ListDelete(L,3,e);
	ListTraverse(L) ;cout<<endl;
} 
Status InitList(SqList &L){
	//线性表的初始化操作就是为表分配一个预定义大小的数组空间,并将表的当前长度设为1. 
	L.elem = (ElemType*)malloc(LIST_INIT_SIZE * sizeof(ElemType)) ;
	if(!L.elem)
		exit (OVERFLOW) ;	//exit(n)表示退出,传入的参数是程序退出时的状态码,0表示正常退出,其他表示非正常退出
	L.length=0 ;
	L.listsize=LIST_INIT_SIZE ;
	return TRUE ;
}
Status DestroyList(SqList &L){
	if(!L.elem){
		cout<<"该顺序表不存在。"<<endl;
		return FALSE ;
	}
	free(L.elem) ;
	L.length=0 ;
	L.listsize=0 ;
	return TRUE ;
}
Status ClearList(SqList &L){
	if(!L.elem){
		cout<<"该顺序表不存在。"<<endl;
		return FALSE ;
	}
	L.length=0 ;
	return TRUE ;
}
Status ListEmpty(SqList L){
	if(!L.elem){
		cout<<"该顺序表不存在。"<<endl;
		return FALSE ;
	}
	else if(L.length>0){
		cout<<"该表不为空。"<<endl;
		return FALSE ; 
	}
	else{
		cout<<"表为空。"<<endl;
		return TRUE ;
	}
}
int ListLength(SqList L){
	if(!L.elem){
		cout<<"顺序表不存在。"<<endl;
		return FALSE ;
	}
//	int i ;
//	for(i=0;i<L.length;i++);
//	return i ;
//顺序表可直接返回其长度。
	return L.length ; 
}
Status GetElem(SqList L,int i,ElemType &e){
	if(!L.elem){
		cout<<"顺序表不存在。"<<endl;
	}
	if(i<0 || i>=L.length){
		cout<<"获取位置不存在。"<<endl;
		return FALSE ;
	}
	e=L.elem[i-1] ;
	return TRUE ;
}
Status ListInsert(SqList &L,int i,ElemType e){	//在第i个位置处插入元素e 。 
    //事先应判断: 插入位置i 是否合法?表是否已满?
	if(!L.elem){
		cout<<"顺序表不存在。"<<endl;
		return FALSE ;
	}
	if(i< 1|| i>L.length+1) {
		cout<<"选择插入位置有误。"<<endl;
		return FALSE ;
	}
	if(L.length+1>L.listsize){
		ElemType *newbase ;
		newbase = (ElemType *)realloc (L.elem,(L.listsize+LISTINCREMENT) * sizeof(ElemType)) ;
		if(!newbase)
			exit(OVERFLOW) ;
		L.elem = newbase ;
		L.listsize += LISTINCREMENT ;
	}
	ElemType *p ;
	p=&L.elem[i-1] ; 
	for(;p<&(L.elem[L.length]);p++)
		*(p+1) = *p ;
	*p=e ;
	L.length++ ;    //不要忘了表长要加1
	return TRUE ; 
}
Status ListDelete(SqList &L,int i,ElemType &e){
    //事先需要判断: 删除位置i 是否合法?
	if(!L.elem){
		cout<<"顺序表不存在。"<<endl;
		return FALSE ;
	}
	if(i<0||i>=L.length){
		cout<<"所需要删除的位置不存在。"<<endl;
		return FALSE ; 
	}
	ElemType *p ;
	p=&L.elem[i-1] ;
	e=*p ;
	for(;p<&(L.elem[L.length]);p++)
		*p = *(p+1) ;
	L.length-- ;    //别忘了
	return TRUE ;
}
Status PriorElem(SqList L,ElemType cur_e,ElemType &pre_e){
	if(!L.elem){
		cout<<"顺序表不存在。"<<endl;
		return FALSE ;
	}
	int i ;
	for(i=1;i<L.length;i++){
		//顺序表的第一个无前驱。 
		if(L.elem[i]==cur_e){
			pre_e=L.elem[i-1] ;
			cout<< cur_e << "的前驱是:" << pre_e <<endl;
			return TRUE ;
		}
	} 
	cout<<"表中未找到所要查找的数据前驱。"<<endl;
	return FALSE ;
}
Status NextElem(SqList L,ElemType cur_e,ElemType &next_e){
	if(!L.elem){
		cout<<"顺序表不存在。"<<endl;
		return FALSE ;
	}
	int i ;
	for(i=0;i<L.length-1;i++){
		//表最后一个数据元素无后继。
		if(L.elem[i]==cur_e){
			next_e=L.elem[i+1] ;
			cout<<next_e<<"的后继是:" << next_e <<endl;
			return TRUE ;
		} 
		/*else{
			cout<<"表中未找到所要查找的数据元素。"<<endl;
			return FALSE ;
		}*/
		//找不到在循环外说明。 
	}
	cout<<"表中未找到所要查找的数据后继。"<<endl;
	return FALSE ;
}
Status ListTraverse(SqList L){
	if(!L.elem){
		cout<<"顺序表不存在。"<<endl;
		return FALSE ; 
	}
	cout<<"依次将链表中的数据元素输出:"<<endl;
	int i ;
	for(i=0;i<L.length;i++){
		cout<<"  " << L.elem[i] ;
	}
	return TRUE ;
}

此外,顺序表还有一些不是经常用到的功能,比如对于两个现有的表La,Lb , 将存在于Lb中而不存在于La中的数据元素插入到表La中去,需要扩大线性表La 或者 将两个表合并为一个,其内的数据元素按照非递减的顺序排列。

void Union(SqList &La, SqList Lb);	//将存在于Lb中而不存在于La中的数据元素插入到表La中 
void MergeList(SqList La,SqList Lb,SqList &Lc);	//将线性表La和表Lb合并到表Lc中

实现如下:

顺序表的合并:

void MergeList(SqList La,SqList Lb,SqList &Lc){
	int i,j,k;
	i=j=k=0;
	ElemType pa , pb , pc ;
	Lc.length = La.length+ Lb.length ;
	Lc.elem = (ElemType*)malloc(Lc.listsize * sizeof(ElemType));
	if(!Lc.elem){
		cout<<"空间分配失败。"<<endl;
		exit (OVERFLOW) ;
	}
	Lc.listsize = Lc.length ;
	while((i<=La.length-1)&&(j<=Lb.length-1)){
		pa = La.elem[i] ;
		pb = Lb.elem[j] ; 
		if(pa<=pb){
			Lc.elem[k]=pa;
			i++;
			k++;
		}
		else{
			Lc.elem[k]=pb;
			j++;
			k++;
		}
	}
	while(i<=La.length-1){
		pa = La.elem[i] ;
		Lc.elem[k]=pa;
		i++;
		k++;
	}
	while(j<=Lb.length-1){
		pb = Lb.elem[j] ;
		Lc.elem[k]=pb;
		j++;
		k++;
	}
}

两个表之间数据元素的插入(这个功能能读懂,但代码部分涉及到了LcoateElem函数,判断元素间关系,我还没具体去看,不是很了解):

Status fun1(ElemType e,ElemType obj)
{
	if(e==obj)
		return TRUE;
	return FALSE;
}
int LocateElem(SqList L,ElemType e,Status (*compare)(ElemType ,ElemType ))
{
	int i=1;
	ElemType *p=L.elem;
	if(L.elem==NULL)
	{
		cout<<"顺序表不存在!"<<endl;
		return -1;
	}
	while(i<=L.length && compare(*p,e)==FALSE)
	{
		i++;
		p++;
	}
	if(i<=L.length)
		return i;
	return 0;
}
void Union(SqList &La, SqList Lb){
	int La_len , Lb_len , i;
	ElemType e ;
	La_len = ListLength(La) ;
	Lb_len = ListLength(Lb) ;
	if(La_len+Lb_len > La.listsize){
		ElemType *newbase ;
		newbase = (ElemType *) realloc(La.elem,(La.listsize+LISTINCREMENT) * sizeof(ElemType));
		La.elem = newbase ;
		La.listsize += LISTINCREMENT ;
	}
	for(i=1;i<=Lb_len;i++){
		GetElem(Lb,i,e);
		if(!LocateElem(La,e,fun1))
			ListInsert(La,++La_len,e);
	}
}

猜你喜欢

转载自blog.csdn.net/qq_43305922/article/details/85240614