数据结构与算法:线性表之顺序表

最近开始学习数据结构与算法,可能是因为刚开始接触,觉得很迷茫,学得非常不顺利,这篇文章只是一些简单的总结。如有错误,欢迎私信!



一、数据结构的一些基本概念

1、数据:数据是信息的载体,是描述客观事物属性的数、字符以及所有能输入到计算机中并被程序识别和处理的符号的集合。

2、数据元素:数据元素是数据的基本单位,通常作为一个整体进行考虑和处理。一个数据元素可由若干数据项组成,数据项是构成数据元素的不可分割的最小单位。例如,学生记录就是一个数据元素,它由学号、姓名、性别等数据项组成。

3、数据对象:数据对象是具有相同性值的数据元素的集合,是数据的一个子集。

4、数据类型:数据类型是一个值的集合和定义再此集合上的一组操作的总称。
1)原子类型。其值不可再分的数据类型。如bool 和int 类型。
2)结构类型。其值可以再分解为若干成分(分量)的数据类型。
3)抽象数据类型。抽象数据组织及与之相关的操作。

5、数据结构:数据结构是相互之间存在一种或多种特定关系的数据元素的集合。

6、时间复杂度:一般情况下,算法中基本操作重复执行的次数是问题规模n的某个函数f(n),算法的时间量度记作T(n)=O(n),它表示随问题规模n的增大而增大,算法执行时间的增长率和f(n)的增长率相同,称作算法的渐近时间复杂度,简称时间复杂度。

7、空间复杂度:算法的空间复杂度S(n)定义为该算法所耗费的存储空间,它是问题规模n的函数。记为S(n)=O(g(n))。

二、线性表中的顺序表

定义:线性表是具有相同数据类型的n(n>0)个数据元素的有限序列,其中n为表长,当n=0时线性表是一个空表。

在线性表的顺序存储结构(即数组)中,其任意一个元素的存储位置可以通过计算得到,因此其数据读取的时间复杂度为 O(1)。

(一)、顺序表的分配方式

1、静态分配

//顺序表的实现——静态分配储存地址 
/*
编译环境:
win10专业版
DEV C++ 5.11
TDM-GCC 4.9.2 64bit
*/


#include<stdio.h>
#define MaxSize 10   //定义表的最大长度 

//创建表 
typedef struct{
	int data[MaxSize];//用静态的"数组"存放数据元素
	int length; //顺序表的当前长度  
}SqList;        //顺序表的类型定义(静态分配方式)

//初始化 
void InitList(SqList L){
	L.length = 0;
	printf("初始化成功\n");
}
int main(){
	SqList L;//声明一个顺序表
	InitList(L);//初始化一个顺序表
	for(int j = 0;j < MaxSize;j++){
		L.data[j]= j; 
	}
	for(int i = 0;i < MaxSize; i++){
		printf("data[%d]=%d\n",i,L.data[i]);
	}
	return 0; 
}

2、动态分配

//顺序表的实现——静态分配储存地址 

/*
编译环境:
win10专业版
DEV c++ 5.11
TDM-GCC 4.9.2 64bit 
*/ 


/*
编译环境:
win10专业版
DEV c++ 5.11
TDM-GCC 4.9.2 64bit 
*/ 
#include <stdio.h>
#include <stdlib.h>

#define MaxSize 5
//线性表储存空间的分配增量
	
//创建表 
typedef struct{			
	int *data;	//存储空间基址 
	int length;	//当前表长 
	int listsize;
	//当前分配的存储容量 
}SqList;	

void CreateList(SqList *L){
	//ElemType的类型根据实际情况而定,这里假定为in
	//L->data = (ElenType *)malloc(InitSize * sizeof(ElemType);
	L->data = (int *)malloc(MaxSize* sizeof(int));
	if(!L->data)	
		return;
	L->listsize = MaxSize;
	printf("请输入这个表的长度:");
	printf("\n"); 
	scanf("%d",&L->length);
	printf("请输入%d个数字\n",L->length);
	for(int i = 1;i <=L->length;i++){
		scanf("%d",&L->data[i]);
	}
	printf("初始化成功!\n");
}

