【数据结构与算法】程序内功篇二--线性顺序表


一、线性表顺序存储

1、顺序存储结构的表示

若将线性表L=(a0,a1, ……,an-1)中的各元素依次存储于计算机一片连续的存储空间。

例如:

设Loc(ai)为ai的地址,Loc(a0)=b,
每个元素占d个单元 则:Loc(ai)=b+i*d

在这里插入图片描述


2、顺序存储结构的特点

  • 逻辑上相邻的元素 ai, ai+1,其存储位置也是相邻的
  • 对数据元素ai的存取为随机存取或按地址存取
  • 存储密度高

存储密度D=(数据结构中元素所占存储空间)/(整个数据结构所占空间)


3、顺序存储结构的表示

在C语言中,可借助于一维数组类型来描述线性表的顺序存储结构
如下:

#define  N 100        //宏定义储存数,方便调整
typedef   int  data_t; //重定义数据类型,方便数据转换
typedef  struct                     
{   data_t data[N]//表的存储空间
     int list;   //最后一位数据的位置
}   sqlist, *sqlink;

二、线性表的C程序实现

1、线性表的基本运算

(1)建立一个空表:list_create(L)

/**
 * @description: 顺序表创建 
 * @param {无}
 * @return {sqlink-成功返回顺序表的地址,NULL-失败返回}
 */
sqlink sqlist_creat()
{
	sqlink sq = (sqlist *)malloc(sizeof(sqlist));
	if(sq == NULL)
	{
		#if DEBUG
		printf("sqlist creat erorr!\n");
		#endif
		return NULL;
	}

	memset(sq,0,sizeof(sqlist));
	sq->list = -1;

	return sq;
}

(2)删除一个顺序表:list_delete(L)

/**
 * @description: 顺序表删除
 * @param {sqlink-传递顺序表的地址} 
 * @return {1-函数成功,0-函数失败}
 */
int sqlist_delete(sqlink sq)
{
	if(sq == NULL)
	{
		#if DEBUG
		printf("sqlist has been delete or sqlist isn't exist!\n");
		#endif
		return 0;
	}

	free(sq);
	sq = NULL;  //这里让局部变量的值为空,是不对的,注意一下

	return 1;
}

(3)置空表:list_clear(L)

/**
 * @description: 顺序表清空
 * @param {sqlink-传递顺序表的地址} 
 * @return {1-函数成功,0-函数失败}
 */
int sqlist_clear(sqlink sq)
{
	if(sq == NULL)
	{
		#if DEBUG
		printf("sqlist isn't exist!\n");
		#endif
		return 0;
	}

	if(sq->list == -1)
	{
		#if DEBUG
		printf("The sqlist has been clear!\n");
		#endif
		return 0;
	}
	else
	{
		memset(sq,0,sizeof(sqlist));
		sq->list = -1;
		return 1;
	}
}

(4)判断表是否为空:list_empty (L)

/**
 * @description: 查看顺序表是否为空
 * @param {sqlink-传递顺序表的地址} 
 * @return {1-表为空,-1,表不空,0-函数失败}
 */
int sqlist_empty(sqlink sq)
{
	
	if(sq == NULL)
	{
		#if DEBUG
		printf("sqlist isn't exist!\n");
		#endif
		return 0;
	}

	if(sq->list == -1)
		return 1;
	else
		return -1;
}

(5)求表长:length (L)

/**
 * @description:求顺序表长度 
 * @param {sqlink-传递顺序表的地址} 
 * @return {储存数据的长度,0-函数失败}
 */
int sqlist_length(sqlink sq)
{	
	if(sq == NULL)
	{
		#if DEBUG
		printf("sqlist isn't exist!\n");
		#endif
		return 0;
	}

	return sq->list+1;
}

(6)定位运算:Locate(L,x),确定元素x在表L中的位置(或序号)

