顺序表的基本操作与实现



前言

顺序表存储结构容易实现随机存取线性表的第i个数据元素的操作,但在插入或删除操作时要移动大量的数据元素,适合数据相对稳定的线性表。


提示:以下是顺序表的基本操作和实现代码,下面案例可供参考

1.头文件

代码如下(示例):

#include<stdio.h>
#include<stdlib.h>
#include<math.h>

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

//线性表的存储空间length初始分配量
#define LIST_INIT_SIZE 10
//线性表的存储空间的分配增加量(防止溢出)
#define LIST_INCREASE 2
//elem是单词element(元素)的缩写,在程序定义中代表某一不确定的类型,也就是抽象的数据类型
#define ElemType int

// Status 是函数的类型,其值是函数的返回结果,如OK等
typedef int Status;

struct Sqlist {
	ElemType* data;
	int length;//当前长度
	int list_size;//当前分配的存储容量
};

2.调用函数

//输出c
void Print(ElemType &c)
{
	printf("%d ", c);
}

//compare比较函数,符合条件
Status Compare(ElemType num1, ElemType num2)
{
	if (num1 == num2)
		return TRUE;
	else
		return FALSE;
}

3.基本操作函数

代码如下(示例):

//初始化线性表
void InitList(Sqlist& L)
{
	//malloc函数申请存储空间
	L.data = (ElemType*)malloc(LIST_INIT_SIZE*sizeof(ElemType));
	if (!L.data)
	{
		printf("内存分配失败!\n");
		exit(OVERFLOW);
	}
	L.length = 0;
	L.list_size = LIST_INIT_SIZE;//初始化存储容量
}

//销毁线性表
void DestoryList(Sqlist& L)
{
	free(L.data);//释放L.data所指的存储空间
	L.data = NULL;//L.data不再指向任何存储单元
	L.length = 0;
	L.list_size = 0;
}

//清空线性表,将L重置为空表
void ClearList(Sqlist& L)
{
	L.length = 0;
}

//输出线性表的长度
Status ListLength(Sqlist L)
{
	return L.length;
}

//若L存在,返回TRUE;否则返回FALSE
Status ListEmpty(Sqlist L)
{
	if (L.length == 0)
		return TRUE;
	else
		return FALSE;
}

//用e作为载体返回L中的第i个元素
Status GetData(Sqlist L, int i, ElemType &e)
{
	if (i<0 || i>L.length)
		return ERROR;
	e = *(L.data + i - 1);
	return e;
}

//找到第一个与e满足compare()的值的位置,返回其所在的位置
Status LocateData(Sqlist L, ElemType e, Status(*compare)(ElemType, ElemType))
{
	int i = 1;
	ElemType* p = L.data;
	while (i <= L.length && !compare(*p++, e))
		i++;
	if (i <= L.length)
		return i;
	else
		return 0;
}

//cur_e:线性表的值,pre_e:cur_e前驱
Status PriorData(Sqlist L, ElemType cur_e, ElemType& pre_e)
{
	int i = 2;
	ElemType* p = L.data + 1;
	while (i <= L.length && *p != cur_e)
	{
		i++;
		p++;
	}
	pre_e = *--p;
	if (i <= L.length)
		return pre_e;
	else
		return ERROR;
}

//next_e:所给元素cur_e的后继
Status NextData(Sqlist L, ElemType cur_e, ElemType& next_e)
{
	int i = 1;
	ElemType* p = L.data;
	while (i < L.length && *p++ != cur_e)
		i++;
	next_e = *p;
	if (i < L.length)
		return next_e;
	else
		return 0;
}

//在L的第i个位置之前插入新元素e
Status ListInsert(Sqlist L, int i, ElemType e)
{
	ElemType* newbase, * p, * q;
	if (i<1 || i>L.length + 1)
		exit(ERROR);
	if (L.length == L.list_size)//当前存储空间已满,再插入的话会溢出,需要增加分配
	{
		//realloc函数重新调整之前调用 malloc所分配的内存块的大小
		newbase = (ElemType*)realloc(L.data, (L.list_size + LIST_INCREASE) * sizeof(ElemType));
		if (!newbase)
		{
			printf("内存分配失败!\n");
			exit(ERROR);
		}
		L.data = newbase;
		L.list_size += LIST_INCREASE;
	}
	p = L.data + i - 1;
	for (q = L.data + i - 1; q <= L.data + L.length - 1; q++)
		*(q + 1) = *p;
	*p = e;
	L.length++;
	return OK;
}

