数据结构顺序表基本操作(C语言)

困扰了我两天的东西,经过不懈努力终于在今天给我整出来了,然后回首一看,才发现没什么太难的点,哎吃了上学期C语言上课睡觉的亏,关于结构体这一方面我到现在都是半懂,更不要说刚接手做这个顺序表的时候哦,这是数据结构课要求的,得谢谢老师。

我的代码可能在大佬眼里十分的浅显简单,确实如此,我的C语言结构这一部分就只能这样了,这个博客希望能给和我一样的同学一些启发一些帮助,也让我能随时来看看改改,如有大佬,望不吝赐教。

文末附点我这次作业的总结,方便以后这个需要实验报告的话来看看。


运行效果如图:(就截了个菜单界面)

目录

//主函数

//菜单

 //判空

 //创建

//打印

//查找

//奇偶分离

//判断是否对称

//插入

//归并

//排序

//删除

总结


//主函数

#define _CRT_SECURE_NO_WARNINGS 1//消除vs里scanf警告用的
#include<stdio.h>

typedef struct SqList {
	int arr[100];//结构体序列
	int length;//序列长度
}Sq;


int main() {
	system("TITLE 数据结构顺序表");
	Sq p;//创建一个结构体变量
	int n;//菜单选择数
	int count = 0;
//定义一个count计数,代表第一次进入程序还没有创建序列,传到每个函数用来判断是否是空序列,是就返回菜单,不是就继续操作
	p.length = 0;//初值为0,代表没有序列存在
	
	while (1) {
		//用死循环一直显示菜单直到自己选择退出
		menu();//显示菜单
		scanf("%d", &n);//输入选择值
		switch (n) {
		case 1:f1(&p); count++; break;//创建顺序表,创建序列后count++不再为零
		case 2:f2(&p,count); break;//输出顺序表
		case 3:f3(&p,count); break;//查找某元素
		case 4:f4(&p,count); break;//奇偶数分离
		case 5:f5(&p,count); break;//判断对称否
		case 6:f6(&p,count); break;//插入某序列
		case 7:
			if (count == 0)//count=0时,没有序列所以直接进入f7()后返回
				f7(&p,count);
			else//count不为零,说明有序列,所以进入f7()完成 操作并返回新序列
				p=f7(&p,count); //归并两序列,p接收归并后的新序列,p就是新序列了
			break;
		case 8:f8(&p,count); break;//按顺序排列
		case 9:f9(&p,count); break;//删除某序列
		case 10:system("cls"); break;//清屏
		case 0:printf("成功退出!"); return;
		default:printf("输入错误!请重新输入:\n");
		}
	}
	return 0;
}

//菜单

