1
0
mirror of https://github.com/Didnelpsun/CS408.git synced 2026-02-10 06:05:51 +08:00

更新串

This commit is contained in:
Didnelpsun
2021-09-20 23:22:17 +08:00
parent 55e55fbf4e
commit 7f7577e4ab
12 changed files with 462 additions and 19 deletions

5
.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1,5 @@
{
"files.associations": {
"xstring": "cpp"
}
}

View File

@@ -0,0 +1,237 @@
#include "head.h"
// 块链串结点
class LinkStringNode {
private:
// 数据
char *_data{};
// 指针
LinkStringNode *_next{};
public:
// 初始化数据
bool SetData();
bool SetData(int data_size);
// 设置数据
bool SetData(char *character);
bool SetData(int index, char character);
// 获取数据
char *GetData();
char GetData(int index);
// 设置指针
bool SetNext();
bool SetNext(LinkStringNode *next);
// 获取指针
LinkStringNode *GetNext();
// 初始化
LinkStringNode();
explicit LinkStringNode(int max_size);
LinkStringNode(int max_size, LinkStringNode *next);
LinkStringNode(int max_size, char *character, LinkStringNode *next);
LinkStringNode(int max_size, char *character);
};
bool LinkStringNode::SetData() {
this->_data = new char[1];
return true;
}
bool LinkStringNode::SetData(int data_size) {
this->_data = new char[data_size];
return true;
}
bool LinkStringNode::SetData(char *character) {
this->_data = character;
return true;
}
bool LinkStringNode::SetData(int index, char character) {
this->_data[index] = character;
return true;
}
char *LinkStringNode::GetData() {
return this->_data;
}
char LinkStringNode::GetData(int index) {
return this->_data[index];
}
bool LinkStringNode::SetNext() {
this->_next = nullptr;
return true;
}
bool LinkStringNode::SetNext(LinkStringNode *next) {
this->_next = next;
return true;
}
LinkStringNode *LinkStringNode::GetNext() {
return this->_next;
}
LinkStringNode::LinkStringNode() {
this->SetData();
this->SetNext();
}
LinkStringNode::LinkStringNode(int max_size) {
this->SetData(max_size);
this->SetNext();
}
LinkStringNode::LinkStringNode(int max_size, LinkStringNode *next) {
this->SetData(max_size);
this->SetNext(next);
}
LinkStringNode::LinkStringNode(int max_size, char *character, LinkStringNode *next) {
this->SetData(max_size);
for (int i = 0; i < max_size; i++) {
if (character[i] != '\0') {
this->SetData(i, character[i]);
}
}
this->SetNext(next);
}
LinkStringNode::LinkStringNode(int max_size, char *character) {
this->SetData(max_size);
for (int i = 0; i < max_size; i++) {
if (character[i] != '\0') {
this->SetData(i, character[i]);
}
}
this->SetNext();
}
class LinkString {
private:
// 头尾指针
LinkStringNode *_front{}, *_rear{};
// 块链长度
int _data_size{};
// 长度
int _length{};
public:
// 设置头指针
bool SetFront();
bool SetFront(LinkStringNode *front);
// 获取头指针
LinkStringNode *GetFront();
// 设置尾指针
bool SetRear();
bool SetRear(LinkStringNode *rear);
// 获取尾指针
LinkStringNode *GetRear();
// 设置总体块链单元长度
bool SetDataSize();
bool SetDataSize(int data_size);
// 获取数据长度
int GetDataSize() const;
// 数据长度自加
bool SetLength();
// 设置数据长度
bool SetLength(int length);
// 获取数据长度
int GetLength() const;
// 初始化
LinkString();
explicit LinkString(int data_size);
};
bool LinkString::SetFront() {
this->_front = nullptr;
return true;
}
bool LinkString::SetFront(LinkStringNode *front) {
this->_front = front;
return true;
}
LinkStringNode *LinkString::GetFront() {
return this->_front;
}
bool LinkString::SetRear() {
this->_rear = nullptr;
return true;
}
bool LinkString::SetRear(LinkStringNode *rear) {
this->_rear = rear;
return true;
}
LinkStringNode *LinkString::GetRear() {
return this->_rear;
}
bool LinkString::SetDataSize() {
this->_data_size = 1;
return true;
}
bool LinkString::SetDataSize(int data_size) {
this->_data_size = data_size;
return true;
}
int LinkString::GetDataSize() const {
return this->_data_size;
}
bool LinkString::SetLength() {
this->_length++;
return true;
}
bool LinkString::SetLength(int length) {
this->_length = length;
return true;
}
int LinkString::GetLength() const {
return this->_length;
}
LinkString::LinkString() {
this->SetFront();
this->SetRear();
this->SetLength(0);
this->SetDataSize(1);
}
LinkString::LinkString(int data_size) {
this->SetFront();
this->SetRear();
this->SetLength(0);
this->SetDataSize(data_size);
}