void listprintf(SqList *L){
	printf("表中的数据为:"); 
	for(int i = 1;i <= L->length;i++){
		printf("%d ",L->data[i]);
	}
	printf("\n");
}


int main(){
	SqList L;
	CreateList(&L);
	listprintf(&L);

	return 0;
}

(二)、顺序表的基本操作

1、构造一个空的线性表

//构造一个空的线性表
int InitList(SqList *L){
	L->data = (int *)malloc( MaxSize* sizeof(int));      //首元素的地址 
	if(!L->data){            //如果存储空间分配失败,L.data为NULL
	printf("存储空间分配失败\n");
	    return 0;    
	}
	L->length = 0;            //当前线性表为空表,即线性表长度为0
	L->listsize = MaxSize;           //给线性表分配初始容量
	printf("一个空的线性表已经构建成功\n");      //输出空线性表构建成功的提示消息 
	return 1; 
} 

2、插入操作

//插入某个元素
void Listinsert(SqList *L){
	int i;int e;
	printf("输入要插入位置及元素\n");
	scanf("%d%d",&i,&e);
	printf("在顺序线性表中第%d个位置之前插入新的元素%d。\n",i,e);
	//在顺序线性表L中第i个位置之前插入新的元素e
	if(i<1||i>L->length+1)return;
	//	 1<=i<=listlength(L)+1;
	int *p,*q;
	q=&(L->data[i-1]);
	for(p=&(L->data[L->length-1]);p >= q;--p) *(p+1)=*p;
	*q=e; 
	++L->length;
	return ;	
}

3、销毁操作

//删除线性表某一位置的元素
int  DeleteList(SqList *L){
	int *p,*q;
	int i;
	printf("请输入要删除的元素的位置:\n");
	scanf("%d",&i);
	if(i < 1 || i > L->length){            //如果要删除的位置不合法
		printf("请输入一个有效数字\n"); 
		return 0;
	} 
	p = &(L->data[i - 1]);                 //p为被删除元素的位置
	q = L->data + L->length - 1;            //将表尾元素的位置赋值给q
	for(++p;p <= q;p++)
	    *(p - 1) = *p;                    //被删除的元素之后的元素全部左移 
	--L->length;                           //表长减1 
	printf("第%d个元素删除成功\n",i);
	return 1;
}

4、查找操作

1)按值查找
//获取线性表某一位置对应的元素
int  GetElem(SqList *L){
	
	int Num,index;
	printf("请输入要查找的元素:\n");
	scanf("%d",&index); 
	int i; 
	for(i = 0;i <L->length;i++){
		if(index==L->data[i]){
			printf("该元素的位置是第%d个元素\n",i);
			return 1;
		}
	} 
	if(index != L->data[i])
	printf("这个元素不存在!");
	return 1;
} 
2)按位查找
//获取线性表某一位置对应的元素
int  GetElem(SqList *L){
	
	int Num,index;
	printf("请输入要查找的位置:\n");
	scanf("%d",&index); 
	if(index <= 0 || index > L->length){              //如果要获取元素的位置是否出界 
		printf("请输入一个有效的数字\n");
		return 0;
	}
	else
	Num = L->data[index - 1];
	printf("第%d个位置的元素为:%d\n",index,Num);
	return 1;
} 

5、清除操作

//对线性表进行重置
int  ClearList(SqList &L){
	if(L->data){                  //如果线性表存在 
	    L->length = 0;            //将线性表的元素个数重置为0
	    printf("线性表已重置\n");
	    return 1;
	}
	else 
	printf("线性表不存在,无法重置\n");
	return 1;
} 

6、删除操作

//对线性表进行销毁
int DistoryList(SqList *L){
	if(!L->data){ 
	  printf("您还未建立线性表,请先建立线性表\n");
	  return 0; 
	} 
	free(L->data);            //使用free函数,将之前动态分配的内存还给系统 
	L->data = NULL;           //重置elem的值为Null 
	L->length = 0;            //将线性表的元素个数重置为0
	L->listsize = 0;          //将线性表的存储容量重置为0 
	printf("线性表已经销毁\n"); 
	return 1;
}