/**
 * @description: 顺序表元素查找
 * @param {sqlink-传递顺序表的地址} 
 * @param {unsigned int-查找元素的位置} 
 * @return {i位置的元素,0-函数失败}
 */
int sqlist_element_query(sqlink sq,unsigned int i)
{	
	if(sq == NULL)
	{
		#if DEBUG
		printf("sqlist isn't exist!\n");
		#endif
		return 0;
	}
	if(i > sq->list)
	{	
		#if DEBUG
		printf("i too big\n");
		#endif
		return 0;
	}
	
	return sq->data[i];
}

(7)遍历列表

/**
 * @description: 顺序表遍历所有元素
 * @param {sqlink-传递顺序表的地址} 
 * @return {1-函数成功,0-函数失败}
 */
int sqlist_ergodic(sqlink sq)
{	
	int i;
	if(sq == NULL)
	{
		#if DEBUG
		printf("sqlist isn't exist!\n");
		#endif
		return 0;
	}
	if(sq->list == -1)
	{
		#if DEBUG
		printf("sqlist is empty!\n");
		#endif
		return 0;
	}
	for(i = 0; i < sq->list+1; i++)
		printf("%d ", sq->data[i]);
	puts("");

	return 1;
}

2、基本运算的相关算法

(1)插入:Insert(L,x,i)

将元素x插入到表L中第i个元素ai之前,且表长+1
插入前: (a0,a1,---,ai-1,ai,ai+1-------,an-1) 0≤i≤n,i=n时,x插入表尾
插入后: (a0,a1,---,ai-1, x, ai,ai+1-------,an-1)

算法思路

若表存在空闲空间,且参数i满足:0≤i≤L->last+1,则可进行正常插入。
插入前,将表中(L->data[L->last]~L->data[i])部分顺序下移一个位置
然后将x插入L->data[i]处即可。算法对应的表结构。

在这里插入图片描述

C程序实现

/**
 * @description: 顺序表插入数据
 * @param {sqlink-传递顺序表的地址}
 * @param {unsigned int-插入数据的位置} 
 * @param {data_t-插入的数据} 
 * @return {1-函数成功,0-函数失败}
 */
int sqlist_insert(sqlink sq, unsigned int i, data_t x)
{	
	int n;

	if(sq == NULL)
	{
		#if DEBUG
		printf("sqlist isn't exist!\n");
		#endif
		return 0;
	}
	if(sq->list == N-1)
	{
		#if DEBUG
		printf("sqlist already full!\n");
		#endif
		return 0;
	}
	if(i > sq->list+1)
	{
		#if DEBUG
		printf("i is too big!\n");
		#endif
		return 0;
	}

	for(n = sq->list; i < n+1; n--)
		sq->data[n+1] = sq->data[n];
	sq->data[i] = x;
	sq->list++;

	return 1;
}

(2)删除:DeleteSqlist(L, i)

将表中第i个元素ai从表中删除。

算法思路

若参数i满足:0≤i≤L->last,
将表中L->data[i+1]∽L->data[L->last] 部分顺序向上移动一个位置,
覆盖L->data[i]。

在这里插入图片描述
C程序实现

/**
 * @description: 删除中元素
 * @param {sqlink-传递顺序表的地址} 
 * @param {unsigned int-删除数据的位置} 
 * @return {1-函数成功,0-函数失败}
 */
int sqlist_element_delete(sqlink sq, unsigned int i)
{	
	if(sq == NULL)
	{
		#if DEBUG
		printf("sqlist isn't exist!\n");
		#endif
		return 0;
	}
	if(i > sq->list)
	{
		#if DEBUG
		printf("i is too big!\n");
		#endif
		return 0;
	}
	
	for(; i < sq->list; i++)
		sq->data[i] = sq->data[i+1];
	sq->data[sq->list] = 0;
	sq->list--;

	return 1;
}

(3)设线性表La=(a0a1, ……,am-1), Lb= (b0b1, ……,bn-1),求La与Lb的并集并用La表示

