【数据结构实验】线性表DEMO

本文介绍了一种实现线性表的方法,包括插入、删除元素及两表归并的操作。通过构造随机数序列,演示了如何在C++中创建线性表,执行基本操作并最终将两个线性表合并到一个新表中。

一、实验要求
构造一个线性表,要求能够完成插入、删除操作,可以输出全部项的数据,并可以将两个线性表归并到第三个空表中。

二、参考代码
本代码通过构造一些随机数输入线性表来完成演示。导入 random 头文件后,构造随机均匀整数分布

std::uniform_int_distribution<unsigned int> u(a, b);

来获得一个均匀整数分布,范围是离散闭区间 [a, b] 。
此外,还需要声明一个随机引擎

std::default_random_engine d;

来获取随机数。通过调用 u(d) 就可以返回一个 [a, b] 范围内的随机整数。
随机引擎需要通过不同的种子来获取不同的随机数序列,这里采用 clock() 函数获得程序启动以来的毫秒数作为随机数种子。

为了训练读者阅读代码的能力,将不对代码作详细解释,只是提一些比较容易出错的地方:
1、函数

void *__cdecl malloc(size_t _Size)

的 _Size 参数是字节数,而不是数组长度。如果分配的空间不足导致写入超过已分配(已授予权限)内存的末端,将会出错。当然这个出错常常不是会立即终止程序并提示的,而是会在执行若干语句后才报错。越界访问可能会提示 Access Violation 或 0xC0000005 或 0xC0000374 或干脆只提示“触发了一个断点”而无任何错误代码。

#include<cstdio>
#include<algorithm>
#include<random>
#include<ctime>
#pragma warning(disable:4996)
unsigned n, p;
struct list { unsigned* data = nullptr, len = 0; };
inline void ins(list &L, const unsigned &pos, const unsigned &num){
	for (unsigned i = L.len; i > p; --i){ L.data[i] = L.data[i - 1]; }
	L.data[p + 1] = num; ++L.len;
}
inline void del(list &L, const unsigned &pos){
	for (unsigned i = pos; i < L.len; ++i){ L.data[i] = L.data[i + 1]; }
	--L.len;
}
int main(){
	for (;;){
		std::uniform_int_distribution<unsigned> u(1, 32), v(0, 62), w(0, 99);
		std::default_random_engine d; d.seed(clock());
		puts("建立线性表 L");
		list L; L.data = (unsigned*)malloc(256); 
		n = u(d); printf("本次输入数据共 %u 个:\n", n);
		for (unsigned i = 0; i < n; ++i){ L.data[i] = w(d); printf("%u ", L.data[i]); ++L.len; }
		printf("\n线性表 L 的长度 = %u\n", L.len);
		n = u(d);
		for (unsigned h = 0; h < n && L.len < 64; ++h) {
			p = v(d); if (p >= L.len) { --h; continue; }
			ins(L, p, v(d)); printf("在 L 的位置 %u 后插入数据 %u\n", p, L.data[p + 1]);
			puts("列表 L 的所有项:");
			for (unsigned i = 0; i < L.len; ++i){ 
				printf("%u ", L.data[i]);
				if (i == p)putchar('*');
			}
			printf("\n线性表 L 的长度 = %u\n", L.len);
		}
		n = u(d); putchar('\n');
		for (unsigned h = 0; h < n && L.len > 0; ++h) {
			p = v(d); if (p >= L.len) { --h; continue; }
			del(L, p); printf("删除 L 的位置 %u 的数据\n", p);
			puts("列表 L 的所有项:");
			for (unsigned i = 0; i < L.len; ++i){
				printf("%u ", L.data[i]);
				if (i == p)putchar('*');
			}
			printf("\n线性表 L 的长度 = %u\n", L.len);
		}
		puts("\n建立线性表 M");
		list M; M.data = (unsigned*)malloc(256);
		n = u(d); printf("本次输入数据共 %u 个:\n", n);
		for (unsigned i = 0; i < n; ++i){ M.data[i] = w(d); printf("%u ", M.data[i]); ++M.len; }
		printf("\n线性表 M 的长度 = %u\n\n", M.len);
		n = u(d);
		for (unsigned h = 0; h < n && M.len < 64; ++h) {
			p = v(d); if (p >= M.len) { --h; continue; }
			ins(M, p, v(d)); printf("在 M 的位置 %u 后插入数据 %u\n", p, M.data[p + 1]);
			puts("列表 M 的所有项:");
			for (unsigned i = 0; i < M.len; ++i){
				printf("%u ", M.data[i]);
				if (i == p)putchar('*');
			}
			printf("\n线性表 M 的长度 = %u\n", M.len);
		}
		n = u(d); putchar('\n');
		for (unsigned h = 0; h < n && M.len > 0; ++h) {
			p = v(d); if (p >= M.len) { --h; continue; }
			del(M, p); printf("删除 M 的位置 %u 的数据\n", p);
			puts("列表 M 的所有项:");
			for (unsigned i = 0; i < M.len; ++i){
				printf("%u ", M.data[i]);
				if (i == p)putchar('*');
			}
			printf("\n线性表 M 的长度 = %u\n", M.len);
		}
		puts("将表 L 和表 M 合并为表 N\n");
		puts("列表 L 的所有项:");
		for (unsigned i = 0; i < L.len; ++i) { printf("%u ", L.data[i]); }
		printf("\n线性表 L 的长度 = %u\n", L.len);
		puts("列表 M 的所有项:");
		for (unsigned i = 0; i < M.len; ++i) { printf("%u ", M.data[i]); }
		printf("\n线性表 M 的长度 = %u\n", M.len);
		list N; N.len = L.len + M.len; N.data = (unsigned*)malloc(4 * N.len);
		std::copy(&L.data[0], &L.data[L.len], &N.data[0]);
		std::copy(&M.data[0], &M.data[M.len], &N.data[L.len]);
		puts("\n列表 N 的所有项:");
		for (unsigned i = 0; i < N.len; ++i) { printf("%u ", N.data[i]); }
		printf("\n线性表 N 的长度 = %u\n", N.len);
		free(L.data); free(M.data); free(N.data);
		puts("\n要继续,输入任意字符;否则,输入EOF");
		if (getchar() == EOF)return 0;
	}
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值