【数据结构实验】串的块链存储DEMO

该实验探讨了如何使用单链表存储串值,以优化顺序串上的插入和删除操作。通过构建链串,实现了包括赋值、比较、求串长、连接、取子串、插入和删除在内的多种操作。文章还提供了代码示例,强调了malloc分配变量的注意事项,并指出链式存储在大量插入删除操作中的优势,但存储空间利用率较低。
摘要由CSDN通过智能技术生成

一、实验要求
顺序串上的插入和删除操作不方便,需要移动大量的字符。因此,我们可用单链表方式来存储串值。这种存储方式适用于需要进行大量的字符串插入删除操作的场景。
构建一个链串,要求至少能完成如下操作:
赋值、比较、求串长、联接、取子串、插入(前插、后插)、删除、清除。

二、参考代码
为了锻炼阅读代码的能力,本文的全部代码都不作详细注释。如果难以看懂,可以在草稿纸上模拟代码的执行过程再进行理解。
代码及其简要注释:
1、malloc 分配的变量不会被初始化,且 malloc 不会调用构造函数来给变量赋值。因此在 malloc 分配了变量后,如果需要给一个默认值,必须手动调用相应的构造函数。如果是直接声明变量或用 new 分配变量地址,那么构造函数会被自动调用。构造函数不返回任何值,也不需要写 void 。
2、部分函数要求传入区间 [l, r] 作为参数,且会自动检测是否 l > r 。如果是,交换两个端点。
3、有的函数会返回 bool 类型,true 和 false 代表操作成功和操作失败(操作未执行)。
4、lstrcmp 函数返回正值代表串 s(第一个字符串)比 t(第二个字符串)的字典序大,返回负数代表 s 比 t 的字典序小,返回 0 代表 s 和 t 相等。
5、将串写成类似链表的形式是针对大量插入删除操作的场景的,这种方式的存储空间利用率很低。读者可以尝试在每个节点同时存储多个字符来减小存储空间的占用。
6、代码仅供参考。随着运行持续时间的增加,从 Visual Studio 中发现内存占用一直在增长。我并没有在代码中发现内存泄漏,为何内存占用会越来越多,原因暂时不明。
7、本链式串中每个串的结尾会留一个空节点,储存字符为 0 ,下一个节点的指针为 nullptr 。

#include<cstdio>
#include<algorithm>
#include<random>
#include<cstring>
#include<ctime>
typedef unsigned long long ull;
#pragma warning(disable:4996)

struct schar {
	char c = 0; schar* next = nullptr;
	schar(schar* p);
};
struct lstring {
	schar* string = nullptr; ull len = 0;
	lstring();
	lstring(lstring* p);
};

char str[1025]; lstring s, t, u, v; std::default_random_engine d; ull l, a, b; int cmpres;
std::uniform_int_distribution<short> c(32, 126); std::uniform_int_distribution<ull> x(1, 128);

inline schar::schar(schar* p) {
	p->c = 0, p->next = nullptr;
}

inline lstring::lstring() {
	this->string = (schar*)malloc(sizeof(schar)), schar::schar(this->string);
}

inline lstring::lstring(lstring* p) {
	p->string = (schar*)malloc(sizeof(schar)), schar::schar(p->string);
}

template<typename _Ty> inline _Ty randint(_Ty l, _Ty r) {
	if (l > r)std::swap(l, r);
	std::uniform_int_distribution<_Ty> u(l, r); return u(d);
}

inline void printlstr(const lstring& s) {
	schar* p = s.string;
	while (p->next != nullptr) { putchar(p->c), p = p->next; }
}

inline void clearlstr(lstring& s) {
	if (s.string == nullptr)return;
	schar* p = s.string, * q;
	while (p->next != nullptr) { q = p, p = p->next, free(q); }
	s.len = 0, s.string = p;
}

inline void lstrassign(lstring& s, const char* str) {
	if (s.string->next != nullptr)clearlstr(s);
	s.len = strlen(str); schar* p = s.string;
	for (ull i = 0; i < s.len; ++i) { p->c = str[i], p->next = (schar*)malloc(sizeof(schar)), schar::schar(p->next), p = p->next; }
}

inline void lstrcpy(lstring& dest, const lstring& src) {
	if (dest.string->next != nullptr)clearlstr(dest);
	dest.len = src.len; schar* p = dest.string, * q = src.string;
	for (ull i = 0; i < dest.len; ++i) { p->c = q->c, p->next = (schar*)malloc(sizeof(schar)), schar::schar(p->next), p = p->next, q = q->next; }
}