7、判断是否为空的操作

//判断线性表是否为空
Status ListEmpty(SqList *L){
	if(L->data){          //判断线性表是否为空的前提是线性表存在,当首元素地址即L.elem存在时说明线性表存在 
		if(L->length != 0){               //如果线性表中元素为0,即L.length的值为0时说明线性表是空表 
		       printf("线性表不是空表\n");
		       return 0; 
			}
			else
			   printf("线性表是空表\n");
		return 1;
	}
	else
	printf("线性表不存在,无法判断\n");
	return 1; 
} 

8、获取线性表的长度

//获取线性表的长度
Status ListLength(SqList *L){
	if(L->data){              //判断当前线性表存在 
		int K;
		K = L->length;        //将线性表的元素个数赋值给K
		printf("线性表长度为%d\n",K); 
		return 1; 
	}
	else
		printf("线性表不存在,无法判断\n");
	return 1;
}

(三)、源码



/*
编译环境:
win10专业版
DEV c++ 5.11
TDM-GCC 4.9.2 64bit 
*/ 
#include <stdio.h>
#include <stdlib.h>

#define MaxSize 5
#define elsesize 10
//线性表储存空间的分配增量

	
//创建表 
typedef struct{			
	int *data;	//存储空间基址 
	int length;	//当前表长 
	int listsize;
	//当前分配的存储容量 
}SqList;	

//构造一个空的线性表
int InitList(SqList *L){
	L->data = (int *)malloc( MaxSize* sizeof(int));      //L.elem为首元素的地址 
	if(!L->data){            //如果存储空间分配失败,L.elem为NULL
	printf("存储空间分配失败\n");
	    return 0;    
	}
	L->length = 0;            //当前线性表为空表,即线性表长度为0
	L->listsize = MaxSize;           //给线性表分配初始容量
	printf("一个空的线性表已经构建成功\n");      //输出空线性表构建成功的提示消息 
	return 1; 
} 

//对线性表进行赋值
int ValueList(SqList *L){
	int i,j;
	printf("请输入线性表元素的个数:");
	scanf("%d",&i);
	if(i > L->listsize)                     //如果当要输入的元素个数大于内存大小时 
	{
		while(1)             //一直开辟新空间,直到开辟的空间大于需要的空间为止
		{
			if(i > L->listsize){
				L->data = (int *)realloc(L->data, elsesize * sizeof(int));
				L->listsize += elsesize;
        /*realloc()函数:重新分配空间      
		           参数:原空间基址,现需空间大小    
		           返回:1.成功:新空间地址(本质上是一个数值) 
		                 2.失败:Null 
	    */ 
			}
			else
			break;
		}
	}	
	printf("请输入元素:\n");
	for(j = 0;j < i;j++){
	
	    scanf("%d",&L->data[j]);	
	} 
	L->length = i;          //赋值完成后,修改并保存线性表的长度 
	printf("赋值成功\n");
	return 1; 
}



void listprintf(SqList *L){
	printf("表中的数据为:"); 
	for(int i = 0;i < L->length;i++){
		printf("%d ",L->data[i]);
	}
	printf("\n");
}
 
//插入某个元素
void Listinsert(SqList *L){
	int i;int e;
	printf("输入要插入位置及元素\n");
	scanf("%d%d",&i,&e);
	printf("在顺序线性表中第%d个位置之前插入新的元素%d。\n",i,e);
	//在顺序线性表L中第i个位置之前插入新的元素e
	if(i<1||i>L->length+1)return;
	//	 1<=i<=listlength(L)+1;
	int *p,*q;
	q=&(L->data[i-1]);
	for(p=&(L->data[L->length-1]);p >= q;--p) *(p+1)=*p;
	*q=e; 
	++L->length;
	return ;	
}

