题目:一个字符串中的任意一个子序列,若子序列中各字符值均相同,则称为字符平台。编写一算法,输入任意一字符串S。输出S中长度最大的所有字符平台的起始位置及所含字符。注意,最大字符平台有可能不止一个。
例如,字符串aabcbbbbdccccaaa的最大的字符平台是bbbb和cccc。
一个全是注释的代码:
#pragma once
#include <stdio.h>
#define MAXSIZE 20
#define OK 1
#define FALSE 0
typedef struct SeqStringing {
char ch[MAXSIZE]; /*用定长字符数组存储字符串*/
int len; /*字符串长度*/
}SeqString; /*定义定长顺序串类型*/
void InitString(SeqString* s); /*初始化顺序串,将顺序串长度置0,并将所有字符置为'\0'*/
void CreateString(SeqString* s); /*根据输入创建一个字符串,输入'$'或输入超过字符串最大长度时停止*/
//void PrintString(SeqString* s); /*打印字符串,目的是检查字符串输入函数是否正确*/
typedef char QueueElemType;
typedef struct TempNode {
QueueElemType ch; /*用于存储字符平台中的字符符号*/
int pos; /*存储字符平台在主串中的位置*/
struct TempNode* next; /*用于构建链表的next指针*/
}TempNode; /*定义链队列节点类型*/
typedef struct TempQueue {
TempNode* head; /*队头指针*/
TempNode* tail; /*队尾指针*/
}*TempQueue; /*定义链队列类型*/
int InitNode(TempNode** tn); /*初始化队列结点,分配空间并置其next指针为NULL*/
int InitQueue(TempQueue* tq); /*初始化队列,创建一个头结点,使队头指针和队尾指针指向它*/
void EnterQueue(TempQueue tq, QueueElemType val, int pos); /*入队函数,将字符符号为val、位置为pos的字符平台加入临时队列tq*/
//int DeleteQueue(TempQueue tq, QueueElemType* x, int* y); /*一个没用到的出队函数,也没测试它的正确性*/
int ClearQueue_1(TempQueue tq); /*清除队列,使头尾指针指向头结点,并释放其他结点占用的内存空间*/
void PrintQueue(TempQueue tq, int max_len); /*打印存储着最大字符平台长度为max_len的队列tq*/
TempQueue GetContinuousRepeatCharacters(SeqString* str, int* max_len); /*找到字符串str中长度为*max_len的最大字符平台返回其地址*/
void InitString(SeqString* s) /*初始化顺序串,将顺序串长度置0,并将所有字符置为'\0'*/
{
int i;
for (i = 0; i < MAXSIZE; ++i)
{
s->ch[i] = '\0';
}
s->len = 0;
}
void CreateString(SeqString* s) /*根据输入创建一个字符串,输入'$'或输入超过字符串最大长度时停止*/
{
char tch; /*用来临时存放输入字符符号的字符变量*/
int flag = 1;
int i = 0;
rewind(stdin);
while (flag)
{
tch = getchar();
if (tch != '$' && i < MAXSIZE) /* 输入'$'或输入超过字符串最大长度时停止*/
{
s->ch[i++] = tch;
}
else
{
flag = 0;
s->len = i; /*输入结束时将字符串长度更改为输入字符串的数量*/
}
}
}
//void PrintString(SeqString* s) /*打印字符串,目的是检查字符串输入函数是否正确*/
//{
// int i = 0;
// while (i < s->len)
// {
// printf("%c", s->ch[i++]);
// }
// printf("\n\n");
//}
int InitNode(TempNode** tn) /*初始化队列结点,分配空间并置其next指针为NULL*/
{
*tn = (TempNode*)malloc(sizeof(TempNode));
if ((*tn) == NULL)
{
return FALSE;
}
(*tn)->next = NULL;
return OK;
}
int InitQueue(TempQueue* tq) /*初始化队列,创建一个头结点,使队头指针和队尾指针指向它*/
{
TempNode* tn;
InitNode(&tn); /*初始化头结点*/
*tq = (TempQueue)malloc(sizeof(TempQueue));
if ((*tq) == NULL)
{
return FALSE;
}
(*tq)->head = tn;
(*tq)->tail = tn; /*使队头指针和队尾指针指向头结点*/
return OK;
}
void EnterQueue(TempQueue tq, QueueElemType val, int pos) /*入队函数,将字符符号为val、位置为pos的字符平台加入临时队列tq*/
{
TempNode* tn;
InitNode(&tn); /*初始化一个新结点*/
tn->ch = val;
tn->pos = pos; /*赋值*/
tq->tail->next = tn;
tq->tail = tn; /*修改队尾指针*/
}
//int DeleteQueue(TempQueue tq, QueueElemType* x, int* y) /*一个没用到的出队函数,也没测试它的正确性*/
//{
// TempNode* tn;
// tn = tq->head->next;
// *x = tn->ch;
// *y = tn->pos;
// if (tn->next == NULL)
// {
// tq->tail = tq->head;
// }
// tq->head->next = tn->next;
// free(tn);
//
//}
int ClearQueue_1(TempQueue tq) /*清除队列,使头尾指针指向头结点,并释放其他结点占用的内存空间*/
{
TempNode* tmp; /*用于暂时存储即将被释放的空间位置*/
TempNode* pos; /*遍历队列*/
if (tq->head->next == NULL)
{
return OK;
} /*少加了这个判断,导致链表原本为空时tmp指向空,此时“pos=tmp->next”语句出错*/
tmp = tq->head->next;
pos = tmp->next;
while (pos)
{
free(tmp);
tmp = pos;
pos = pos->next;
}
free(tmp); /*循环结束时pos为空,tmp指向最后一个结点,故还需要释放此时tmp所指空间*/
tq->head->next = NULL;
tq->tail = tq->head;
return OK;
} /*也可以使用出队函数来清空链表,实现如下*/
/*首先需要定义队列判空函数,定义如下*/
/*int IsEmpty(TempQueue tq)
{
if (tq->head == tq->tail)
{
return OK;
}
return FALSE;
}*/
/*使用出队函数来清空链表,定义如下*/
/*void ClearQueue_2(TempQueue tq)
{
int tmpa, tmpb;
while (!IsEmpty(tq))
{
DeleteQueue(tq, &tmpa, &tmpb);
}
}*/
void PrintQueue(TempQueue tq, int max_len) /*打印存储着最大字符平台长度为max_len的队列tq*/
{
TempNode* pos = tq->head->next;
while (pos)
{
printf("start position: %2d | ", pos->pos+1);
printf("element: %c\n",pos->ch);
pos = pos->next;
} /*打印字符平台的符号和在主串中的位置*/
printf("max character platform length: %d", max_len); /*打印字符平台的长度*/
printf("\n");
}
TempQueue GetContinuousRepeatCharacters(SeqString* str, int* max_len) /*找到字符串str中长度为*max_len的最大字符平台返回其地址*/
{
TempQueue pq; /*声明一个队列用于存储字符平台*/
//TempNode* pn; /*多声明了一个变量*/
int spos = 0, epos = 0; /*用于遍历字符串,spos为字符平台开始位置,epos为字符平台最后一个字符的下一位置*/
*max_len = 0; /*字符平台最大长度*/
InitQueue(&pq); /*初始化队列*/
while (spos <= str->len - 1) /*结束条件为遍历完最后一个字符平台,此时spos等于字符串长度减一*/
{
while (str->ch[spos] == str->ch[epos]) /*循环结束时字符串str的ch[spos]到ch[epos]之间即是一个字符平台*/
{
epos++;
}
if (*max_len < epos - spos) /*如果新字符平台长度大于之前字符平台的最大长度*/
{
*max_len = epos - spos; /*更新字符平台最大长度*/
ClearQueue_1(pq); /*清空原队列*/
EnterQueue(pq, str->ch[spos], spos); /*记录新的最大字符平台*/
}
else if (*max_len == epos - spos) /*如果新字符平台长度等于之前字符平台的最大长度*/
{
EnterQueue(pq, str->ch[spos], spos); /*在队列中添加一个新纪录*/
}
spos = epos;
epos++; /*修改变量遍历下一个字符平台*/
}
return pq; /*忘了添加返回值*/
}
void Test() /*完整实现题目功能的函数*/
{
/*int i = 0;*/ /*注释掉的语句为测试函数功能语句*/
int len; /*用于带出最大字符平台的长度*/
/*char ch;*/
SeqString* ss; /*声明字符串*/
TempQueue tq; /*声明队列,存放最大字符平台信息*/
ss = (SeqString*)malloc(sizeof(SeqString)); /*为顺序字符串分配空间*/
InitString(ss); /*初始化字符串*/
CreateString(ss); /*通过输入创建字符串*/
/*PrintString(ss);*/
tq = GetContinuousRepeatCharacters(ss, &len); /*用tq记录最大字符平台信息*/
/*InitQueue(&tq);
rewind(stdin);
while (i < 10)
{
ch = getchar();
EnterQueue(tq, ch, i);
i++;
}*/
PrintQueue(tq,len); /*打印最大字符平台信息*/
/*ClearQueue(tq);
PrintQueue(tq);*/
}
int main()
{
Test(); /*调用测试函数*/
return 0;
}