//严蔚敏《数据结构》
//串:串的块链存储表示
//特殊之处(重要):除了指针p遍历链串之外,每个数据结点还需要额外的Chunkcount来进行结点内部数据的遍历(便于操作)
//自学中,加油!!!
#include<iostream>
using namespace std;
const int ChunkSize=4;
typedef struct CNode
{
char ch[ChunkSize];
struct CNode* next;
}CNode;
typedef struct
{
CNode* head,* tail;
int length;
}LString;
bool Init_str(LString& s)//初始化链串
{
s.head=new CNode;
if(!s.head)
return false;
s.head->next=nullptr;
s.tail=s.head;
s.length=0;
return true;
}
bool Input_str(LString& s)//向链串中输入数据
{
char ch;
cout<<"输入数据 #停止\n";
int Chunkcount=4;//此处默认在头结点的数据数组的最后一个
CNode* p;
while(cin>>ch,ch!='#'){
if(Chunkcount==ChunkSize){
p=new CNode;
if(!p)
return false;
Chunkcount=0;
p->ch[Chunkcount++]=ch;
p->next=s.tail->next;
s.tail->next=p;
s.tail=p;
}
else{
s.tail->ch[Chunkcount++]=ch;
}
s.length++;
cout<<"该字符输入完成\n";
}
if(Chunkcount!=ChunkSize){//尾结点 剩余空间补'#'
while(Chunkcount!=ChunkSize)
s.tail->ch[Chunkcount++]='#';
}
if(!cin){
cin.clear();
while(cin.get()!='\n')
continue;
}
return true;
}
void Output_str(LString s)//遍历输出
{
CNode* p=s.head->next;
cout<<"输出:\n";
while(p){
for(int i=0;i!=ChunkSize;i++)
cout<<p->ch[i];
cout<<endl;
p=p->next;
}
cout<<"-----"<<endl;
}
bool Clear_Str(LString& s)//清空链串s
{
CNode* p=s.head->next,* pp;
while(p){
pp=p;
p=p->next;
free(pp);
}
s.head->next=nullptr;
s.tail=s.head;
s.length=0;
return true;
}
bool Assign_Str(LString& s,char* chars)//生成其值与chars相等的链串s(注意 chars的尾部应是'\0')
{
if(s.length)
Clear_Str(s);
int Chunkcount=4;
CNode* p;
for(int i=0;chars[i]!='\0';i++){
if(Chunkcount==ChunkSize){//if目前结点满了
p=new CNode;
if(!p)
return false;
Chunkcount=0;
p->ch[Chunkcount++]=chars[i];
p->next=s.tail->next;
s.tail->next=p;
s.tail=p;
}
else{
s.tail->ch[Chunkcount++]=chars[i];
}
s.length++;
}
if(Chunkcount!=ChunkSize){
while(Chunkcount!=ChunkSize)
s.tail->ch[Chunkcount++]='#';
}
return true;
}
int Length_Str(LString s)//返回链串的长度
{
return s.length;
}
int Compare_Str(LString s1,LString s2)//若s1>s2,返回值>0;若s1=s2,返回值=0;若s1<s2,返回值<0
{
CNode* p1=s1.head->next,* p2=s2.head->next;
int i=0;
while(p1&&p2){
if(p1->ch[i]!=p2->ch[i]){
if(p1->ch[i]=='#'||p2->ch[i]=='#')
break;
return p1->ch[i]-p2->ch[i];
}
i++;
if(i==4){
p1=p1->next;
p2=p2->next;
i=0;//bug1:未重置i值
}
}
return s1.length-s2.length;
}
bool Concat_Str(LString& T,LString s1,LString s2)//T=s1+s2 先将s1、s2存入一个数组
{
if(T.length)
Clear_Str(T);
char* ch=new char[s1.length+s2.length+2];
int i=0,Chunkcount=0;//i计数读取的长度 chunkcount计数char[]数组
CNode* p=s1.head->next;
while(i!=s1.length){
if(Chunkcount==4){
p=p->next;
Chunkcount=0;
}
ch[i++]=p->ch[Chunkcount++];
}
p=s2.head->next;//p指向s2的第一个数据
Chunkcount=0;//重置Chunkcount
while(i!=s1.length+s2.length){
if(Chunkcount==4){
p=p->next;
Chunkcount=0;
}
ch[i++]=p->ch[Chunkcount++];
}
ch[i]='\0';//(重要 为啥出现一定的乱码 原因就在此)
//bug:在使用char数组后,将末尾的数据置为'0',不然可能会出现乱码
Assign_Str(T,ch);
return true;
}
bool Sub_Str(LString& T,LString s,int pos,int len)//用T存储主串s从pos位置开始的len个数据的子串
{//1<=pos<=s.length 0<=len<=s.length-pos+1
if(pos<1||pos>s.length||len<0||len>s.length-pos+1)
return false;
if(T.length)
Clear_Str(T);
char* ch=new char[len];
int x,y;
x=(pos-1)/4;y=(pos-1)%4;
CNode* p=s.head->next;
while(x){
p=p->next;
x--;
}
int Chunkcount=y;
for(int i=0;i!=len;i++){
ch[i]=p->ch[Chunkcount++];
if(Chunkcount==4){
p=p->next;
Chunkcount=0;
}
}
Assign_Str(T,ch);
return true;
}
int main()
{
LString s1;
Init_str(s1);
Input_str(s1);
Output_str(s1);
cout<<"长度="<<s1.length<<endl;
Assign_Str(s1,"dong1");
Output_str(s1);
cout<<"长度="<<s1.length<<endl;
LString s2;
Init_str(s2);
Input_str(s2);
Output_str(s2);
cout<<"长度="<<s2.length<<endl;
cout<<"result="<<Compare_Str(s1,s2)<<endl;
cout<<"============\n";
Output_str(s1);
Output_str(s2);
LString T;
Init_str(T);
Concat_Str(T,s1,s2);
Output_str(T);
Output_str(s1);
Output_str(s2);
Sub_Str(T,s2,8,4);
Output_str(T);
return 0;
}
输入数据 #停止
dong#
该字符输入完成
该字符输入完成
该字符输入完成
该字符输入完成
输出:
dong
-----
长度=4
输出:
dong
1###
-----
长度=5
输入数据 #停止
dong1234567890999#
该字符输入完成
该字符输入完成
该字符输入完成
该字符输入完成
该字符输入完成
该字符输入完成
该字符输入完成
该字符输入完成
该字符输入完成
该字符输入完成
该字符输入完成
该字符输入完成
该字符输入完成
该字符输入完成
该字符输入完成
该字符输入完成
该字符输入完成
输出:
dong
1234
5678
9099
9###
-----
长度=17
result=-12
============
输出:
dong
1###
-----
输出:
dong
1234
5678
9099
9###
-----
输出:
dong
1don
g123
4567
8909
99##
-----
输出:
dong
1###
-----
输出:
dong
1234
5678
9099
9###
-----
输出:
4567
-----
Process returned 0 (0x0) execution time : 13.349 s
Press any key to continue.