0%

C和数据结构——串的两种实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
/*S是串的名字,串值,串中字符,串的长度,空串,注意空串和空白串的区别。
子串:连续的!位置由第一个字符第一次出现的位置确定
主串:任意的连续的包涵子串的串
串变量和串常量
1,字符串:
串的初始化:错误形式: char name【10】;name = “mwdiade”是非法的。因为这里的name是const型,无法修改
gets和puts函数(getchar和putchar)
strlen()函数:计算长度的,不包括最后的\0 string lenth
strcat(a,b)函数:拼接字符串a,b string catation
strcmp(a,b)函数:字符串比较函数 string compare 返回字符的ansic码的差值
*/

//--------------------------------------------------------------------------------------------------
//定长顺序存储表示(数组)
#define MAXSTRLEN 200 //自定义长度
typedef struct
{
char SString[MAXSTRLEN]; //存储字符数组
int length; //串中实际的字符个数
} SqString; //数据结构

//--------------------------------------------------------------------------------------------
//堆分配存储实现(malloc)
typedef struct
{
char *ch; //串的存储数组,只能是指针类型,不然没法修改
int maxSize; //串数组的最大长度,可以被修改,取决于用户的初始化
int length; //串的当前长度,同上
} HString;

//堆存储的初始化
void InitString(HString &S)
{
S.ch = (char *)malloc(MAXSTRLEN * sizeof(char)); //申请空间
if (S.ch == NULL) //判断申请是否成功
exit(1);
S.ch[0] = '\0'; //置空,注意,这里置空后后续是可以修改的,因为是指针类型;
S.maxSize = MAXSTRLEN; //修改参量
S.length = 0; //修改参量
}

//堆存储的提取子串
HString SubString(HString &S, int pos, int len)
{
HString tmp;
tmp.ch = (char *)malloc(MAXSTRLEN * sizeof(char));
tmp.maxSize = MAXSTRLEN;
if (pos < 0 || len < 0 || pos + len - 1 >= S.maxSize) //如果输入的数据不合法,返回空串,注意这里的判断用法
{
tmp.length = 0; //修改参数
tmp.ch[0] = '\0';
}
else
{
if (pos + len - 1 >= S.length) //长度大于主串,那么只能得到部分len
len = S.length - pos; //此时传进的len的值有误,修改,使得长度到末尾
//此时已经保证了所有的数据都是合法的了,于是可以循环遍历复制了
for (int i = 0, j = pos; i < len; i++, j++)
tmp.ch[i] = S.ch[j]; //复制
tmp.length = len; //修改参数
tmp.ch[len] = '\0'; //加上串最后一位的\0
}
return tmp; //返回子串
}

//堆串的链接算法
void concation(HString &S, HString &T)
{
//函数将串t复制到串S之后,通过S返回结果,串T不变
if (S.length + T.length <= S.maxSize) //如果不溢出,就直接复制,然后修改参数
{
for (int i = 0; i < T.length; i++) //循环遍历复制
S.ch[S.length + 1] = T.ch[i];
S.length = S.length + T.length; //修改参数
S.ch[S.length] = '\0'; //增加最后一个位置的\0
}
else //如果存在溢出
{ //就好像我们在学习链表的存储一样,此时我们创建新的堆串,使得新的堆串和原先的
//堆串指向同一片区域,最后释放这片区域。同时,开辟新的区域,存储链接后的结果,
//最后返回新的区域的地址,当然,也可以修改使得返回值
char *tmp = S.ch; //创建新的堆栈,最后便于释放原先的空间
S.maxSize = S.length + T.length; //修改参数,用于确定新开辟的空间的大小和链接串
S.ch = (char *)malloc((S.maxSize + 1) * sizeof(char)); //开辟新的空间
strcpy(S.ch, tmp); //复制原先的串的值到tmp
strcat(S.ch, T.ch); //链接串
S.length = S.length + T.length; //修改结果中的参数
free(tmp); //释放旧的串
}
}

//--------------------------------------------------------------------------------------------------------------------------
//串的块链存储表示
/*单链表形式存储字符串
每个结点的数据域可以存储n(自定义固定大小的值)个字符,叫做块的大小
存储密度: (串值所占的存储位/实际分配的存储位) <1
*/
#define BlockSize 4 //自定义结点的数据域大小
typedef struct block
{
char ch[BlockSize]; //数据域
struct block *next; //指向下一个结点的指针

} Chunk; //结点的数据结构
typedef struct
{
Chunk *first, *last; //头指针和尾指针
int length; //串的当前长度
} LString;