//删除线性表某一位置的元素
int  DeleteList(SqList *L){
	int *p,*q;
	int i;
	printf("请输入要删除的元素的位置:\n");
	scanf("%d",&i);
	if(i < 1 || i > L->length){            //如果要删除的位置不合法
		printf("请输入一个有效数字\n"); 
		return 0;
	} 
	p = &(L->data[i - 1]);                 //p为被删除元素的位置
	q = L->data + L->length - 1;            //将表尾元素的位置赋值给q
	for(++p;p <= q;p++)
	    *(p - 1) = *p;                    //被删除的元素之后的元素全部左移 
	--L->length;                           //表长减1 
	printf("第%d个元素删除成功\n",i);
	return 1;
}

//获取线性表某一位置对应的元素
int  GetPlace(SqList *L){
	
	int Num,index;
	printf("请输入要查找的位置:\n");
	scanf("%d",&index); 
	if(index <= 0 || index > L->length){              //如果要获取元素的位置是否出界 
		printf("请输入一个有效的数字\n");
		return 0;
	}
	else
	Num = L->data[index - 1];
	printf("第%d个位置的元素为:%d\n",index,Num);
	return 1;
} 
//获取线性表某一位置对应的元素
int  GetElem(SqList *L){
	
	int Num,index;
	printf("请输入要查找的元素:\n");
	scanf("%d",&index); 
	int i; 
	for(i = 0;i <L->length;i++){
		if(index==L->data[i]){
			printf("该元素的位置是第%d个元素\n",i);
			return 1;
		}
	} 
	if(index != L->data[i])
	printf("这个元素不存在!");
	return 1;
} 
//对线性表进行重置
int  ClearList(SqList *L){
	if(L->data){                  //如果线性表存在 
	    L->length = 0;            //将线性表的元素个数重置为0
	    printf("线性表已重置\n");
	    return 1;
	}
	else 
	printf("线性表不存在,无法重置\n");
	return 1;
} 
//对线性表进行销毁
int DistoryList(SqList *L){
	if(!L->data){ 
	  printf("您还未建立线性表,请先建立线性表\n");
	  return 0; 
	} 
	free(L->data);            //使用free函数,将之前动态分配的内存还给系统 
	L->data = NULL;           //重置elem的值为Null 
	L->length = 0;            //将线性表的元素个数重置为0
	L->listsize = 0;          //将线性表的存储容量重置为0 
	printf("线性表已经销毁\n"); 
	return 1;
}

//获取线性表的长度
int ListLength(SqList *L){
	if(L->data){              //判断当前线性表存在 
		int K;
		K = L->length;        //将线性表的元素个数赋值给K
		printf("线性表长度为%d\n",K); 
		return 1; 
	}
	else
		printf("线性表不存在,无法判断\n");
	return 1;
}
//判断线性表是否为空
int ListEmpty(SqList *L){
	if(L->data){          //判断线性表是否为空的前提是线性表存在,当首元素地址即L.elem存在时说明线性表存在 
		if(L->length != 0){               //如果线性表中元素为0,即L.length的值为0时说明线性表是空表 
		       printf("线性表不是空表\n");
		       return 0; 
			}
			else
			   printf("线性表是空表\n");
		return 1;
	}
	else
	printf("线性表不存在,无法判断\n");
	return 1; 
} 


int main(){
	SqList L;
	InitList(&L);//初始化一个空表 
	ValueList(&L);//赋值 
	listprintf(&L);//打印 
	
	DeleteList(&L);//删除元素 
	listprintf(&L);//打印 
	GetPlace(&L);//按位查找 
	GetElem(&L);//按值查找
	ListLength(&L);//获取其长度
	ClearList(&L);//清空表 
	ListEmpty(&L);//判断是不是空表
	
	DistoryList(&L);//销毁表
	ListEmpty(&L);//判断是不是空表
	
	
	 
	 
	return 0;
}


在这里插入图片描述

三、总结

这里只是我的一些总结,可能不太完整,所以最后附上一些大神的博客方便大家学习和理解:

1、《王道》数据结构笔记整理2022

2、数据结构——学习笔记——入门必看【建议收藏】

3、《数据结构》C语言版(清华严蔚敏考研版) 全书知识梳理 + 练习习题详解(超详细清晰易懂)

posted @ 2022-04-30 00:08  猫咪爱吃兔子  阅读(208)  评论(0编辑  收藏  举报