//删除L中的第i个元素
Status ListDelete(Sqlist L, int i, ElemType e)
{
	ElemType* p;
	if (i<1 || i>L.length)//i值不合法
		return ERROR;
	for ( p = L.data + i - 1; p < L.data + L.length-1; p++)
		*p = *p + 1;
	L.length--;
	return OK;
}

//遍历顺序表,调用visit型的函数
void ListTravrse(Sqlist L, void(*visit)(ElemType &))
{
	ElemType* p=L.data;
	int i;
	for (i = 1; i <=L.length; i++)
		visit(*p++);
	printf("\n");
}

4.操作菜单

代码如下(示例):

void Menu()
{
	printf("请选择以下操作:\n");
	printf("1.初始化线性表\n");
	printf("2.销毁线性表\n");
	printf("3.清空线性表\n");
	printf("4.判断线性表是否为空\n");
	printf("5.求线性表的长度\n");
	printf("6.获取线性表指定位置的元素\n");
	printf("7.获取指定元素的位置\n");
	printf("8.求指定元素的前驱\n");
	printf("9.求指定元素的后继\n");
	printf("10.在线性表指定位置插入元素\n");
	printf("11.删除线性表指定位置的元素\n");
	printf("12.显示线性表\n");
	printf("13.获取线性表的元素\n");
	printf("14.合并两个非递减线性表\n");
	printf("输出一个负数退出\n");
	printf("\n");
}

5.调用菜单

void Choice(Sqlist L)
{
	while (1)
	{
		int choice, result;
		ElemType i = 0, e = 0;
		printf("请输入菜单序号:\n");
		scanf("%d", &choice);
		if (choice < 0)
		{
			printf("结束操作!");
			exit(ERROR);
		}
		switch (choice)
		{
		case 1:
			InitList(L);
			break;
		case 2:
			DestoryList(L);
			printf("操作成功!");
			break;
		case 3:
			ClearList(L);
			printf("操作成功!");
			break;
		case 4:
			if (ListEmpty(L))
				printf("线性表非空\n");
			else
				printf("线性表为空\n");
			break;
		case 5:
			printf("线性表的长度为:%d\n", ListLength(L));
			break;
		case 6:
			printf("请输入你想要获取的位置:");
			scanf("%d", &i);
			result = GetData(L, i, e);
			printf("此位置的元素为:%d\n", e);
			break;
		case 7:
			printf("请输入你想要获取的元素:");
			scanf("%d", &e);
			result = LocateData(L, e, Compare);
			printf("此元素的位置为:%d\n", result);
			break;
		case 8:
			i = 0;
			printf("请输入你想哪个元素的前驱:");
			scanf("%d", &e);
			result = PriorData(L, e, i);
			if (result)
				printf("此元素的前驱为:%d\n", result);
			break;
		case 9:
			i = 0;
			printf("请输入你想哪个元素的后继:");
			scanf("%d", &e);
			result = NextData(L, e, i);
			if (result)
				printf("此元素的后继为:%d\n", result);
			break;
		case 10:
			int n;
			printf("请输入你要插入的位置:");
			scanf("%d", &i);
			printf("请输入你要插入的数据:");
			scanf("%d", &e);
			result = ListInsert(L, i, e);
			printf("插入成功!此时的线性表为: ");
			ListTravrse(L, Print);
			break;
		case 11:
			printf("请输入你要删除的位置:");
			scanf("%d", &i);
			result = ListDelete(L, i, e);
			printf("删除成功!此时的顺序表为: ");
			ListTravrse(L, Print);
			break;
		case 12:
			printf("此时线性表为:");
			ListTravrse(L, Print);
			break;
		case 13:
			InsertData(L);
			break;
		case 14:
			Sqlist La, Lb, Lc;
			InitList(La);
			InitList(Lb);
			InsertData(La);
			InsertData(Lb);
			MergeList(La, Lb, Lc);
			printf("合并后的线性表为: ");
			ListTravrse(Lc, Print);
			break;
		default:
			printf("输入错误!!!请重新选择!\n");
			break;
		}
		Menu();
	}
}

6.主函数

代码如下(示例):

int main()
{
	Sqlist L;
	ElemType e;
	int i;

	InitList(L);

	Menu();
	Choice(L);

	return 0;
}

总结

提示:这里对文章进行总结:
例如:通过对基本操作有机地结合,就可以对线性表进行复杂的处理。


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值