串的块链存储结构(待改,欢迎指正)

注:主函数中的操作和参数是直接以实参的形式放在了调用的函数中
"加油站"指的是解决 从头指针一直扫描到当前所需要的指针的繁杂问题 的办法,即如设置加油站一样在串中设置一些特定的指示性指针。(下图中的程序未用此方法)

#include<iostream>
#include<cstdio>
using namespace std;

const int OK = 1;
const int overflow = -2;
const int ERROR = 0;
const int TRUE = 1;
const int FALSE = 0;
const int CHUNKSIZE = 4;

typedef int Status;
typedef struct Chunk //结点
{
	char ch[CHUNKSIZE];
	struct Chunk* next;
}Chunk;

typedef struct        //链表
{
	Chunk* head;
	Chunk* tail;
	int curlen; //串的当前长度(结点数)
}LString;
const char blank = '#';//填补空余的标准
const char del = '@';//被删除的标志
/**************函数声明****************/
Status SLength(char S[]);
//返回数组S的长度

Status InitString(LString& T);

Status StrAssign(LString& T, char chars[]);
//生成一个值等于chars的串T

Status StrCopy(LString& T, LString S);
//由S复制得到串T

Status StrEmpty(LString S);
//若为空则返回TRUE

Status StrCompare(LString S, LString T);
//若S>T,则返回值>0;若S=T,则返回值=0;若S<T,则返回值<0

Status StrLength(LString S);

Status ClearString(LString &S);

Status Concat(LString &S1, LString S2);

Status SubString(LString& Sub, LString S, int pos, int len);
//用Sub返回子串

Status index(LString S, LString T, int pos);
//若T非空,主串S中第pos个字符之后存在与T相等的子串
//则返回第一个这样的子串在S中的位置,否则返回0

Status StrInsert(LString& S, int pos, LString T);
//在S的第pos个结点之后插入串T

Status StrDelete(LString &S, int pos, int len);

Status Replace(LString &news, LString S, LString T, LString V);
//用V替换主串S中出现的所有与T相等的不重叠的子串

Status StrPrint(LString T);
//输出字符串T

Status DestoryString(LString& T);

/************主函数**********/
int main()
{
	LString T1;
	LString T2;
	LString T3;
	LString Sub1;

	InitString(Sub1);

	char S1[11] = {"012354" };
	char S2[11] = { "012" };
	InitString(T1);
	StrAssign(T1, S1);
	cout << "T1:";
	StrPrint(T1);
	cout << endl << endl;

	cout << "输出复制T1后的T2:" << endl;
	InitString(T2);
	StrCopy(T2, T1);
	cout << "T2:";
	StrPrint(T2);
	cout << endl << endl;

	InitString(T3);
	StrAssign(T3, S2);
	cout << "T3:";
	StrPrint(T3);

	cout << endl << endl;
	cout << "T1和T3的比较结果:" << endl;
	if (StrCompare(T1, T3) > 0)
	{
		cout << "T1 > T3" << endl;
	}
	else if (StrCompare(T1, T3) < 0)
	{
		cout << "T1 < T3" << endl;
	}
	else
	{
		cout << "T1 = T3" << endl;
	}
	cout << "T1的(字符数)长度为:" << StrLength(T1);

	Concat(T1, T3);
	cout << endl << endl;
	cout << "T1和T3合并之后的结果:" << endl;
	StrPrint(T1);
	cout << endl << endl;

	cout << "插入T3后的T2:" << endl;
	StrInsert(T2, 1, T3);//此处的1是指结点的位置,而不是某个元素的位置
	StrPrint(T2);

	cout << endl << endl;
	SubString(Sub1, T2, 3, 7);
	cout << "所返回的子串Sub1为:" << endl;
	StrPrint(Sub1);

	cout << endl << endl;
	cout << "T3在T2的位置为:" << endl;
	cout << "位于第" << index(T2, T3, 2) << "个字符";
	cout << endl << endl;

	StrDelete(T2, 2, 3);
	cout << "删除指定元素后的串:" << endl;
	StrPrint(T2);
	return OK;
}