View File

@@ -0,0 +1,118 @@
#include "head.h"
// 顺序串
class SequenceString{
private:
// 数据
char* _data{};
// 长度
int _length{};
// 最大容量
int _max_size{};
public:
// 设置数据
bool SetData();
bool SetData(int max_size);
bool SetData(char *character);
bool SetData(int index, char character);
// 获取数据
char* GetData();
char GetData(int index);
// 长度自加
bool SetLength();
// 设置长度
bool SetLength(int length);
// 获取长度
int GetLength() const;
// 设置最大容量
bool SetMaxSize();
bool SetMaxSize(int max_size);
// 获取最大容量
int GetMaxSize() const;
// 构造函数
SequenceString();
explicit SequenceString(int max_size);
};
bool SequenceString::SetData() {
this->_data = new char[MAXSIZE];
return true;
}
bool SequenceString::SetData(int max_size) {
this->_data = new char[max_size];
return true;
}
bool SequenceString::SetData(char * character) {
this->_data = character;
return true;
}
bool SequenceString::SetData(int index, char character) {
this->_data[index] = character;
return true;
}
char *SequenceString::GetData() {
return this->_data;
}
char SequenceString::GetData(int index) {
return this->_data[index];
}
bool SequenceString::SetLength() {
this->_length++;
return true;
}
bool SequenceString::SetLength(int length) {
this->_length = length;
return true;
}
int SequenceString::GetLength() const {
return this->_length;
}
bool SequenceString::SetMaxSize() {
this->_max_size = MAXSIZE;
return true;
}
bool SequenceString::SetMaxSize(int max_size) {
this->_max_size = max_size;
return true;
}
int SequenceString::GetMaxSize() const {
return this->_max_size;
}
SequenceString::SequenceString() {
this->SetData();
this->SetMaxSize();
this->SetLength(0);
}
SequenceString::SequenceString(int max_size) {
this->SetData(max_size);
this->SetMaxSize();
this->SetLength(0);
}

View File

