携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第14天,点击查看活动详情 >>
串
在数据结构中有串这种类型的存储结构,本次学习的串就是字符串,串也是一种线性结构,在字符串与字符之间也是一对一的关系。 字串主串关系:主串abc则ab是主串的字串
- 出题:当有关系的字串与字符串通常会让我们使用算法找到字串在主串的位置,这里说的是第一次出现的位置。
串的定长顺序存储
之前学习顺序存储结构可知,数组可以分为静态数组与动态数组。我们也可以将串的长度理解为固定的长度的字符串。
例如
char str[4] = "abc";长度是字符串长度+1.因为最后一位需要存储字符串结束标志‘\0’
串的堆分配存储
堆分配存储实际靠的是动态数组存储字符串。在C语言中使用malloc来开辟空间的内存地址。
char * a = (char*)malloc(5*sizeof(char));
当需要更多内存时,使用realloc来进行新增开辟内存的空间
a = (char*)realloc(a, 10*sizeof(char));
串的块链存储结构
我们可以使用链表的思想进行链式存储字符串。 我们可以给链表各个节点存储四个字符串。
例如我们可以如下方式实现一个块链的存储格式
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define linkNum 3//全局设置链表中节点存储数据的个数
typedef struct Link {
char a[linkNum]; //数据域可存放 linkNum 个数据
struct Link* next; //代表指针域,指向直接后继元素
}link; // nk为节点名,每个节点都是一个 link 结构体
link* initLink(link* head, char* str);
void displayLink(link* head);
int main()
{
link* head = NULL;
head = initLink(head, "data.biancheng.net");
displayLink(head);
return 0;
}
//初始化链表,其中head为头指针,str为存储的字符串
link* initLink(link* head, char* str) {
int length = strlen(str);
//根据字符串的长度,计算出链表中使用节点的个数
int num = length / linkNum;
if (length % linkNum) {
num++;
}
//创建并初始化首元节点
head = (link*)malloc(sizeof(link));
head->next = NULL;
link* temp = head;
//初始化链表
for (int i = 0; i < num; i++)
{
int j = 0;
for (; j < linkNum; j++)
{
if (i * linkNum + j < length) {
temp->a[j] = str[i * linkNum + j];
}
else
temp->a[j] = '#';
}
if (i * linkNum + j < length)
{
link* newlink = (link*)malloc(sizeof(link));
newlink->next = NULL;
temp->next = newlink;
temp = newlink;
}
}
return head;
}
//输出链表
void displayLink(link* head) {
link* temp = head;
while (temp) {
for (int i = 0; i < linkNum; i++) {
printf("%c", temp->a[i]);
}
temp = temp->next;
}
}
拓展
之前面试遇到一个问题,给了我一个字符串叫我求字串多少个 这里粘贴下字串的计算公式 n(n+1)/2+1-重复的字符数。\
- 例:串中字符出现重复:字符串www.qq.com所有非空子串(两个子串如果内容相同则只算一个)个数是()
答案:50 备注:存在相同字符,所以计算方法为总个数减去重复个数,即n(n+1)/2+1-重复个数 解析:包含重复子串共:n(n+1)/2+1=10(10+1)/2+1=55,减去重复:2个w,1个ww,1个q,1个.,所以共55-5=50个
- 如果题目中问非空字串那么不需要加最后的1
- 若题目问非空真子串还需要再减一