/*****************函数定义*******************/
Status SLength(char S[])
{
	int count = 0;
	int number = 0;
	while (S[number] != '\0')
	{
		count++;
		number++;
	}
	return count;
}

Status InitString(LString& T)
{
	Chunk* p = (Chunk*)malloc(CHUNKSIZE * sizeof(Chunk));
	if (!p)
	{
		exit(overflow);
	}
	T.head = p;
	T.tail = T.head;
	p->next = NULL;
	T.curlen = 0;
	return OK;
}

Status StrAssign(LString& T, char chars[])
{
	int i;
	int length = SLength(chars);
	int num = length / CHUNKSIZE;
	if (length % CHUNKSIZE)
	{
		num++;
	}
	T.curlen = num;//结点数量

	for (i = 0; i < num; i++)
	{
		Chunk* p = (Chunk*)malloc(CHUNKSIZE * sizeof(Chunk));
		if (!p)
		{
			exit(overflow);
		}
		T.tail->next = p;
		T.tail = p;

		if (i == num - 1 && (length % CHUNKSIZE) >= 1 && (length % CHUNKSIZE) < CHUNKSIZE)
		{
			for (int n = 0; n < (length % CHUNKSIZE); n++)
			{
				T.tail->ch[n] = chars[n + 4 * i];
			}

			for (int k = length % CHUNKSIZE; k <= (CHUNKSIZE - 1); k++)
			{
				T.tail->ch[k] = blank;
			}
		}
		else
		{
			for (int m = 0; m < CHUNKSIZE; m++)
			{
				T.tail->ch[m] = chars[m + 4 * i];
			}
			T.tail->next = NULL;
		}
	}
	return OK;
}
//生成一个值等于chars的串T

Status StrCopy(LString& T, LString S)
{
	for (int i = 0; i < S.curlen; i++)
	{
		Chunk* p = (Chunk*)malloc(CHUNKSIZE * sizeof(Chunk));
		if (!p)
		{
			exit(overflow);
		}
		T.tail->next = p;
		T.tail = p;
		for (int m = 0; m < CHUNKSIZE; m++)
		{
			T.tail->ch[m] = S.head->next->ch[m];
		}
		S.head = S.head->next;
	}
	T.curlen = S.curlen;
	return OK;
}
//由S复制得到串T

Status StrEmpty(LString S)
{
	if (S.curlen == 0)
	{
		return TRUE;
	}
	else
	{
		return FALSE;
	}
}
//若为空则返回TRUE

Status StrCompare(LString S, LString T)
{
	for (int i = 0; i < S.curlen && i < T.curlen; i++)
	{
		for (int j = 0; j < CHUNKSIZE; j++)
		{
			if (S.head->next->ch[j] != T.head->next->ch[j])
			{
				return S.head->next->ch[j] - T.head->next->ch[j];
			}
		}
		S.head = S.head->next;
		T.head = T.head->next;
	}
	return 0;
}

Status StrLength(LString S)
{
	int count1 = S.curlen * CHUNKSIZE;
	int count2 = 0;
	for (int i = 0; i < CHUNKSIZE; i++)
	{
		if (S.tail->ch[i] == blank)
		{
			count2++;
		}
	}
	return count1 - count2;
}

Status ClearString(LString &S)
{
	S.tail = S.head;
	S.curlen = 0;
	return OK;
}

Status Concat(LString &S1, LString S2)
{
	S1.tail->next = S2.head->next;
	S1.tail = S2.tail;
	S1.curlen = S1.curlen + S2.curlen;
	return OK;
}