//菜单
void menu() {
	printf("**********************\n");
	printf("******顺序表操作******\n");
	printf("********0.退出********\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("----请输入你的选择----\n");
}

 //判空

//0.判断是否空序列
int f0(int count) {
	if (count == 0) {
		printf("当前没有序列!请先创建序列再进行操作!\n");
		return 0;
	}
	return 1;
}

 //创建


//1.创建顺序表
void f1(Sq* p) {
	int length;//作序列的大小
	int count1 = 0;
	//用来计数,记输入了几个数了,如果输入的数超出了既定的范围,那么就跳出循环,避免下次输入的值是缓存区残留

	//判断是否有序列存在
	if (p->length != 0) {
		printf("已有序列!请勿重复创建!\n");
		return;
	}
	printf("请输入你想创建的序列的大小:");
	scanf("%d", &length);
	if (length <= 0) {
		printf("创建失败!返回菜单!\n");
		return;
	}
	printf("请输入整数序列(输入-1可手动退出):");
	for (int i = 0; i < 100; i++) {
		scanf("%d", &p->arr[i]);
		count1++;
		if (p->arr[i] == -1) {
			printf("结束输入!\n");
			p->length += count1-1;
			return;
		}
		if (count1 >= length) {//当输入的个数大于了给定的范围
			while (getchar() != '\n') {//用getchar接收后面多余的数,直到接收到换行符
				;//空语句用来支持循环
			}
			break;//跳出外层的输入数的循环
		}
	}
	p->length = length;
	printf("录入成功!\n");
}

//打印

//2.输出顺序表
void f2(Sq* p, int count) {
	if (!(f0(count))) //先判断是否是个空列表,是就返回菜单,不是就向下操作
		return;
	int count1 = 0;//用来计数,打印一次加一,当他等于10的时候就换行,达到一排只打印十个数字的效果
	printf("当前的序列是:\n");
	for (int i = 0; i < p->length; i++) {
		printf("%2d ", p->arr[i]);
		count1++;
		if (count1 == 10) {
			printf("\n");
			count1 = 0;//重置count,方便下一排继续计数
		}
	}
	printf("\n");
	printf("----------------------\n");//换行,下一行是菜单
}

//查找

//3.查找某元素
void f3(Sq* p, int count) {
	if (!(f0(count)))//先判断是否是个空列表,是就返回菜单,不是就向下操作
		return;
	printf("请输入你想查找的元素:\n");
	int n;
	scanf("%d", &n);//输入查找的元素
	for (int i = 0; i < p->length; i++) {//遍历数组查找元素
		if (n == p->arr[i]) {
			printf("找到了!下标是:%d\n", i);
			return;
		}
	}
	printf("该序列中没有此元素!\n");
}

//奇偶分离


//4.奇偶数分离
//奇数在前偶数在后,不考虑大小顺序
void  f4(Sq* p, int count) {
	if (!(f0(count)))//先判断是否是个空列表,是就返回菜单,不是就向下操作
		return;
	int* p1 = &p->arr[0];//定义个头指针放在顺序表的第一个元素位置
	int* p2 = &p->arr[p->length - 1];//定义个尾指针放在顺序表的最后一个元素位置
	for (int i = 0; i < p->length; i++) {
		if ((*p1) % 2 == 0) {//第一种情况:如果第一个元素是个偶数,下面又分两种情况
			if ((*p2) % 2 != 0) {//①最后一个元素是个奇数
				//那么就将这俩个数交换,并且,头指针向后移动一格,尾指针向前移动一格
				int tmp = *p1;
				*p1 = *p2;
				*p2 = tmp;
				p1++;
				p2--;
			}
			else {//②最后一个元素是个偶数,那么最后一个偶数不需要动,将头指针向后移动一格直到它是一个奇数
				p2--;
			}
		}
		else {//第二种情况:如果第一个元素是奇数,下面又分两种情况:
			if ((*p2) % 2 == 0) {//①最后一个元素是偶数,这是我们的理想状态,所以不需要交换,只需移动指针
				p1++;//头指针后移一格
				p2--;//尾指针前移一格
			}
			else {//②最后一个元素是奇数,只将尾指针向前移动直到它是个偶数
				p1++;
			}
		}
		if (p1 >= p2)//循环退出条件:此时两个指针起码走在了一起,说明序列已经分离完毕
			break;//跳出循环
	}
	int count1 = 0;//计数,记有多少个奇数,用来分开打印奇数和偶数
	for (int i = 0; i < p->length; i++) {//遍历序列,得出有几个奇数
		if (p->arr[i] % 2 != 0) {
			count1++;
		}
	}
	printf("分离成功!\n");
	printf("奇数为:");
	for (int i = 0; i < count1; i++) {//打印奇数
		printf("%d ", p->arr[i]);
	}
	printf("\n");
	printf("偶数为:");
	for (int i = count1; i < p->length; i++) {//打印偶数
		printf("%d ", p->arr[i]);
	}
	printf("\n");
	printf("分离后的序列为:\n");
	//打印整个序列
	int count2 = 0;//用来计数,打印一次加一,当他等于10的时候就换行,达到一排只打印十个数字的效果
	for (int i = 0; i < p->length; i++) {
		printf("%2d ", p->arr[i]);
		count2++;
		if (count2 == 10) {
			printf("\n");
			count2 = 0;
		}
	}
	printf("\n");
	printf("----------------------\n");//换行,下一行是菜单
}

//判断是否对称

//5.判断对称否
void f5(Sq* p, int count) {
	if (!(f0(count)))//先判断是否是个空列表,是就返回菜单,不是就向下操作
		return;
	for (int i = 0; i < (p->length) / 2; i++) {//因为这里是头和尾两个一起比较,所以次数减半
		if (p->arr[i] != p->arr[p->length - 1 - i]) {
			printf("不对称!\n");
			return;
		}
	}
	printf("对称!\n");
}

//插入

//6.插入序列
void f6(Sq* p, int count) {
	if (!(f0(count)))//先判断是否是个空列表,是就返回菜单,不是就向下操作
		return;
	int num;//插入序列的大小
	printf("请输入要插入序列的大小:");
	scanf("%d", &num);
	if (num <= 0) {//判断要插入的序列大小是否不合理
		printf("插入失败!返回菜单!\n");
		return;
	}
	printf("请输入要插入的序列元素:");
	int count1=p->length;//计数
	for (int i = p->length; i < p->length + num; i++) {
		scanf("%d", &p->arr[i]);//输入要插入的序列
		count1++;
		if (count1 >= p->length+num) {//当输入的个数大于了给定的范围
			while (getchar() != '\n') {//用getchar接收后面多余的数,直到接收到换行符
				;//空语句用来支持循环
			}
			break;//跳出外层的输入数的循环
		}
	}
	p->length += num;//更新序列的长度
	printf("添加成功!\n");
}

//归并


//7.归并序列
Sq f7(Sq* p, int count) {
	if (!(f0(count)))//先判断是否是个空列表,是就返回菜单,不是就向下操作
		return *p;//因为在主函数那边有个结构体变量p接收本函数返回的新序列,所以得有个返回值,因为现在没有归并,所以直接返回原序列

	printf("请注意:你确认当前的序列是有序的吗?\n*1.确认继续*\n*0.返回菜单*\n请输入:");
	int intput;
	scanf("%d", &intput);
	if (intput == 0)
		return *p;//因为在主函数那边有个结构体变量p接收本函数返回的新序列,所以得有个返回值,因为现在没有归并,所以直接返回原序列

	printf("抱歉!现在只有一个序列,请再新建一个顺序序列!\n");
	printf("新建序列:");
	Sq q;//新建一个结构体变量用来创建第二个序列
	q.length = 0;//向f1()表示当前这个结构体没有序列
	f1(&q);//创建序列
	printf("请稍后...\n");

	//判断原序列是否是从小到大排列的
	for (int i = 1; i < p->length; i++) {
		if (p->arr[i - 1] <= p->arr[i]) {
			;//空语句,如果满足条件不需要做什么所以这里放个空语句,接下来就是执行i++
		}
		else {
			printf("对不起!原序列不是一个顺序序列不能进行归并!\n");
			return *p;//因为在主函数那边有个结构体变量p接收本函数返回的新序列,所以得有个返回值,因为现在没有归并,所以直接返回原序列
		}
	}
	//判断新建序列是否是从小到大排列的
	for (int i = 1; i < q.length; i++) {
		if (q.arr[i - 1] <= q.arr[i]) {
			;//空语句,如果满足条件不需要做什么所以这里放个空语句,接下来就是执行i++
		}
		else {
			printf("对不起!新序列不是一个顺序序列不能进行归并!\n");
			return *p;//因为在主函数那边有个结构体变量p接收本函数返回的新序列,所以得有个返回值,因为现在没有归并,所以直接返回原序列
		}
	}

	Sq new;//新建一个结构体变量,用来作归并后的新序列
	new.length = p->length + q.length;//归并后的序列长度是两个序列的长度之和
	//将两个序列归并
	for (int i = 0; i < new.length; i++) {
		if (i < p->length)
			new.arr[i] = p->arr[i];
		if (i >= p->length)
			new.arr[i] = q.arr[i - (p->length)];//i - (p->length)这一部分就代表着i是从开始的
	}
	//这里冒泡排序用来排序归并后的新序列
	for (int i = 0; i < new.length - 1; i++) {
		for (int j = 0; j < new.length - 1 - i; j++) {
			if (new.arr[j] > new.arr[j + 1]) {
				int tmp = new.arr[j];
				new.arr[j] = new.arr[j + 1];
				new.arr[j + 1] = tmp;
			}
		}
	}
	printf("归并后的新序列:\n");
	int count1 = 0;//用来计数,打印一次加一,当他等于10的时候就换行,达到一排只打印十个数字的效果
	for (int i = 0; i < new.length; i++) {
		printf("%2d ", new.arr[i]);
		count1++;
		if (count1 == 10) {
			printf("\n");
			count1 = 0;
		}
	}
	printf("\n");
	printf("----------------------\n");//换行,下一行是菜单
	return new;//返回新序列
}

//排序

//8.排序
void f8(Sq* p, int count) {
	if (!(f0(count)))//先判断是否是个空列表,是就返回菜单,不是就向下操作
		return;
	//依旧是冒泡排序
	for (int i = 0; i < p->length - 1; i++) {
		for (int j = 0; j < p->length - 1 - i; j++) {
			if (p->arr[j] > p->arr[j + 1]) {
				int tmp = p->arr[j];
				p->arr[j] = p->arr[j + 1];
				p->arr[j + 1] = tmp;
			}
		}
	}
	printf("排序完成!排序后的序列:\n");
	int count1 = 0;//用来计数,打印一次加一,当他等于10的时候就换行,达到一排只打印十个数字的效果
	for (int i = 0; i < p->length; i++) {
		printf("%2d ", p->arr[i]);
		count1++;
		if (count1 == 10) {
			printf("\n");
			count1 = 0;
		}
	}
	printf("\n");
	printf("----------------------\n");//换行,下一行是菜单
}

//删除

//9.删除某序列
void f9(Sq* p, int count) {
	if (!(f0(count)))//先判断是否是个空列表,是就返回菜单,不是就向下操作
		return;
	printf("请输入要删除的元素个数:");
	int num;//要删除的元素个数
	int index;//要删除的序列的头元素得下标
	scanf("%d", &num);
	if (num == p->length) {//如果删除个数和元素个数一样多也就是全部删除的话
		for (int i = 0; i < p->length; i++) {
			p->arr[i] = p->arr[i + num];//将后面的空值赋给序列
		}
		p->length -= num;//删除过后要将长度减少
		printf("删除成功!请按2输出查看!\n");
		return *p;
	}
	else if (num < 1) {
		printf("没有要删除的序列,返回菜单!\n");
		return;
	}
	else if (num == 1) {
		printf("请输入要删除的元素下标:");
		scanf("%d", &index);
		if (index > p->length - 1) {//判断要删除的一个元素是否存在
			printf("没有该元素!返回菜单!\n");
				return;
		}
		for (int i = index; i <= p->length - 1; i++) {
			p->arr[i] = p->arr[i + 1];
		}
		p->length--;
		printf("删除成功!请按2输出查看!\n");
	}
	else if(num>p->length){//如果要删除的元素大于序列总元素,那就从给定的位置向后删除直到最后一个元素
		printf("请输入要删除序列的开始元素下标:");
		scanf("%d", &index);
		for (int i = index; i < p->length; i++) {
			p->arr[index] = p->arr[index + num];
		}
		p->length -= index;//不能直接减去num,因为怕从输入的下标开始到最后的元素并没有num这么多
		//比如:输入num=5,序列总共就才5个元素,然后输入开始删除的下标3,这样从下标3的元素到末尾并没有够5个数
		//所以事实上只删除了两个数,所以长度也减少2而不是减少5
		printf("删除成功!请按2输出查看!\n");
	}
	else {//要删除的元素个数大于1小于序列长度时
		printf("请输入要删除的元素下标:");
		scanf("%d", &index);
		if (index + num > p->length) {//如果从给定位置开始删除给定的个数时,元素不够
			//比如共有五个元素,给定删除个数3,给定下标位置3,需要删除位置3和后面的两个元素,但是后面只有一个元素存在
			//所以还是只删除当前位置到末尾
			for (int i = index; i < p->length; i++) {
				p->arr[index] = p->arr[index + num];
			}
			p->length -= index;
			printf("删除成功!请按2输出查看!\n");
			return;
		}
		else {
			for (int i = index; i < index + num; i++) {//这里的循环条件代表着要删除的地方
				p->arr[i] = p->arr[i + num];
			}
			p->length -= num;
			printf("删除成功!请按2输出查看!\n");
			return;
		}
	}
	return;
}

欢迎评论指出问题!

总结

typedef struct A{

int arr[10];

int length;

……

}a;

1.这个A是类型,用在创建结构体变量的时候:struct A p;//创建一个结构体变量p。

2.这个a是结构体类型名,因为加了typedef,所以要在 } 后面给A编个名字,这样的话方便书写,在创建结构体变量就不用像上面那样要写struct了:a p;//创建一个结构体变量p。

