【数据结构与算法(C语言)】1. 线性表的顺序存储

文章目录

  • 前言
  • [一. 线性表插入和删除](#一. 线性表插入和删除)
    • [1. 元素的插入](#1. 元素的插入)
    • [2. 元素的删除](#2. 元素的删除)
  • [二. 代码](#二. 代码)
  • [三. 优缺点](#三. 优缺点)

前言

线性表的顺序存储结构,指的是用一段地址连续的存储单元依次存储线性表的数据结构

一. 线性表插入和删除

1. 元素的插入

插入位置之后的数据都向后移一位,上图中元素98、208、999、789都向后移一位。元素666插入到第5个位置。

2. 元素的删除

待删除元素之后所有的元素都向前移一位,上图中,元素209,999,789都向前移一位

二. 代码

C++ 复制代码
#include <stdio.h>
#include <stdlib.h>

#define OK 	1
#define ERROR 	0
#define TRUE	1
#define	FALSE	0

#define LIST_INIT_SIZE 	20 	/*	线性表初始空间	*/
#define LIST_INCREMENT	10      /*	线性表每次的扩展空间大小 */

typedef int Status;	/*	状态码,函数返回的状态码 */
typedef int ElemType;	/*	元素类型,根据需要可以任意修改ElemType的原始类型,此处使用int型	*/

typedef struct 
{
	ElemType* elem ;	/*线性表数据, 使用数组实现顺序存储线性表的数据 */
	int length;		/*线性表长度*/
	int listSize;
} SqList;

Status InitList(SqList * list);		/*初始化线性表list*/
void DestoryList(SqList * list);		/*销毁线性表list*/
void ClearList(SqList * list);		/*清空线性表list*/
Status ListEmpty(SqList list);		/*判断线性表是否为空表,空表返回TRUE,非空返回FALSE*/
int ListLength(SqList list);		/*返回list的元素个数*/
Status GetElem(SqList list,int i, ElemType * elemPtr);	/*从list中获取第i个元素,并将获取到的元素放到 elemPtr指针中,
							  获取到返回OK,否则返回ERROR */
int LocateElem(SqList list,ElemType elem);		/*在list中查找数据元素elem的位置*/

Status PriorElem(SqList list ,ElemType elem, ElemType * elemPtr); /*在list中查找元素elem的前一个元素,并将找到的元素存放到elemPtr指针中*/
Status NextElem(SqList list, ElemType elem, ElemType * elemPtr);  /*在list中查找元素elem的后一个元素,并将找到的元素存放到elemPtr指针中*/
Status ListInsert(SqList * list,int i,ElemType elem);		/*在list的第i个位置插入元素elem*/
Status ListDelete(SqList * list,int i,ElemType * elemPtr);	/*在list中删除第i个元素,并将第i个元素存放到elemPtr指针中*/

Status Visit(ElemType elem);   /*对elem操作 */ 
Status ListTraverse(SqList list,Status (*visit)(ElemType));		/* 遍历表 */
Status ListUnion(SqList * listA,SqList listB);	/* 将listB 中的数据合并到listA中	*/
int main()
{
	
 int i,j;
 SqList list,listA,listB;
 ElemType  elem;
 InitList(&list);
 InitList(&listA);
 InitList(&listB);
 
 if(!ListTraverse(list,Visit))
 printf("list没有数据打印!\n");
 for(i=0;i<9;i++){
	ListInsert(&list,i+1,i+100);
	ListInsert(&listA,i+1,i+200);
 }
 for(i=5;i<30;i++)
	ListInsert(&listB,i+1,i+200);/* i=26的时候,listB的数量超过20个,会将存储空间扩容*/
 printf("list的数据:\t");
 ListTraverse(list,Visit); 
 if(PriorElem(list,103,&elem))
 printf("103前面的一个数字为;%d\n",elem);

 if(NextElem(list,103,&elem))
 printf("103后面的一个数字为:%d\n",elem);

 printf("在第2个位置插入999\n");
 ListInsert(&list,2,999);
 printf("list的数据:\t");
 ListTraverse(list,Visit); 

 ListDelete(&list,5,&elem);
 printf("删除第5个数字:%d\n",elem);
 printf("list的数据:\t");
 ListTraverse(list,Visit);
 i=ListUnion(&listA,listB); /*将listB数据合并到listA中*/
 j=4;
 printf("listA的数据为:\n");
 ListTraverse(listA,Visit);
 
 DestoryList(&listA);  	    /*销毁listA,释放地址*/
 DestoryList(&listB);
 DestoryList(&list);
 return 0;

}

 /*初始化线性表list*/
Status InitList(SqList *list)
{
	list->elem = (ElemType*) malloc(LIST_INIT_SIZE*sizeof(ElemType));
	if(list->elem == NULL)
		return ERROR;
	list->length = 0;
	list->listSize = LIST_INIT_SIZE;
	return OK;
} 

 /*销毁线性表list*/
void DestoryList(SqList * list)
{
  free(list->elem);
  list->elem = NULL;
  list->length = 0;
  list->listSize = 0;
}

 /*清空线性表list*/
void ClearList(SqList * list){
	list->length=0;
}

 /*判断线性表是否为空表,空表返回TRUE,非空返回FALSE*/
Status ListEmpty(SqList list){

	if(list.length>0)
		return FALSE;
	else 
		return TRUE;

}

/*返回list的元素个数*/
int ListLength(SqList list){
	return list.length;
}

/*从list中获取第i个元素,并将获取到的元素放到 elemPtr指针中,  获取到返回OK,否则返回ERROR */
Status GetElem(SqList list,int i,ElemType * elemPtr){
	if(list.length==0 || i<1 || i>list.length)
		return ERROR;
	*elemPtr= list.elem[i-1];
	return OK;
}

 /*在list中查找第一个和elem相等的元素的位置,如果没有找到,返回ERROR,即0 */
int LocateElem(SqList list,ElemType elem)
{
	int i=0;
	for(; i<list.length; i++)
		if(list.elem[i]==elem)
			return i+1;
	return ERROR;
}

 /*在list中查找元素elem的前一个元素,并将找到的元素存放到elemPtr指针中*/
Status PriorElem(SqList list,ElemType elem,ElemType * elemPtr){

	int i;
	for(i=1 ; i<list.length; i++)/*第一个元素i=0没有前导,所以从第二个元素i=1开始*/
	{
		if(list.elem[i]==elem ){
	    	  *elemPtr=list.elem[i-1];
		  return OK;
		}
	}
	return ERROR;

}

 /*在list中查找元素elem的后一个元素,并将找到的元素存放到elemPtr指针中*/
Status NextElem(SqList list, ElemType elem, ElemType * elemPtr)
{
	int i;
	for( i=0; i<list.length-1; i++)/*最后一个元素没有后驱元素,所以查找到倒数第二个元素就结束(下标为list.length-2)*/
	{
		if(list.elem[i]==elem && i<list.length-1){
		  *elemPtr=list.elem[i+1];
		  return OK;
		}
	}
	return ERROR;
}

  /*在list的第i个位置插入元素elem*/
 Status ListInsert(SqList * list,int i,ElemType elem){
	 
	 int j;
	 ElemType * base;
	 if(i<1) 
		return ERROR;
	 if(list->length==list->listSize)/*list满了,需要对list扩容*/{
		base=(ElemType *) realloc(list->elem,(list->listSize+LIST_INCREMENT)*sizeof(ElemType));
		if(base!=NULL){  	/*扩容成功,将新的基地址赋值给list->elem,并更新list的存储空间listSize*/
			list->listSize += LIST_INCREMENT;
			list->elem=base;
		}
		else 
		 	return ERROR;
	 }
	 

	 for(j=list->length-1; j>=i-1; j--) /* 从第i个数据开始,所有元素向后移一位 */ 
		list->elem[j+1]=list->elem[j];
	 list->elem[j+1]=elem;		   /*在第i个位置的值更新为新值elem, 此时的j=i-2, j+1=i-1,data[j+1]的位置就是第i个元素位置 */
	 list->length++;

	 return OK;
	
 }

  /*在list中删除第i个元素,并将第i个元素存放到elemPtr指针中*/
 Status ListDelete(SqList * list,int i,ElemType * elemPtr) 
{
	int j;
	if(i<1 || i>list->length)
		return ERROR;
	*elemPtr=list->elem[i-1];

	for(j=i-1; j<list->length-1; j++)
		list->elem[j]=list->elem[j+1];
	list->length--;
	return OK;
}	

/*对elem操作,具体什么操作可以根据需要修改,本示例中是打印elem的值*/
Status Visit(ElemType elem){
	printf("%d\t",elem);
}


/*遍历线性表,并对每一个元素调用Visit函数,一旦Visit()失败,这遍历失败 */
Status ListTraverse(SqList list, Status(*Visit) (ElemType elem) ){

	int i;
	if(list.length==0)
		return ERROR;
	for(i=0;i<list.length;i++)
		(*Visit)(list.elem[i]);
	printf("\n");
	return OK;
}

 
 	
 /* 将listB 中的数据合并到listA中,B的元素已经在A中存在,不重复插入 */
 Status  ListUnion(SqList * listA,SqList listB){

	 int i ;
	 ElemType  elem;

	 for(i=1; i<=listB.length; i++) /*循环listB所有元素 */
	 {
		 if( GetElem(listB,i,&elem) && !LocateElem(*listA,elem))/*在获取listB的元素,存放到变量elem中,在 listA中查找elem,不存在插入*/
		 ListInsert(listA,listA->length+1,elem);
	 }
	
	 return OK;

 }	 

三. 优缺点

优点:读取快

缺点:插入和删除需要移动大量元素; 存储空间会有浪费的情况

相关推荐
A_Tai23333333 分钟前
MyBatis高级扩展
java·开发语言·mybatis
夏子曦20 分钟前
java虚拟机——频繁发生Full GC的原因有哪些?如何避免发生Full GC
java·开发语言
Thomas_YXQ27 分钟前
Unity3D Lua如何支持面向对象详解
开发语言·游戏·junit·性能优化·lua·unity3d
MYBOYER31 分钟前
Kotlin DSL Gradle 指南
android·开发语言·kotlin
武昌库里写JAVA36 分钟前
SpringCloud+SpringCloudAlibaba学习笔记
java·开发语言·算法·spring·log4j
夏天吃哈密瓜38 分钟前
用Scala来解决成绩排名的相关问题
开发语言·后端·scala
subject625Ruben38 分钟前
代码美学:MATLAB制作渐变色
开发语言·matlab
小咖拉眯1 小时前
第十六届蓝桥杯模拟赛第二期题解—Java
java·数据结构·算法·蓝桥杯·图搜索算法
IRevers1 小时前
使用Python和Pybind11调用C++程序(CMake编译)
开发语言·c++·人工智能·python·深度学习
Sunyanhui11 小时前
力扣 最长回文字串-5
算法·leetcode·职场和发展