@@ -9,6 +9,8 @@
#include "../head/link_stack.h"
#include "../head/sequence_queue.h"
#include "../head/link_queue.h"
#include "../head/sequence_string.h"
#include "../head/link_string.h"
bool SequenceListTest() {
DynamicSequenceList list;

View File

@@ -2,5 +2,9 @@
#define MAXSIZE 5
// 定义默认值
#define DEFAULTELEM '\0'
// 定义默认串值
#define DEFAULTCHAR '\0'
// 定义串块链数据长度
#define DATASIZE 4
// 定义默认数据类型
typedef char element_type;

View File

@@ -7,6 +7,12 @@ typedef struct LinkListNode {
} LinkListNode, *LinkList;
// 初始化
bool InitLinkList(LinkList &list) {
list->data = DEFAULTELEM;
list->next = nullptr;
return true;
}
LinkList InitLinkList() {
auto list = (LinkList) malloc(sizeof(LinkList));
list->data = DEFAULTELEM;
@@ -14,12 +20,6 @@ LinkList InitLinkList() {
return list;
}
bool InitLinkList(LinkList &list) {
list->data = DEFAULTELEM;
list->next = nullptr;
return true;
}
// 判空
bool EmptyLinkList(LinkList list) {
return list->next == nullptr && list->data == DEFAULTELEM;

View File

@@ -4,8 +4,8 @@ typedef struct LinkStackNode{
// 数据
element_type data;
// 指针
struct LinkStackNode *next;
} *LinkStack;
LinkStackNode *next;
} LinkStackNode, *LinkStack;
// 初始化
LinkStack InitLinkStack(){

View File

@@ -0,0 +1,25 @@
#include "head.h"
// 块链串结点
typedef struct LinkStringNode {
// 数据
char *data;
// 指针
LinkStringNode *next;
} LinkStringNode, *LinkString;
bool InitLinkString(LinkString &string) {
string->data = (char *) malloc(sizeof(char) * DATASIZE);
string->next = nullptr;
return true;
}
LinkString InitLinkString() {
auto* string = (LinkString) malloc(sizeof(LinkString));
string->data = (char *) malloc(sizeof(char) * DATASIZE);
string->next = nullptr;
return (LinkString &)string;
}

View File

@@ -0,0 +1,41 @@
#include "head.h"
// 顺序串
typedef struct {
// 数据
char *data;
// 长度
unsigned int length;
// 最大容量
unsigned int max_size;
} SequenceString;
bool InitSequenceString(SequenceString &string) {
string.data = (char *) malloc(sizeof(char) * MAXSIZE);
string.max_size = MAXSIZE;
string.length = 0;
return true;
}
bool InitSequenceString(SequenceString &string, int max_size) {
string.data = (char *) malloc(sizeof(char) * max_size);
string.max_size = max_size;
string.length = 0;
return true;
}
SequenceString InitSequenceString() {
auto *string = (SequenceString *) malloc(sizeof(SequenceString));
string->data = (char *) malloc(sizeof(char) * MAXSIZE);
string->max_size = MAXSIZE;
string->length = 0;
return (SequenceString &) string;
}
SequenceString InitSequenceString(int max_size) {
auto *string = (SequenceString *) malloc(sizeof(SequenceString));
string->data = (char *) malloc(sizeof(char) * max_size);
string->max_size = max_size;
string->length = 0;
return (SequenceString &) string;
}

View File

@@ -9,6 +9,8 @@
#include "../head/share_stack.h"
#include "../head/sequence_queue.h"
#include "../head/link_queue.h"
#include "../head/sequence_string.h"
#include "../head/link_string.h"
using namespace std;

View File

@@ -10,22 +10,25 @@
串的基本操作是对子串的操作。
## 顺序
## 串定义
### 顺序串
顺序串的结构定义方案
+ 使用单独的变量length保存串长。
+ 使用data[0]记录串长使得字符位序与数组下标一致但是由于char类型一个为一字节大小所以能表示的数字是0到255太大的串无法表示。
+ 没有表示串长的变量,使用\0表示串结尾对应ASCII码的0号字符。
+ data[0]空余使用单独的变量length保存串长这个比较常用。
+ 使用单独的变量$length$保存串长。
+ 使用$data[0]$记录串长;使得字符位序与数组下标一致;但是由于$char$类型一个为一字节大小,所以能表示的数字是$0$到$255$,太大的串无法表示,大于的部分会被截断
+ 没有表示串长的变量,使用$\backslash0$表示串结尾,对应$ASCII$码的$0$号字符。
+ $data[0]$空余,使用单独的变量$length$保存串长,这个比较常用。
+ 可以定长分配也可以用堆分配。
## 链串
### 链串
如一般的链式存储结构定义一样,定义一个数据与指向下一位的指针。
但是如果你只在每个结点定义了一个字节的数据,但是又包含了四个字节的指针,那么存储利用率会很低。
如果是顺序表数据类型是整数类型,那么这种利用率低的情况确实无可奈何,但是对于串而言,因为一个字节存储一个字符,所以能一个字节存一个字符类型数据,所以为了提升数据存储利用率,可以每个结点存等多个字符。
如果是顺序表数据类型是整数类型,那么这种利用率低的情况确实无可奈何,但是对于串而言,因为一个字节存储一个字符,所以能一个字节存一个字符类型数据,所以为了提升数据存储利用率,可以每个结点存等多个字符。这个就是块链串。
## 模式匹配
@@ -33,15 +36,15 @@
### 朴素模式匹配算法
从主串T、模式串P子串的第一个位置开始比较i=0,j=0若相等 ij各自+1然后比较下一个字符。若不等主串指针回溯到上一轮比较位置的下一个位置子串回溯到0,再进行下一次比较。令子串长度为m,主串长度为n
从主串$T$、模式串$P$(子串)的第一个位置开始比较($i=0,j=0$),若相等,则$i$$j$各自$+1$,然后比较下一个字符。若不等,主串指针回溯到上一轮比较位置的下一个位置,子串回溯到$0$,再进行下一次比较。令子串长度为$m$,主串长度为$n$
+ 匹配成功的最好时间复杂度:$O(m)$:刚好第一个就匹配上了,总对比次数为子串长度。
+ 匹配失败的最好时间复杂度:$O(n-m+1)=O(n-m)=O(n)$:匹配成功之前,每一个与第一个字符都匹配失败。
+ 匹配失败的最坏时间复杂度:$O(nm-m^2+m)= O(nm)$:子串除了最后一个对不上,其余的都能对上,则每次遍历完一边后,又要走回头路;直到匹配成功/失败一共需要比较$m\times(n-m+1)$次。m:每次需要移动m次i需要移动$n-m+1$次。
+ 匹配失败的最坏时间复杂度:$O(nm-m^2+m)= O(nm)$:子串除了最后一个对不上,其余的都能对上,则每次遍历完一边后,又要走回头路;直到匹配成功/失败一共需要比较$m\times(n-m+1)$次。$m$:每次需要移动$m$次,$i$需要移动$n-m+1$次。
### KMP算法
KMP算法是对朴素模式匹配算法的优化。
$KMP$算法是对朴素模式匹配算法的优化。
朴素模式匹配算法的缺点就是当某些子串与模式串能部分匹配时主串的扫描指针i经常回溯从而导致时间开销。

View File

@@ -12,7 +12,7 @@ $C.88$
$D.89$
解:$B$。根据公式$k=2i+j-3$。但是这种公式很难记忆,所以直接找规律。
解:$B$。根据公式$k=2i+j-3$。但是这种公式很难记忆,所以直接找规律。观察三对角矩阵不难发现,第一行有两个元素,剩下的在元素$m_{30,30}$所在行之前的$28$行中,每行都有$3$个元素,而$m_{30,30}$之前仅有一个元素$m_{30,29}$,不难发现元素$m_{30,30}$在数组$N$中的下标是$2+28\times3+2-1=87$。
**例题** 若将$n$阶上三角矩阵$A$按列优先级压缩存放在一维数组$B[1\cdots n(n+1)/2+1]$中,则存放到$B[k]$中的非零元素$a_{i,j}$1\leqslant i,j\leqslant n$)的下标$i$、$j$与$k$的对应关系是()。
@@ -24,6 +24,8 @@ $C.j(j-1)/2+i$
$D.j(j-1)/2+i-1$
解:$C$。按列优先存储,故元素$a$,前面有$j-1$列,共有$1+2+3+\cdots+j-1=j(j-1)/2$个元素,元素$a_{i,j}$在第$j$列上是第$i$个元素,数组$B$的下标是从$1$开始,因此$k=j(j-1)/2+i$。
**例题** 若将$n$阶下三角矩阵$A$按列优先顺序压缩存放在一维数组$B[1\cdots n(n+1)/2+1]$中,则存放到$B[k]$中的非零元素$a_{i,j}$$1\leqslant i,j\leqslant n$)的下标$i,j$与$k$的对应关系是()。
$A.(j-1)(2n-j+1)/2+i-j$
@@ -34,6 +36,8 @@ $C.(j-1)(2n-j+2)/2+i-j$
$D.(j-1)(2n-j+1)/2+i-j-1$
解:$B$。按列优先存储,故元素$a_{i,j}$之前有$j-1$列,共有$n+(n-1)+\cdots+(n-j+2)=(j-1)(2n-j+2)/2$个元素,元素$a_{i,j}$是第$j$列上第$i-j+1$个元素,数组$B$下标从$1$开始,$k=(j-1)(2n-j+2)/2+i-j+1$。
**例题** 设有一个$12\times12$的对称矩阵$M$,将其上三角部分的元素$m_{i,j}$$1\leqslant i\leqslant j\leqslant12$)按行优先存入$C$语言的一维数组$N$中,元素$m_{7,2}$在$N$中的下标是()。
$A.50$
@@ -43,3 +47,5 @@ $B.51$
$C.55$
$D.66$
解:$A$。在$C$语言中,数组$N$的下标从$0$开始。第一个元素$m_{1,1}$对应存入$n_0$,矩阵$M$的第一行有$12$个元素,第二行有$11$个,第三行有$10$个,第四行有$9$个,第五行有$8$个,所以$m_{6,6}$。是第$12+11+10+9+8+1=51$个元素,下标应为$50$。