数据结构学习(五)

串存储结构

字符串要单独用一种存储结构来存储,称为串存储结构,串指的就是字符串。

串有三种存储方式

定长顺序存储结构(静态)

char str[100]="hello world";

堆分配存储结构(动态数组存储字符串)

void test1()
{
	char* str1 = (char*)malloc(10 * sizeof(char)); //申请10个char大小的动态数组
	char* str2 = (char*)malloc(10 * sizeof(char));

	strcpy_s(str1, strlen(str1)+1,"hello");
	strcpy_s(str2, strlen(str2)+1,"world");	

	int len1 = strlen(str1);
	int len2 = strlen(str2);

	if (len1 < len1 + len2)
	{
		str1 = (char*)realloc(str1, (len1+len2+1) * sizeof(char)); //如果不够可以进行申请空间 之前为10,现在扩大为len1+len2+1
	}
	for (int i = len1; i < len1 + len2; i++)
	{
		str1[i] = str2[i - len1];
	}
	str1[len1 + len2] = '\0';
	cout << str1 << endl;
}

链式存储结构

#define char_max_size 3
typedef struct linkchar
{
	char a[char_max_size];
	struct linkchar* next;
};
void printlinkchar(linkchar* c)
{
	linkchar* temp = c;
	while (temp->next != NULL)
	{
		for (int i = 0; i < char_max_size; i++)
		{
			cout << temp->a[i];
		}
		temp = temp->next;
	}
}
linkchar* initlinkchar(const char* a)
{
	linkchar* head = (linkchar*)malloc(sizeof(linkchar));
	head->next = NULL;

	linkchar* temp = head;

	int len = strlen(a);
	int num = len / char_max_size + 1;

	for (int i = 0; i < num; i++)
	{
		linkchar* b = (linkchar*)malloc(sizeof(linkchar));
		temp->next = b;
		b->next = NULL;
		for (int j = 0; j < char_max_size; j++)
		{
			if (char_max_size * i + j < len)
			{
				temp->a[j] = a[char_max_size * i + j];
			}
			else
			{
				temp->a[j] = ' ';
			}
		}		
		temp = b;
	}

	return head;
}

串模式匹配算法

BF算法

void BFpp(char* a, char* b)
{
	char* i = a;
	char* j = b;
	int lena = strlen(a);
	int lenb = strlen(b);
	int size = 0;
	int time = 0;
	while (strlen(a)>=strlen(b) && strlen(j)!=0)
	{
		if (*i == *j)
		{
			i++;
			j++;
			size++;
			time++;
		}
		else
		{
			j = b;
			a++;
			i = a;
			size = 0;
			//break;
		}
	}
	if (size == lenb)
	{
		cout << "pp " <<time<< endl;
	}
	if (size != lenb)
	{
		cout << "bcz" << endl;
	}

}

KMP算法

void getnext(char* b,int* next)
{
	int i = 0;
	int k = -1;
	next[i] = k;
	while (i < strlen(b))
	{
		if (k == -1 || b[i] == b[k])
		{
			i++;
			k++;
			next[i] = k;
		}
		else
		{
			k = next[k];
		}
	}
}


void KMPpp(char* a, char* b)
{
	char* i = a;
	char* j = b;
	int lena = strlen(a);
	int lenb = strlen(b);
	int size = 0;
	char first = *a;
	//int next[6] = {-1,0,0,1,0}; //abada
	int next[255];
	getnext(b,next);
	int time = 0;
	
	while (size != lenb)
	{
		if (next[size]==-1 || *i == *j)
		{
			i++;
			j++;
			size++;
		}
		else
		{
			int x = next[size];
			j = b + x;
			size = x;
		}
		if (size == lenb)
		{
			cout << "pp " <<time<< endl;
			break;
		}
		time++;
		if ( strlen(i) < strlen(j) )
		{
			cout << "bcz" << endl;
			break;
		}
	}
}

获取子串next数组的代码有点难以理解,我是通过下面这两个链接才搞明白的

​​​​​​KMP模式匹配(中)如何理解反人类next数组代码!_哔哩哔哩_bilibili

​​​​​KMP模式匹配算法中next和nextval数组的快速求解_czw8528的专栏-CSDN博客_next和nextval

KMP算法优化

getnextval

void getnextval(char* b, int* nextval)
{
	int i = 0;
	int k = -1;
	nextval[i] = k;
	while (i < strlen(b))
	{
		if (k == -1 || b[i] == b[k])
		{
			i++;
			k++;
			if (b[k] != b[i])
			{
				nextval[i] = k;
			}
			else
			{
				nextval[i] = nextval[k];
			}
		}
		else
		{
			k = nextval[k];
		}
	}
}

应用: 字符过滤系统

void initdl(dl5& d)
{
	d.end = new char[max_sized];
	d.top = d.end;
	d.size = max_sized;
}

void insertdl(dl5& d,char val)
{
	if (d.top - d.end == d.size)
	{
		cout << "full" << endl;
		exit;
	}
	*d.top = val;
	d.top++;
}

char pushdl(dl5& d)
{
	char e = *d.end;
	d.end++;
	return e;
}

void getnextval1(char* g, int* nextval)
{
	int k = -1;
	int i = 0;
	nextval[i] = k;
	while (i < strlen(g))
	{
		if (k == -1 || g[i] == g[k])
		{
			i++;
			k++;
			if (g[i] != g[k])
			{
				nextval[i] = k;
			}
			else
			{
				nextval[i] = nextval[k];
			}
		}
		else
		{
			k = nextval[k];
		}
	}
}

void gl(char* a,char* g)
{
	int i = 0, j = 0;
	int lena = strlen(a);
	int leng = strlen(g);
	int nextval[20];
	getnextval1(g, nextval);
	int x[20];
	int y = 0;

	while (i < lena)
	{
		if (j == -1 || a[i] == g[j])
		{
			i++;
			j++;
		}
		else
		{
			j = nextval[j];
		}
		if (j == leng)
		{
			x[y] = i - leng;
			y++;
		}
	}

	for (int i = 0; i < y; i++)
	{
		cout << x[i] << " ";
	}
	cout << "输入代替的字母:";
	char str1[20];
	cin >> str1;
	dl5 d;
	initdl(d);
	for (int i = 0; i < y; i++)
	{
		int t = x[i] + (strlen(str1)- leng) * i ;
		for (int j = t + 1; j < strlen(a); j++)
		{
			insertdl(d, a[j]);
		}
		for (int k = 0; k < strlen(str1); k++)
		{
			a[t + k] = str1[k];
		}
		int lend = d.top - d.end;
		for (int p = 0; p < lend; p++)
		{
			char x2 = pushdl(d);
			a[t + strlen(str1) + p] = x2;
		}
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值