Status SubString(LString& Sub, LString S, int pos, int len) //(待改进)
{
	int n;//子串(Sub)应包含的结点(块)数
	n = len / CHUNKSIZE;
	if (len % CHUNKSIZE)
	{
		n++;
	}
	Sub.curlen = n;
	for (int i = 0; i < n; i++)
	{
		Chunk* p = (Chunk*)malloc(sizeof(Chunk) * CHUNKSIZE);
		if (!p)
		{
			exit(overflow);
		}
		Sub.tail->next = p;
		Sub.tail = p;
	}

	Chunk* q = NULL;//指向S中待操作块的指针
	Chunk* k = NULL;//指向Sub中待操作块的指针

	k = Sub.head->next;

	int Nodeplace = pos / CHUNKSIZE; //第一个所求字符所在结点的位序
	if (pos % CHUNKSIZE)
	{
		Nodeplace++;
	}

	for (int i = 0; i < Nodeplace; i++)
	{
		q = S.head->next; //"加油站"的问题
	}

	int Speplace = pos % CHUNKSIZE; //某字符在数组中的具体位置

	for (int j = 0; j < len; j++)
	{
		if (Speplace != 1 && (Speplace ) % CHUNKSIZE == 1)
		{
			Speplace = Speplace - CHUNKSIZE;
			q = q->next;
		}
		if (j != 0 && (j + 1) % CHUNKSIZE == 1)
		{
			k = k->next;//k = NULL error;
		}

		k-> ch[j % CHUNKSIZE] = q->ch[Speplace - 1];
		Speplace++;
	}

	if (len % CHUNKSIZE != 0)
	{
		for (int i = len % CHUNKSIZE; i < CHUNKSIZE; i++)
		{
			k->ch[i] = blank;
		}
	}

	return OK;
}
//用Sub返回子串

Status index(LString S, LString T, int pos)
{
	int m;				//T串长度
	int n;				//主串长度
	int i;
	LString sub;
	InitString(sub);

	if (StrLength(T) == 0)
	{
		return ERROR;
	}
	
	if (pos >= 1 && pos <= StrLength(S))
	{
		m = StrLength(T);
		n = StrLength(S);
		i = pos;
		while (i <= n - m + 1)
		{
			SubString(sub, S, i, m);
			if (StrCompare(sub, T) == 0)
			{
				return i;
			}
			else
			{
				i++;
			}
		}
	}
	return 0; //此处不写OK是为了表示没有符合条件的位序,用0表示
}
//定位函数![在这里插入图片描述](https://img-blog.csdnimg.cn/20200405181005191.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3d1cWlzZW45eg==,size_16,color_FFFFFF,t_70)

Status StrInsert(LString& S, int pos, LString T)
{
	S.curlen = S.curlen + T.curlen;
	Chunk* p = S.head; //中间变量
	Chunk* q;          //中间变量
	for (int i = 0; i < pos; i++)//"加油站问题"(此处效率较低,需要改进)
	{
		p = p->next;
	}
	q = p->next;
	p->next = T.head->next;
	T.tail->next = q;
	
	return OK;
}
//在S的第pos个结点之前插入串T

Status StrDelete(LString &S, int pos, int len)//未完成
{
	Chunk* p = S.head; //作为移动的指针
	int Nodeplace = 0; //被删除的字符串的第一个字符所在的结点位置
	int Speplace = pos % CHUNKSIZE; //该串的第一个字符所在结点的具体位置
	if ((pos % CHUNKSIZE) != 0)
	{
		Nodeplace = pos / CHUNKSIZE + 1;
	}
	else
	{
		Nodeplace = pos / CHUNKSIZE;
	}

	for (int i = 0; i < Nodeplace; i++)
	{
		p = p->next;
	}

	for (int i = 0; i < len; i++)
	{
		if (Speplace > CHUNKSIZE)
		{
			Speplace = Speplace - CHUNKSIZE;
			p = p->next;
		}
		p->ch[Speplace - 1] = del;
		Speplace++;
	}
	return OK;
}

Status StrPrint(LString T)
{
	cout << "(主串的结点数为" << T.curlen << ')' << endl;
	for (int i = 0; i < T.curlen; i++)
	{
		for (int j = 0; j < CHUNKSIZE; j++)
		{
			cout << T.head->next->ch[j] << ' ';
		}
		T.head = T.head->next;
	}
	return OK;
}
//输出字符串T

Status DestoryString(LString& T)
{
	if (!T.head)
	{
		free(T.head);
	}
	T.head = NULL;
	T.tail = NULL;
	T.curlen = 0;
	return OK;
}

在这里插入图片描述
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值