数据结构 线性表及其顺序存储

什么是线性表:
由n个数据特性相同的元素构成的有限有序序列称为线性表
表中元素的个数成为线性表的长度,n=0时为空表
表起始位置:表头
表结束位置:表尾
除第一个之外,结构中每个数据元素只有一个前驱
除最后一个之外,结构中每个数据元素均只有一个后继
线性表的抽象数据类型描述:
类型名称:线性表(List)

在这里插入图片描述
基本操作:
建空表
销毁表
清空表
判断表是否为空
返回表的长度
求线性表中的某个元素
在线性表中查找某元素X第一次出现的位置
删除指定位序i的元素
在位序i前插入一个新元素X
本程序代码均采用两种方式。
线性表的顺序存储实现

//指针
typedef struct LNode*List;//结构体指针
struct LNode{
ElementType Data[MAXSIZE];
int last;
};
struct LNode L;
List PtrL;
//结构体  以图书为例
#define MAXSIZE 100
typedef struct{
float price;
char name[20];
}book;
typedef struct {
book *elem;//存储空间基地址,类型为定义的结构体类型
int length;
}SqList;
SqList L;//在上述定义之后,可以通过该变量定义语句

在这里插入图片描述

**线性表的顺序存储结构:**一组地址连续的存储单元依次存储线性表的数据元素
**起始地址/基地址:**线性表中第一个数据元素的位置
**随机存取:**只要确定了存储线性表的位置,线性表中任意数据元素都可随机存取。
主要操作实现
1.初始化(建立空的顺序表)

//指针
List MakeEmpty(){
List PtrL;
PtrL=(List)malloc(sizeof(struct LNode));
PtrL->last=-1;
return PtrL;
}
//结构体
//1.为顺序表L动态分配一个预定大小的数组空间,使elem指向这段空间的基地址
//2.将当前表的长度设为0
Status InitList(SqList &L){
L.elem=new ElemType[MAXSIZE];
//因为在顺序表存储结构的时候这个elem是个指针。
if(!L.elem)exit(OVERFLOW);//OVERFLOW在实际程序编写运行的时候需要提前宏定义,如果L.elem为0,则存储分配失败退出。
L.length=0;//空表当前长度为0;
return OK;//OK也要宏定义
}

2.查找

int find(ElementType X,List PtrL){
int i=0;
while(i<=PtrL->last&&PtrL->Data[i]!=X)
i++;
if(i>PtrL->last)return -1;
else return i;//返回实际的数组元素的位置
}

查找成功的平均比较次数为(n+1)/2
运气好第一次就找到,运气不好最后一次找到
时间复杂度:O(n) 一个循环

根据指定的要查找的元素的值e,查找顺序表中第一个与e相等的元素。若查找成功,则返回该元素在表中的位置序号;若查找失败,则返回0;
用for循环

int find(ElementType X,List PtrL){
for(int i=0;i<PtrL->last;i++)
if(Ptrl->Data[i]==X)
return i+1;//考虑数组的位置和实际所确定的位置相差1
return 0;

}

3.插入
1.判断插入位置i是否合法 1<=i<=n+1
2.判断顺序表的存储空间是否已满,若已满就返回ERROR
3将第n个至第i个位置的元素依次向后移动一个位置,空出第i个位置(i=n+1时无需移动)
4.将要插入的新元素e放入第i个位置(赋值)
5.表长+1

void Insert(ElementType X,int i,List PtrL) {
int j;
if(PtrL->last==MAXSIZE-1){
	printf("表满"); 
	return;
	
}
if(i<1||i>PtrL->last+2){//实际输入从1开始算起,可以在末尾插入 
	printf("位置不合法"); 
	return; 
	
}
for(j=PtrL->last;j>=i-1;j--){
	PtrL->Data[j+1]=PtrL->Data[j];	
}
PtrL->Data[i-1]=X;
PtrL->last++;
return;

}
Status ListInsert(SqList &L.int i,ElemType e){
if(i<1||i>L.length+1)return ERROR;
if(L.length==MAXSIZE)return ERROR;
for(int j=L.length-1;j>=i-1;j--){
L.elem[j+1]=L.elem[j];
}
L.elem[i-1]=e;
++L.length;
return OK;
}

删除操作:

void Delete(int i,List PtrL){
	if(i<1||i>PtrL->last+1)
	return;
	for(int j=i;j<=PtrL->last;j++)
		PtrL->Data[j-1]=PtrL->Data[j];
		PtrL->last--;
		return;
}


另一种写法

 Status ListDelete(SqList &L,int i){
 	if((i<1)||i>L.length)return ERROR;
 	for(int j=i;j<=L.length-1;j++)
 	L.elem[j-1]=L.elem[j];
 	L.length--;
 	return OK;
 	
 }

部分操作的运行程序
转载链接感谢这位大佬的程序,让我终于明白了书上的代码如何实现运行。

//顺序表的初始化
#include <stdio.h>
#include <stdlib.h>//exit 所在头文件 
// exit(1)表示异常退出.这个1是返回给操作系统的
//exit(x)(x不为0)都表示异常退出
// exit(0)表示正常退出
#define OK 1;//ok在程序中是要有规定的。 
#define OVERFLOW -2 
#define MAXSIZE 100//顺序表可能达到的最大长度 
typedef int Status;//Status是函数的类型,其值是函数结果状态代码,如OK等  
typedef int ElemType;//ElemType是线性表中数据元素的类型,此处用int
//若有时数据类型不一致,就在函数里直接把elemtype改成相应的数据类型,
typedef struct
{
	ElemType *elem;//存储空间的基地址 
	int length;//当前长度 
	int listsize;//当前分配的存储容量 
}SqList;
Status InitList_Sq(SqList &L)//构造一个空的顺序表 
{
	L.elem=new ElemType[MAXSIZE];//为顺序表分配一个大小为MAXSIZE的数组空间 
	if(!L.elem) exit(OVERFLOW);//存储失败 
	L.length=0;//空表长度为零 
	L.listsize=MAXSIZE;
	return OK;
}
Status ListTraverse(SqList L)//  初始条件:顺序线性表L已存在  
{
	ElemType *p;
	p=L.elem;
	int i;
	printf("线性表当前容量为:%d\n",L.listsize);
	if(L.length>0)
	{
		printf("当前线性表有%d个元素,分别是\n",L.length);
		for(i=1;i<=L.length;i++)
		{
			printf("%d ",*p++);
		}
	}
	else 
	{
		printf("目前还是空线性表.\n");
	}
}
int main()
{
	SqList la;
	InitList_Sq(la);
	ListTraverse(la);
}
 

exit与return的区别:exit和系统有关系,干脆利落直接退出进程。
return一级一级的返回,返回到最初一级,退出进程。
这就是为什么在main函数之外,用exit的缘故

第一种写法的运行实例

#include<iostream>
#include<stdlib.h>
using namespace std; 
#define MAXSIZE 100
typedef int ElementType;
struct LNode{
ElementType Data[MAXSIZE];
int last;
};
typedef struct LNode*List;//结构体指针

List MakeEmpty(){
List PtrL;
PtrL=(List)malloc(sizeof(struct LNode));
PtrL->last=-1;
return PtrL;
}

void Delete(int i,List PtrL){
	if(i<1||i>PtrL->last+1)
	return;
	for(int j=i;j<=PtrL->last;j++)
		PtrL->Data[j-1]=PtrL->Data[j];
		PtrL->last--;
		return;
}
int find(ElementType X,List PtrL){
int i=0;
while(i<=PtrL->last&&PtrL->Data[i]!=X)
i++;
if(i>PtrL->last)return -1;
else return i;//返回实际的数组元素的位置
}
void Insert(ElementType X,int i,List PtrL) {
int j;
if(PtrL->last==MAXSIZE-1){
	printf("表满"); 
	return;
	
}
if(i<1||i>PtrL->last+2){//实际输入从1开始算起,可以在末尾插入 
	printf("位置不合法"); 
	return; 
	
}
for(j=PtrL->last;j>=i-1;j--){
	PtrL->Data[j+1]=PtrL->Data[j];	
}
PtrL->Data[i-1]=X;
PtrL->last++;
printf("添加成功\n");
return;

}

int main(){

	 List A=MakeEmpty();
	 int a=10,b=3,c=6;
	  Insert(a,1,A);


 cout<<A->Data[0];
	 	return 0;
}


在这里插入图片描述

通过二次学习数据结构,感觉懂得了很多。。。真高兴!!!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值