在这里插入图片描述
算法思路

依次取表Lb中的bi(i=0,1,……,n-1),
若bi不属于La,则将其插入表La中。

C程序实现

/**
 * @description: 两个顺序表求并集
 * @param {sqlink-传递顺序表1的地址} 
 * @param {sqlink-传递顺序表2的地址} 
 * @return {1-函数成功,0-函数失败}
 */
int sqlist_union(sqlink sq1, sqlink sq2)
{	
	int i,j;

	if(sq1 == NULL || sq2 == NULL)
	{
		#if DEBUG
		printf("sqlist isn't exist!\n");
		#endif
		return 0;
	}
	if(sq2->list == -1)
	{
		#if DEBUG
		printf("sqlist2 is empty!\n");
		#endif
		return 0;
	}

	for(i = 0; i < sq2->list+1; i++)
	{
		if(sq1->list == -1)
		{
			sq1->data[0] = sq2->data[i];
			sq1->list++;
		}
		for(j = 0; j < sq1->list+1; j++)
		{
			if(sq1->data[j] == sq2->data[i])
				break;	
		}
		if(j > sq1->list)
			sqlist_insert(sq1,sq1->list+1, sq2->data[i]);		
	}
	return 1;
}

(4)设计清除线性表L=(a0,a1,—,ai,-------,an-1)中重复元素的算法

算法思路

对当前表L中的每个ai(0≤i≤n-2),依次与aj(i+1≤j≤n-1) 比较,
若与ai相等,则删除之。

C程序实现

/**
 * @description: 顺序表删除重复元素
 * @param {sqlink-传递顺序表的地址} 
 * @return {1-函数成功,0-函数失败}
 */
int sqlist_repeat_delete(sqlink sq)
{
	int i,j;

	if(sq == NULL)
	{
		#if DEBUG
		printf("sqlist isn't exist!\n");
		#endif
		return 0;
	}
	if(sq->list == -1)
	{	
		#if DEBUG
		printf("sqlist is empty!\n");
		#endif
		return 0;
	}

	for(i = 1; i < sqlist_length(sq)+1; i++)
		for(j = 0; j < i; j++)
		{
			if(sq->data[i] == sq->data[j])
				sqlist_element_delete(sq, j);	
		}
	return 1;
}

最后这里给出整体文件的免费下载链接:
顺序表C程序
到这里就结束啦!
在这里插入图片描述

  • 8
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 15
    评论
顺序表是一种经典的数据结构,它可以用来存储一组具有相同数据类型的元素,并且这些元素在内存中是连续存储的。顺序表在内存中的存储方式类似于数组,因此可以通过下标来快速访问元素。 在顺序表中,元素的插入和删除操作可能会导致元素位置的移动,因此需要进行数据的搬移操作,这是其一个缺点。另外,顺序表的大小是固定的,一旦超过了预分配的空间,需要进行扩容操作。 算法解决问题的一系列步骤或规则。在数据结构与算法中,我们可以使用顺序表来实现各种常见的算法,比如线性查找、分查找、插入排序、选择排序等等。 线性查找是一种简单的查找算法,它从顺序表的第一个元素开始逐个比较,直到找到目标元素或者遍历完整个顺序表分查找是一种高效的查找算法,它只适用于有序顺序表,通过比较目标元素与中间元素的大小关系来确定查找范围,从而快速缩小查找范围。 插入排序是一种简单直观的排序算法,它通过构建有序子序列的方式来逐步扩大排序范围,将后面的元素插入到有序子序列的正确位置。 选择排序是一种简单的排序算法,它每次从未排序的元素中选择最小(或最大)的元素,然后放到已排序部分的末尾。 以上只是顺序表和部分相关算法的简单介绍,希望能对你有所帮助。如果你有更多关于顺序表算法的问题,请继续提问。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

修成真

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值