inline int lstrcmp(const lstring& s, const lstring& t) {
	ull l = std::min(s.len, t.len); schar* p = s.string, * q = t.string;
	for (ull i = 0; i < l; ++i) {
		if ((*p).c != (*q).c)return (*p).c - (*q).c;
		p = p->next, q = q->next;
	}
	return 0;
}

inline void lstrcat(lstring& dest, const lstring& s, const lstring& t) {
	if (dest.string->next != nullptr)clearlstr(dest);
	dest.len = s.len + t.len; schar* p = s.string, * r = dest.string;
	for (ull i = 0; i < s.len; ++i) { r->c = p->c, r->next = (schar*)malloc(sizeof(schar)), schar::schar(r->next), r = r->next, p = p->next; }
	p = t.string;
	for (ull i = s.len; i < dest.len; ++i) { r->c = p->c, r->next = (schar*)malloc(sizeof(schar)), schar::schar(r->next), r = r->next, p = p->next; }
}

inline lstring sublstr(const lstring& s, ull l, ull r) {
	if (l > r)std::swap(l, r);
	if (l >= s.len)l = s.len - 1;
	if (r >= s.len)r = s.len - 1;
	lstring t; t.len = r - l + 1; schar* p = s.string, * q = t.string;
	for (ull i = 0; i < l; ++i) { p = p->next; }
	for (ull i = l; i <= r; ++i) { q->c = p->c, p = p->next, q->next = (schar*)malloc(sizeof(schar)), schar::schar(q->next), q = q->next; }
	return t;
}

inline bool lstrins_front(lstring& dest, const char* str, ull off) {
	ull l = strlen(str); if (l == 0)return false;
	if (off >= dest.len)off = dest.len - 1;
	ull l0 = l - 1, off0 = 0; schar* o, * p = dest.string, * q = (schar*)malloc(sizeof(schar)), * r = q; schar::schar(q);
	if (off != 0)off0 = off - 1;
	for (ull i = 0; i < off0; ++i) { p = p->next; }
	o = p, p = p->next;
	for (ull i = 0; i < l0; ++i) { q->c = str[i], q->next = (schar*)malloc(sizeof(schar)), schar::schar(q->next), q = q->next; }
	q->c = str[l0], q->next = p, dest.len += l;
	if (off == 0) { q->next = dest.string, dest.string = r; return true; }
	o->next = r; return true;
}

inline bool lstrins_rear(lstring& dest, const char* str, ull off) {
	ull l = strlen(str); if (l == 0)return false;
	if (off >= dest.len)off = dest.len - 1;
	ull l0 = l - 1; schar* o, * p = dest.string, * q = (schar*)malloc(sizeof(schar)), * r = q; schar::schar(q);
	for (ull i = 0; i < off; ++i) { p = p->next; }
	o = p, p = p->next;
	for (ull i = 0; i < l0; ++i) { q->c = str[i], q->next = (schar*)malloc(sizeof(schar)), schar::schar(q->next), q = q->next; }
	q->c = str[l0], q->next = p, dest.len += l;
	o->next = r; return true;
}

inline bool lstrins_front(lstring& dest, const lstring& src, ull off) {
	if (src.len == 0)return false;
	if (off >= dest.len)off = dest.len - 1;
	lstring* Src = (lstring*)malloc(sizeof(lstring)); lstring::lstring(Src); lstrcpy((*Src), src);
	ull l0 = src.len - 1, off0 = 0; schar * o, *p = dest.string, *s = (*Src).string;
	if (off != 0)off0 = off - 1;
	for (ull i = 0; i < off0; ++i) { p = p->next; }
	o = p, p = p->next;
	for (ull i = 0; i < l0; ++i) { s = s->next; }
	s->next = p, dest.len += src.len;
	if (off == 0) { s->next = dest.string, dest.string = (*Src).string; return true; }
	o->next = (*Src).string; return true;
}

inline bool lstrins_rear(lstring& dest, const lstring& src, ull off) {
	if (src.len == 0)return false;
	if (off >= dest.len)off = dest.len - 1;
	lstring* Src = (lstring*)malloc(sizeof(lstring)); lstring::lstring(Src); lstrcpy((*Src), src);
	ull l0 = src.len - 1; schar* o, * p = dest.string, * r = p, * s = (*Src).string;
	for (ull i = 0; i < off; ++i) { p = p->next; }
	o = p, p = p->next;
	for (ull i = 0; i < l0; ++i) { s = s->next; }
	s->next = p, dest.len += src.len;
	o->next = (*Src).string; return true;
}