3.结构体变量不用非得创建在函数体内,可以在函数体外创建:在函数内创建就是个局部变量,只能在这个函数里用;在函数体外创建就是个全局变量,每个函数内都可以直接用。

4.结构体也可以在函数体内创建也可在函数体外创建,在函数体内创建的话,那么结构体变量也就只能在函数内创建,是个局部变量,只能在这个函数内生效;如果结构体在函数体外创建,那么结构体变量就如上面第三点。

5.结构体内的 int arr[10]和int length都是结构体变量的属性,类型是int,要想调用的话一般是用点操作符“.” :结构体变量名.属性名,如:p.arr[10];p.length;

还有一种就是用“->”操作符:结构体变量名->属性名,如:p->arr[10];p->length;

当然二者有所区别,“.“是用来一个数据类型联系其子数据的,而用“->”的必须得是个指针,在这就不写例子了,在上面程序中有。

 暂记载这么多,啥时候想起来了在更新。


推荐博客:

斐波那契数列问题👇:

Java基础——斐波那契数列问题之兔子不死会有几只兔子_多低调的博客-CSDN博客_兔子数列

鸡兔同笼问题👇:

Java基础for——鸡兔同笼问题(穷举法)_多低调的博客-CSDN博客

数据结构中的顺序表(Sequential List)是用一段连续的存储单元依次存储数据元素的线性结构。在C语言中,顺序表通常可以通过数组来实现。基本操作包括初始化、插入、删除、查找、获取元素和更新元素等。 1. 初始化:创建一个固定大小的数组,用于存储顺序表的元素,并初始化长度为0。 2. 插入:在顺序表的指定位置插入一个新元素,需要移动插入位置之后的所有元素,以保证数据的连续性。 3. 删除:删除顺序表中指定位置的元素,并将删除位置之后的元素前移,以填补空缺。 4. 查找:在顺序表中查找给定值的第一个匹配元素的位置。 5. 获取元素:获取顺序表中指定位置的元素值。 6. 更新元素:修改顺序表中指定位置的元素值。 以下是一个简单的顺序表插入操作的C语言示例代码: ```c #include <stdio.h> #include <stdbool.h> #define MAX_SIZE 10 // 定义顺序表的最大长度 typedef struct { int data[MAX_SIZE]; // 存储顺序表的数组 int length; // 顺序表当前长度 } SeqList; // 初始化顺序表 void InitList(SeqList *L) { L->length = 0; } // 在顺序表的第i个位置插入新元素e bool ListInsert(SeqList *L, int i, int e) { if (i < 1 || i > L->length + 1 || L->length == MAX_SIZE) { return false; // 插入位置不合法或表满 } for (int j = L->length; j >= i; j--) { L->data[j] = L->data[j - 1]; // 将第i个位置及之后的元素后移 } L->data[i - 1] = e; // 在位置i处放入新元素 L->length++; return true; } // 主函数 int main() { SeqList L; InitList(&L); ListInsert(&L, 1, 10); // 在位置1插入元素10 // ... 可以继续调用ListInsert等函数进行操作 return 0; } ```
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

多低调

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

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

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

打赏作者

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

抵扣说明:

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

余额充值