inline bool lstrdel(lstring& s, const ull& l, const ull& r) {
	if (l > r || l >= s.len || r >= s.len)return false;
	schar* p = s.string, * q, * t; ull l0 = 0;
	if (l != 0)l0 = l - 1;
	for (ull i = 0; i < l0; ++i)p = p->next;
	t = p, s.len -= r - l + 1; if (l != 0)p = p->next;
	for (ull i = l; i <= r; ++i) { q = p, p = p->next, free(q); }
	if (l == 0) { s.string = p; return true; }
	t->next = p; return true;
}

int main(){
	d.seed(clock());
	for (;;) {
		l = x(d); for (ull i = 0; i < l; ++i) { str[i] = c(d); } str[l] = 0;
		lstrassign(s, str);
		printf("Generated char array str = \"%s\" and assigned it to link string s. The content of s is\n", str);
		printlstr(s), putchar('\n');
		printf("The length of s is %llu\n\n", s.len);

		lstrcpy(t, s);
		puts("Copied s to link string t. The content of t is");
		printlstr(t), putchar('\n');
		printf("The length of t is %llu\n\n", t.len);

		clearlstr(t);
		printf("Cleared link string t. Now the length of t is %llu. The content of t is\"", t.len), printlstr(t), puts("\"\n");
		
		l = x(d); for (ull i = 0; i < l; ++i) { str[i] = c(d); } str[l] = 0;
		lstrassign(t, str);
		printf("Generated char array str = \"%s\" and assigned it to link string t. The content of t is\n", str);
		printlstr(t), putchar('\n');
		printf("The length of t is %llu\n\n", t.len);
		
		cmpres = lstrcmp(s, t);
		if (cmpres > 0)puts("The lexicographic order of s is greater than t.\n");
		else if (cmpres < 0)puts("The lexicographic order of s is less than t.\n");
		else puts("Link string s and t are equal.\n");
		
		lstrcat(u, s, t);
		puts("Link string s and t have been catenated and written to u. The content of u is");
		printlstr(u), putchar('\n');
		printf("The length of u is %llu\n\n", u.len);
		
		a = randint(0ull, u.len), b = randint(0ull, u.len), v = sublstr(u, a, b);
		printf("Got a substring v at range of [%llu, %llu] from link string u. The content of v is\n", a, b);
		printlstr(v), putchar('\n');
		printf("The length of v is %llu\n\n", v.len);
		
		l = x(d); for (ull i = 0; i < l; ++i) { str[i] = c(d); } str[l] = 0;
		a = randint(0ull, u.len), lstrins_front(u, str, a);
		printf("Inserted char array str = \"%s\" before index %llu of link string u. The content of u is\n", str, a);
		printlstr(u), putchar('\n');
		printf("The length of u is %llu\n\n", u.len);
		
		l = x(d); for (ull i = 0; i < l; ++i) { str[i] = c(d); } str[l] = 0;
		a = randint(0ull, v.len), lstrins_rear(v, str, a);
		printf("Inserted char array str = \"%s\" after index %llu of link string v. The content of v is\n", str, a);
		printlstr(v), putchar('\n');
		printf("The length of v is %llu\n\n", v.len);
		
		a = randint(0ull, u.len), lstrins_front(u, s, a);
		fputs("Inserted link string s \"", stdout); printlstr(s);
		printf("\" before index %llu of link string u. The content of u is\n", a);
		printlstr(u), putchar('\n');
		printf("The length of u is %llu\n\n", u.len);

		a = randint(0ull, u.len), lstrins_rear(v, t, a);
		fputs("Inserted link string v \"", stdout); printlstr(t);
		printf("\" after index %llu of link string v. The content of v is\n", a);
		printlstr(v), putchar('\n');
		printf("The length of v is %llu\n\n", v.len);

		a = randint(0ull, u.len), b = randint(0ull, u.len);
		if (lstrdel(u, a, b) == false)puts("Something wrong with parameters. Deleting failed.");
		printf("Deleted a substring at range of [%llu, %llu] from link string u. The content of u is\n", a, b);
		printlstr(u), putchar('\n');
		printf("The length of u is %llu\n\n", u.len);

		puts("Input any character except EOF to continue...");
		if (getchar() == EOF)return 0;
		getchar(), putchar('\n');
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值