💡 <03 栈和队列>习题代码

This commit is contained in:
康建伟
2019-11-04 23:04:29 +08:00
parent 11b529b069
commit 053ceec710
222 changed files with 15289 additions and 1 deletions

View File

@@ -0,0 +1,162 @@
#include <stdio.h>
#include "Status.h" //**▲01 绪论**//
/* 宏定义 */
#define N 100 //栈的容量
/* 双向栈元素类型定义 */
typedef int SElemType;
/* 双向栈中包含的两个栈的栈名 */
typedef enum {
Left, Right
} StackName;
/* 双向栈结构 */
typedef struct {
SElemType stack[N]; // 用一个容量足够大的数组做栈
int top[2]; // 存放栈顶指针
} TWS;
// 初始化栈
Status Inistack_3_15(TWS* tws);
// 入栈name指示向哪个栈中添加元素
Status Push_3_15(TWS* tws, StackName name, SElemType x);
// 出栈name指示从哪个栈中移除元素
Status Pop_3_15(TWS* tws, StackName name, SElemType* x);
// 输出栈中元素name指示输出哪个栈中的元素
void OutputStack(TWS tws, StackName name);
int main(int argc, char* argv[]) {
TWS S;
int i, x;
printf("████████ 初始化栈...\n");
Inistack_3_15(&S);
printf("████████ 向两个栈中压入元素...\n");
for(i = 1; i <= 5; i++) {
Push_3_15(&S, Left, i);
Push_3_15(&S, Right, 2 * i);
}
printf("█ 左栈中的元素(从栈底到栈顶):");
OutputStack(S, Left);
printf("█ 右栈中的元素(从栈底到栈顶):");
OutputStack(S, Right);
printf("████████ 分别弹出两个栈的栈顶元素...\n");
Pop_3_15(&S, Left, &x);
printf("█ 弹出左栈的栈顶元素为:%d\n", x);
printf("█ 左栈中的元素(从栈底到栈顶):");
OutputStack(S, Left);
Pop_3_15(&S, Right, &x);
printf("█ 弹出右栈的栈顶元素为:%d\n", x);
printf("█ 右栈中的元素(从栈底到栈顶):");
OutputStack(S, Right);
return 0;
}
// 初始化栈
Status Inistack_3_15(TWS* tws) {
if(tws == NULL) {
return ERROR;
}
(*tws).top[Left] = -1; // 栈0的栈顶指针注意不是0
(*tws).top[Right] = N; // 栈1的栈顶指针注意不是N-1
return OK;
}
// 入栈name指示向哪个栈中添加元素
Status Push_3_15(TWS* tws, StackName name, SElemType x) {
if(tws == NULL) {
return ERROR;
}
// 注意栈满条件,数组全被填充完才算栈满,不浪费空间
if((*tws).top[Left] + 1 == (*tws).top[Right]) {
return ERROR;
}
// 先移动栈顶游标,再存入元素
switch(name) {
case Left:
(*tws).top[name]++; // 左边栈的游标向右移动
break;
case Right:
(*tws).top[name]--; // 右边栈的游标向左移动
break;
default:
break;
}
// 存入元素
(*tws).stack[(*tws).top[name]] = x;
return OK;
}
// 出栈name指示从哪个栈中移除元素
Status Pop_3_15(TWS* tws, StackName name, SElemType* x) {
if(tws == NULL) {
return ERROR;
}
// 先移除元素,再移动游标
switch(name) {
case Left:
// 判断左边的栈是否为空
if((*tws).top[name] == -1) {
return ERROR;
}
*x = (*tws).stack[(*tws).top[name]];
(*tws).top[name]--;
break;
case Right:
// 判断右边的栈是否为空
if((*tws).top[name] == N) {
return ERROR;
}
*x = (*tws).stack[(*tws).top[name]];
(*tws).top[name]++;
break;
default:
break;
}
return OK;
}
// 输出栈中元素name指示输出哪个栈中的元素
void OutputStack(TWS tws, StackName name) {
int i;
switch(name) {
case Left:
for(i = 0; i <= tws.top[name]; i++) {
printf("%d ", tws.stack[i]);
}
break;
case Right:
for(i = N - 1; i >= tws.top[name]; i--) {
printf("%d ", tws.stack[i]);
}
break;
default:
break;
}
printf("\n");
}

View File

@@ -0,0 +1,6 @@
# 包含公共库
include_directories(${CMAKE_SOURCE_DIR}/Status)
# 生成可执行文件,并链接公共库
add_executable(03.15 03.15.c)
target_link_libraries(03.15 Scanf_lib)

View File

@@ -0,0 +1,136 @@
#include <stdio.h>
#include "Status.h" //**▲01 绪论**//
#include "SqStack.h" //**▲03 栈和队列**//
/*
* 生成车厢调度序列,其中'I'代表入栈,'O'代表出栈
*
* 假设入口在右边,出口在左边,且车厢读取顺序【从左到右】
*
* En :等待调度的列车序列
* seq调度序列
*/
void Algo_3_16(char* En, char seq[]);
/*
* 使用约定好的调度序列seq将入口En处的车厢调度到出口Ex
*
* 该方法可看做是对调度序列的检验
*
* En :等待调度的列车序列
* seq调度序列
* Ex :调度完成后的序列
*/
Status Dispatch(char* En, char* seq, char Ex[]);
int main(int argc, char* argv[]) {
char* En = "HSHHSHHHSSHSSSHS"; // 等待调度的列车序列
char Ex[100] = {'\0'}; // 调度完成的列车序列
char seq[100] = {'\0'}; // 调度序列
printf("████ 入口处的序列:\n");
printf("█ En = %s\n", En);
Algo_3_16(En, seq);
printf("████ 生成的调度序列:\n");
printf("█ seq = %s\n", seq);
Dispatch(En, seq, Ex);
printf("████ 根据生成的调度序列,对入口处的车厢调度,调度完成后的车厢序列:\n");
printf("█ Ex = %s\n", Ex);
return 0;
}
/*
* 生成车厢调度序列,其中'I'代表入栈,'O'代表出栈
*
* 假设入口在右边,出口在左边,车厢读取顺序从左到右
*
* En :等待调度的列车序列
* seq调度序列
*/
void Algo_3_16(char* En, char seq[]) {
int i, j;
SqStack S;
SElemType e;
// 初始化一个中转栈
InitStack(&S);
// 遍历待调度序列
for(i = j = 0; En[i] != '\0'; i++) {
// 遇到硬席,则将其入栈
if(En[i] == 'H') {
Push(&S, En[i]);
seq[j++] = 'I';
}
// 遇到软席,则先入栈,并立即出栈,相当于用栈做中转
if(En[i] == 'S') {
Push(&S, En[i]);
Pop(&S, &e);
seq[j++] = 'I';
seq[j++] = 'O';
}
}
// 将中转栈中的硬席出栈
while(!StackEmpty(S)) {
Pop(&S, &e);
seq[j++] = 'O';
}
seq[j] = '\0';
DestroyStack(&S);
}
/*
* 使用约定好的调度序列seq将入口En处的车厢调度到出口Ex
*
* 该方法可看做是对调度序列的检验
*
* En :等待调度的列车序列
* seq调度序列
* Ex :调度完成后的序列
*/
Status Dispatch(char* En, char* seq, char Ex[]) {
int i, j, k;
SqStack S;
SElemType e;
// 初始化一个中转栈
InitStack(&S);
i = j = k = 0;
// 遍历调度序列
while(seq[k] != '\0') {
// 遇到入栈标记,则将车厢加入中转栈
if(seq[k] == 'I') {
Push(&S, En[i++]);
}
// 遇到出栈标记,则将车厢移除,并转移到出口处
if(seq[k] == 'O') {
Pop(&S, &e);
Ex[j++] = e;
}
k++;
}
// 如果调度序列为空,但是入口处存在未调度的车厢,或者中转栈里存在未处理的车厢,则表示发生错误
if(seq[k] == '\0' && (En[i] || StackEmpty(S))) {
return ERROR;
}
Ex[j] = '\0';
DestroyStack(&S);
return OK;
}

View File

@@ -0,0 +1,7 @@
# 包含公共库
include_directories(${CMAKE_SOURCE_DIR}/Status)
# 生成可执行文件
add_executable(03.16 SqStack.h SqStack.c 03.16.c)
# 链接公共库
target_link_libraries(03.16 Scanf_lib)

View File

@@ -0,0 +1,109 @@
/*=========================
* 栈的顺序存储结构(顺序栈)
==========================*/
#include "SqStack.h" //**▲03 栈和队列**//
/*
* 初始化
*
* 构造一个空栈。初始化成功则返回OK否则返回ERROR。
*/
Status InitStack(SqStack* S) {
if(S == NULL) {
return ERROR;
}
(*S).base = (SElemType*) malloc(STACK_INIT_SIZE * sizeof(SElemType));
if((*S).base == NULL) {
exit(OVERFLOW);
}
(*S).top = (*S).base;
(*S).stacksize = STACK_INIT_SIZE;
return OK;
}
/*
* 销毁(结构)
*
* 释放顺序栈所占内存。
*/
Status DestroyStack(SqStack* S) {
if(S == NULL) {
return ERROR;
}
free((*S).base);
(*S).base = NULL;
(*S).top = NULL;
(*S).stacksize = 0;
return OK;
}
/*
* 判空
*
* 判断顺序栈中是否包含有效数据。
*
* 返回值:
* TRUE : 顺序栈为空
* FALSE: 顺序栈不为空
*/
Status StackEmpty(SqStack S) {
if(S.top == S.base) {
return TRUE;
} else {
return FALSE;
}
}
/*
* 入栈
*
* 将元素e压入到栈顶。
*/
Status Push(SqStack* S, SElemType e) {
if(S == NULL || (*S).base == NULL) {
return ERROR;
}
// 栈满时,追加存储空间
if((*S).top - (*S).base >= (*S).stacksize) {
(*S).base = (SElemType*) realloc((*S).base, ((*S).stacksize + STACKINCREMENT) * sizeof(SElemType));
if((*S).base == NULL) {
exit(OVERFLOW); // 存储分配失败
}
(*S).top = (*S).base + (*S).stacksize;
(*S).stacksize += STACKINCREMENT;
}
// 进栈先赋值,栈顶指针再自增
*(S->top++) = e;
return OK;
}
/*
* 出栈
*
* 将栈顶元素弹出并用e接收。
*/
Status Pop(SqStack* S, SElemType* e) {
if(S == NULL || (*S).base == NULL) {
return ERROR;
}
if((*S).top == (*S).base) {
return ERROR;
}
// 出栈栈顶指针先递减,再赋值
*e = *(--(*S).top);
return OK;
}

View File

@@ -0,0 +1,66 @@
/*=========================
* 栈的顺序存储结构(顺序栈)
==========================*/
#ifndef SQSTACK_H
#define SQSTACK_H
#include <stdio.h>
#include <stdlib.h> // 提供malloc、realloc、free、exit原型
#include "Status.h" //**▲01 绪论**//
/* 宏定义 */
#define STACK_INIT_SIZE 100 // 顺序栈存储空间的初始分配量
#define STACKINCREMENT 10 // 顺序栈存储空间的分配增量
/* 顺序栈元素类型定义 */
typedef int SElemType;
// 顺序栈元素结构
typedef struct {
SElemType* base; // 栈底指针
SElemType* top; // 栈顶指针
int stacksize; // 当前已分配的存储空间,以元素为单位
} SqStack;
/*
* 初始化
*
* 构造一个空栈。初始化成功则返回OK否则返回ERROR。
*/
Status InitStack(SqStack* S);
/*
* 销毁(结构)
*
* 释放顺序栈所占内存。
*/
Status DestroyStack(SqStack* S);
/*
* 判空
*
* 判断顺序栈中是否包含有效数据。
*
* 返回值:
* TRUE : 顺序栈为空
* FALSE: 顺序栈不为空
*/
Status StackEmpty(SqStack S);
/*
* 入栈
*
* 将元素e压入到栈顶。
*/
Status Push(SqStack* S, SElemType e);
/*
* 出栈
*
* 将栈顶元素弹出并用e接收。
*/
Status Pop(SqStack* S, SElemType* e);
#endif

View File

@@ -0,0 +1,69 @@
#include <stdio.h>
#include "Status.h" //**▲01 绪论**//
#include "SqStack.h" //**▲03 栈和队列**//
/*
* 判定输入序列是否为"序列1&序列2"这种模式
* 其中序列2是序列1的逆置
*
* s待验证的序列以'@'符号结尾
*/
Status Algo_3_17(char* s);
int main(int argc, char* argv[]) {
char* s = "a+b-c&c-b+a@";
printf("判断序列 %s 是否合规...\n", s);
if(Algo_3_17(s)) {
printf("█ 序列满足题意!\n");
} else {
printf("█ 序列不满足题意!!\n");
}
return 0;
}
/*
* 判定输入序列是否为"序列1&序列2"这种模式
* 其中序列2是序列1的逆置
*
* s待验证的序列以'@'符号结尾
*/
Status Algo_3_17(char* s) {
SqStack S;
SElemType e;
int i;
InitStack(&S);
i = 0;
// 将'&'前的序列入栈
while(s[i] != '@' && s[i] != '&') {
Push(&S, s[i]);
i++;
}
// 如果遇到了'&'符号
if(s[i] != '@') {
i++; // 跳过&符号
// 将'&'后的序列出栈
while(!StackEmpty(S) && s[i] != '@') {
Pop(&S, &e);
if(s[i] != e) {
return ERROR;
}
i++;
}
}
// 如果栈为空,且序列恰好访问完,说明符合题意
if(StackEmpty(S) && s[i] == '@') {
return OK;
}
return ERROR;
}

View File

@@ -0,0 +1,7 @@
# 包含公共库
include_directories(${CMAKE_SOURCE_DIR}/Status)
# 生成可执行文件
add_executable(03.17 SqStack.h SqStack.c 03.17.c)
# 链接公共库
target_link_libraries(03.17 Scanf_lib)

View File

@@ -0,0 +1,90 @@
/*=========================
* 栈的顺序存储结构(顺序栈)
==========================*/
#include "SqStack.h" //**▲03 栈和队列**//
/*
* 初始化
*
* 构造一个空栈。初始化成功则返回OK否则返回ERROR。
*/
Status InitStack(SqStack* S) {
if(S == NULL) {
return ERROR;
}
(*S).base = (SElemType*) malloc(STACK_INIT_SIZE * sizeof(SElemType));
if((*S).base == NULL) {
exit(OVERFLOW);
}
(*S).top = (*S).base;
(*S).stacksize = STACK_INIT_SIZE;
return OK;
}
/*
* 判空
*
* 判断顺序栈中是否包含有效数据。
*
* 返回值:
* TRUE : 顺序栈为空
* FALSE: 顺序栈不为空
*/
Status StackEmpty(SqStack S) {
if(S.top == S.base) {
return TRUE;
} else {
return FALSE;
}
}
/*
* 入栈
*
* 将元素e压入到栈顶。
*/
Status Push(SqStack* S, SElemType e) {
if(S == NULL || (*S).base == NULL) {
return ERROR;
}
// 栈满时,追加存储空间
if((*S).top - (*S).base >= (*S).stacksize) {
(*S).base = (SElemType*) realloc((*S).base, ((*S).stacksize + STACKINCREMENT) * sizeof(SElemType));
if((*S).base == NULL) {
exit(OVERFLOW); // 存储分配失败
}
(*S).top = (*S).base + (*S).stacksize;
(*S).stacksize += STACKINCREMENT;
}
// 进栈先赋值,栈顶指针再自增
*(S->top++) = e;
return OK;
}
/*
* 出栈
*
* 将栈顶元素弹出并用e接收。
*/
Status Pop(SqStack* S, SElemType* e) {
if(S == NULL || (*S).base == NULL) {
return ERROR;
}
if((*S).top == (*S).base) {
return ERROR;
}
// 出栈栈顶指针先递减,再赋值
*e = *(--(*S).top);
return OK;
}

View File

@@ -0,0 +1,59 @@
/*=========================
* 栈的顺序存储结构(顺序栈)
==========================*/
#ifndef SQSTACK_H
#define SQSTACK_H
#include <stdio.h>
#include <stdlib.h> // 提供malloc、realloc、free、exit原型
#include "Status.h" //**▲01 绪论**//
/* 宏定义 */
#define STACK_INIT_SIZE 100 // 顺序栈存储空间的初始分配量
#define STACKINCREMENT 10 // 顺序栈存储空间的分配增量
/* 顺序栈元素类型定义 */
typedef int SElemType;
// 顺序栈元素结构
typedef struct {
SElemType* base; // 栈底指针
SElemType* top; // 栈顶指针
int stacksize; // 当前已分配的存储空间,以元素为单位
} SqStack;
/*
* 初始化
*
* 构造一个空栈。初始化成功则返回OK否则返回ERROR。
*/
Status InitStack(SqStack* S);
/*
* 判空
*
* 判断顺序栈中是否包含有效数据。
*
* 返回值:
* TRUE : 顺序栈为空
* FALSE: 顺序栈不为空
*/
Status StackEmpty(SqStack S);
/*
* 入栈
*
* 将元素e压入到栈顶。
*/
Status Push(SqStack* S, SElemType e);
/*
* 出栈
*
* 将栈顶元素弹出并用e接收。
*/
Status Pop(SqStack* S, SElemType* e);
#endif

View File

@@ -0,0 +1,72 @@
#include <stdio.h>
#include "Status.h" //**▲01 绪论**//
#include "SqStack.h" //**▲03 栈和队列**//
/*
* 判定表达式开闭括号是否配对出现
*
*【注】
* 只是判断括号是否配对出现,而不是判断括号类型、顺序是否正确
*/
Status Algo_3_18(char* s);
int main(int argc, char* argv[]) {
char* s = "(1+2)*3/{2/[(4-5)*3]-5*(8-7)}";
printf("判断表达式 %s 开闭括号数量是否匹配...\n", s);
if(Algo_3_18(s) == TRUE) {
printf("█ 表达式开闭括号数量匹配!\n");
} else {
printf("█ 表达式开闭括号数量不匹配!!\n");
}
return 0;
}
/*
* 判定表达式开闭括号是否配对出现
*
*【注】
* 只是判断括号是否配对出现,而不是判断括号类型、顺序是否正确
*/
Status Algo_3_18(char* s) {
SqStack S;
SElemType e;
int i;
InitStack(&S);
for(i = 0; s[i] != '\0'; i++) {
switch(s[i]) {
// 遇到左括号,则入栈
case '(':
case '[':
case '{':
Push(&S, s[i]);
break;
// 遇到右括号,则出栈
case ')':
case ']':
case '}':
if(StackEmpty(S)) {
return ERROR;
}
Pop(&S, &e);
break;
default:
break;
}
}
// 如果栈正好为空了,说明校验成功
if(StackEmpty(S)) {
return OK;
}
return ERROR;
}

View File

@@ -0,0 +1,7 @@
# 包含公共库
include_directories(${CMAKE_SOURCE_DIR}/Status)
# 生成可执行文件
add_executable(03.18 SqStack.h SqStack.c 03.18.c)
# 链接公共库
target_link_libraries(03.18 Scanf_lib)

View File

@@ -0,0 +1,90 @@
/*=========================
* 栈的顺序存储结构(顺序栈)
==========================*/
#include "SqStack.h" //**▲03 栈和队列**//
/*
* 初始化
*
* 构造一个空栈。初始化成功则返回OK否则返回ERROR。
*/
Status InitStack(SqStack* S) {
if(S == NULL) {
return ERROR;
}
(*S).base = (SElemType*) malloc(STACK_INIT_SIZE * sizeof(SElemType));
if((*S).base == NULL) {
exit(OVERFLOW);
}
(*S).top = (*S).base;
(*S).stacksize = STACK_INIT_SIZE;
return OK;
}
/*
* 判空
*
* 判断顺序栈中是否包含有效数据。
*
* 返回值:
* TRUE : 顺序栈为空
* FALSE: 顺序栈不为空
*/
Status StackEmpty(SqStack S) {
if(S.top == S.base) {
return TRUE;
} else {
return FALSE;
}
}
/*
* 入栈
*
* 将元素e压入到栈顶。
*/
Status Push(SqStack* S, SElemType e) {
if(S == NULL || (*S).base == NULL) {
return ERROR;
}
// 栈满时,追加存储空间
if((*S).top - (*S).base >= (*S).stacksize) {
(*S).base = (SElemType*) realloc((*S).base, ((*S).stacksize + STACKINCREMENT) * sizeof(SElemType));
if((*S).base == NULL) {
exit(OVERFLOW); // 存储分配失败
}
(*S).top = (*S).base + (*S).stacksize;
(*S).stacksize += STACKINCREMENT;
}
// 进栈先赋值,栈顶指针再自增
*(S->top++) = e;
return OK;
}
/*
* 出栈
*
* 将栈顶元素弹出并用e接收。
*/
Status Pop(SqStack* S, SElemType* e) {
if(S == NULL || (*S).base == NULL) {
return ERROR;
}
if((*S).top == (*S).base) {
return ERROR;
}
// 出栈栈顶指针先递减,再赋值
*e = *(--(*S).top);
return OK;
}

View File

@@ -0,0 +1,59 @@
/*=========================
* 栈的顺序存储结构(顺序栈)
==========================*/
#ifndef SQSTACK_H
#define SQSTACK_H
#include <stdio.h>
#include <stdlib.h> // 提供malloc、realloc、free、exit原型
#include "Status.h" //**▲01 绪论**//
/* 宏定义 */
#define STACK_INIT_SIZE 100 // 顺序栈存储空间的初始分配量
#define STACKINCREMENT 10 // 顺序栈存储空间的分配增量
/* 顺序栈元素类型定义 */
typedef int SElemType;
// 顺序栈元素结构
typedef struct {
SElemType* base; // 栈底指针
SElemType* top; // 栈顶指针
int stacksize; // 当前已分配的存储空间,以元素为单位
} SqStack;
/*
* 初始化
*
* 构造一个空栈。初始化成功则返回OK否则返回ERROR。
*/
Status InitStack(SqStack* S);
/*
* 判空
*
* 判断顺序栈中是否包含有效数据。
*
* 返回值:
* TRUE : 顺序栈为空
* FALSE: 顺序栈不为空
*/
Status StackEmpty(SqStack S);
/*
* 入栈
*
* 将元素e压入到栈顶。
*/
Status Push(SqStack* S, SElemType e);
/*
* 出栈
*
* 将栈顶元素弹出并用e接收。
*/
Status Pop(SqStack* S, SElemType* e);
#endif

View File

@@ -0,0 +1,98 @@
#include <stdio.h>
#include "Status.h" //**▲01 绪论**//
#include "SqStack.h" //**▲03 栈和队列**//
// 判定表达式开闭括号是否配对出现,且类型是否匹配
Status Algo_3_19(char* s);
// 判断括号a和括号b之间的类型是否匹配
Status Matching(char a, char b);
int main(int argc, char* argv[]) {
char* s = "(1+2)*3/{2/[(4-5)*3]-5*(8-7)}";
printf("判断表达式 %s 括号是否匹配...\n", s);
if(Algo_3_19(s)) {
printf("█ 表达式括号匹配!\n");
} else {
printf("█ 表达式括号不匹配!!\n");
}
return 0;
}
// 判定表达式开闭括号是否配对出现,且类型是否匹配
Status Algo_3_19(char* s) {
SqStack S;
SElemType e;
int i;
InitStack(&S);
for(i = 0; s[i] != '\0'; i++) {
switch(s[i]) {
// 遇到左括号,则入栈
case '(':
case '[':
case '{':
Push(&S, s[i]);
break;
// 遇到右括号,则出栈
case ')':
case ']':
case '}':
if(StackEmpty(S)) {
return ERROR;
}
Pop(&S, &e);
// 判断括号是否匹配
if(!Matching(e, s[i])) {
return ERROR;
}
break;
default:
break;
}
}
if(StackEmpty(S)) {
return OK;
}
return ERROR;
}
// 判断括号a和括号b之间的类型是否匹配
Status Matching(char a, char b) {
switch(a) {
case '(':
if(b != ')') {
return ERROR;
}
break;
case '[':
if(b != ']') {
return ERROR;
}
break;
case '{':
if(b != '}') {
return ERROR;
}
break;
default:
return ERROR;
}
return OK;
}

View File

@@ -0,0 +1,7 @@
# 包含公共库
include_directories(${CMAKE_SOURCE_DIR}/Status)
# 生成可执行文件
add_executable(03.19 SqStack.h SqStack.c 03.19.c)
# 链接公共库
target_link_libraries(03.19 Scanf_lib)

View File

@@ -0,0 +1,90 @@
/*=========================
* 栈的顺序存储结构(顺序栈)
==========================*/
#include "SqStack.h" //**▲03 栈和队列**//
/*
* 初始化
*
* 构造一个空栈。初始化成功则返回OK否则返回ERROR。
*/
Status InitStack(SqStack* S) {
if(S == NULL) {
return ERROR;
}
(*S).base = (SElemType*) malloc(STACK_INIT_SIZE * sizeof(SElemType));
if((*S).base == NULL) {
exit(OVERFLOW);
}
(*S).top = (*S).base;
(*S).stacksize = STACK_INIT_SIZE;
return OK;
}
/*
* 判空
*
* 判断顺序栈中是否包含有效数据。
*
* 返回值:
* TRUE : 顺序栈为空
* FALSE: 顺序栈不为空
*/
Status StackEmpty(SqStack S) {
if(S.top == S.base) {
return TRUE;
} else {
return FALSE;
}
}
/*
* 入栈
*
* 将元素e压入到栈顶。
*/
Status Push(SqStack* S, SElemType e) {
if(S == NULL || (*S).base == NULL) {
return ERROR;
}
// 栈满时,追加存储空间
if((*S).top - (*S).base >= (*S).stacksize) {
(*S).base = (SElemType*) realloc((*S).base, ((*S).stacksize + STACKINCREMENT) * sizeof(SElemType));
if((*S).base == NULL) {
exit(OVERFLOW); // 存储分配失败
}
(*S).top = (*S).base + (*S).stacksize;
(*S).stacksize += STACKINCREMENT;
}
// 进栈先赋值,栈顶指针再自增
*(S->top++) = e;
return OK;
}
/*
* 出栈
*
* 将栈顶元素弹出并用e接收。
*/
Status Pop(SqStack* S, SElemType* e) {
if(S == NULL || (*S).base == NULL) {
return ERROR;
}
if((*S).top == (*S).base) {
return ERROR;
}
// 出栈栈顶指针先递减,再赋值
*e = *(--(*S).top);
return OK;
}

View File

@@ -0,0 +1,59 @@
/*=========================
* 栈的顺序存储结构(顺序栈)
==========================*/
#ifndef SQSTACK_H
#define SQSTACK_H
#include <stdio.h>
#include <stdlib.h> // 提供malloc、realloc、free、exit原型
#include "Status.h" //**▲01 绪论**//
/* 宏定义 */
#define STACK_INIT_SIZE 100 // 顺序栈存储空间的初始分配量
#define STACKINCREMENT 10 // 顺序栈存储空间的分配增量
/* 顺序栈元素类型定义 */
typedef int SElemType;
// 顺序栈元素结构
typedef struct {
SElemType* base; // 栈底指针
SElemType* top; // 栈顶指针
int stacksize; // 当前已分配的存储空间,以元素为单位
} SqStack;
/*
* 初始化
*
* 构造一个空栈。初始化成功则返回OK否则返回ERROR。
*/
Status InitStack(SqStack* S);
/*
* 判空
*
* 判断顺序栈中是否包含有效数据。
*
* 返回值:
* TRUE : 顺序栈为空
* FALSE: 顺序栈不为空
*/
Status StackEmpty(SqStack S);
/*
* 入栈
*
* 将元素e压入到栈顶。
*/
Status Push(SqStack* S, SElemType e);
/*
* 出栈
*
* 将栈顶元素弹出并用e接收。
*/
Status Pop(SqStack* S, SElemType* e);
#endif

View File

@@ -0,0 +1,220 @@
#include <stdio.h>
#include "Status.h" //**▲01 绪论**//
/* 此算法类似于迷宫寻路算法 */
/* 宏定义 */
#define SleepTime 2
#define Row 10
#define Col 17
/* 访问方向 */
typedef enum {
East, South, West, North
} Direction;
/* 颜色枚举 */
typedef enum {
Color_1, Color_2, Color_3
} Color;
/* 栈的元素类型 */
typedef struct {
int x, y; // 像素点的横、纵坐标定义
int di; // 从此像素点走向下一像素点的"方向"
} SElemType;
// 迷宫染色函数:对指定的图像染色
void Algo_3_20(int g[][17], SElemType start);
// 初始化图像区域和染色起点
void InitGrap(int g[][17], SElemType* start);
// 在屏幕上显示当前图像
void PaintGrap(int g[][17]);
// 判断某个点是否需要染色
Status Pass(SElemType e, int g[][17]);
// 遇到可以染色的点即留下标记,即染上相应的颜色
void Mark(SElemType* e, int g[][17]);
// 获取下一个该染色的点的信息
Status NextPos(SElemType* e);
// 判断当前的点是否出界
Status IsCross(SElemType e);
int main(int argc, char** argv) {
int g[Row][Col]; // 存放图像区域点的颜色
SElemType start; // 染色的起点
InitGrap(g, &start);
PaintGrap(g);
Algo_3_20(g, start);
return 0;
}
// 对指定的图像染色
void Algo_3_20(int g[][Col], SElemType start) {
SElemType e;
SElemType stack[10000]; // 定义一个足够大的数组作为栈,存放染过色的点
int top = -1; // 栈顶指针
e = start;
do {
// 如果需要染色
if(Pass(e, g)) {
Mark(&e, g); // 将其染色,并标记其前进方向
PaintGrap(g);
stack[++top] = e; // 将访问过的像素点入栈
NextPos(&e); // 得出下一个像素点信息
} else {
if(top != -1) {
e = stack[top--];
// 栈中弹出的点已没多余方向可访问
while(e.di == North && top != -1) {
e = stack[top--];
}
if(e.di < North) {
e.di++;
stack[++top] = e;
NextPos(&e);
}
}
}
} while(top != -1); // 栈不为空
}
/* 初始化图像区域和染色起点 */
void InitGrap(int g[][Col], SElemType* start) {
int i, j;
// 储存颜色0和颜色1
int a[Row][Col]={{0,0,1,1,1,0,0,0,0,0,0,0,1,1,1,0,0},
{0,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,0},
{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
{0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0},
{0,0,0,1,1,1,1,1,1,1,1,1,1,1,0,0,0},
{0,0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0},
{0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0},
{0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0}};
for(i = 0; i < 10; i++) {
for(j = 0; j < 17; j++) {
g[i][j] = a[i][j];
}
}
(*start).x = 9; // 起点坐标
(*start).y = 8;
(*start).di = East; // East代表方向向右
}
/* 在屏幕上显示当前图像 */
void PaintGrap(int g[][Col]) {
int i, j;
Wait(SleepTime);
for(i = 0; i < Row; i++) {
for(j = 0; j < Col; j++) {
// 颜色0用"^"显示
if(g[i][j] == Color_1) {
printf(".");
}
// 颜色1显示为空白
if(g[i][j] == Color_2) {
printf(" ");
}
// 颜色2用"*"显示
if(g[i][j] == Color_3) {
printf("*");
}
if(j && !(j % (Col - 1))) {
printf("\n");
}
}
}
printf("\n");
}
/* 判断某个点是否需要染色 */
Status Pass(SElemType e, int g[][Col]) {
int x = e.x;
int y = e.y;
// 将颜色为1的点染成其他颜色
if(g[x][y] == 1) {
return TRUE;
} else {
return FALSE;
}
}
/* 遇到可以染色的点即留下标记,即染上相应的颜色 */
void Mark(SElemType* e, int g[][Col]) {
int x = (*e).x;
int y = (*e).y;
(*e).di = East; // 标记此像素点的前进方向
g[x][y] = 2; // 将此像素点颜色染为颜色2
}
/* 获取下一个该染色的点的信息 */
Status NextPos(SElemType* e) {
SElemType tmp;
tmp = *e;
switch(tmp.di) {
case East:
(tmp.y)++; // East代表向右
break;
case South:
(tmp.x)++; // South代表向下
break;
case West:
(tmp.y)--; // West代表向左
break;
case North:
(tmp.x)--; // North代表向上
break;
default:
return FALSE;
}
if(IsCross(tmp)) {
++(*e).di;
NextPos(e);
} else {
*e = tmp;
}
return TRUE;
}
/* 判断当前的点是否出界 */
Status IsCross(SElemType e) {
int x = e.x;
int y = e.y;
// 越界
if(x < 0 || y < 0 || x > Row - 1 || y > Col - 1) {
return OK;
} else {
return ERROR;
}
}

View File

@@ -0,0 +1,6 @@
# 包含公共库
include_directories(${CMAKE_SOURCE_DIR}/Status)
# 生成可执行文件,并链接公共库
add_executable(03.20 03.20.c)
target_link_libraries(03.20 Scanf_lib)

View File

@@ -0,0 +1,124 @@
#include <stdio.h>
#include <string.h> // 提供strlen原型
#include <ctype.h> // 提供isalpha原型
#include "SqStack.h" //**▲03 栈和队列**//
// 运算符表,即表达式中允许出现的符号
static const char OP[] = {'+', '-', '*', '/'};
/*
* 运算符优先级表与上面的OP表是呼应的。
* 这里只有四则运算符号的优先级
*/
static const char PrecedeTable[7][7] = {
{'>', '>', '<', '<'},
{'>', '>', '<', '<'},
{'>', '>', '>', '>'},
{'>', '>', '>', '>'}
};
/*
* 根据给定的中缀表达式,返回其对应的逆波兰表达式(后缀表达式)
* 如将"a+b*c-d/e"将转化为:"abc*+de/-"
*
*【注】
* 表达式的变量为单字母,操作符只有'+'、'-'、'*'、'/'四则运算
*/
char* Algo_3_21(char s[]);
/*
* 判断运算符栈中操作符o1与表达式中的操作符o2的优先级。
*
* 返回'>'、'<'、'='以指示o1和o2的优先级
*/
char Precede(char o1, char o2);
int main(int argc, char* argv[]) {
char* s = "a+b*c-d/e";
printf("中缀表达式为:");
printf("%s\n", s);
printf("后缀表达式为:");
printf("%s\n", Algo_3_21(s));
return 0;
}
/*
* 根据给定的中缀表达式,返回其对应的逆波兰表达式(后缀表达式)
* 如将"a+b*c-d/e"将转化为:"abc*+de/-"
*
*【注】
* 表达式的变量为单字母,操作符只有'+'、'-'、'*'、'/'四则运算
*/
char* Algo_3_21(char s[]) {
int i, j;
SqStack S; // 运算符栈,临时存储操作符
SElemType e; // SElemType被定义char类型char和int类型可直接比较
char* c;
// 逆波兰式序列
c = (char*) malloc((strlen(s) + 1) * sizeof(char));
InitStack(&S);
for(i = j = 0; s[i] != '\0'; i++) {
// 如果读到了字母,将其视为操作数,
if(isalpha(s[i])) {
c[j++] = s[i]; // 将字母直接存入逆波兰式中
// 如果读到的是运算符
} else {
while(!StackEmpty(S)) {
// 获取栈顶元素
GetTop(S, &e);
// 如果运算符栈中运算符优先级高
if(Precede(e, s[i]) == '>') {
Pop(&S, &e); // 将运算符栈中优先级高的操作符出栈
c[j++] = e; // 将出栈后的操作符添加到逆波兰式中
// 如果遇到运算符栈中操作符优先级低时,结束循环
} else {
break;
}
}
// 将表达式中读取到的操作符压入运算符栈
Push(&S, s[i]);
}
}
// 将运算符栈中所有操作符追加到逆波兰式中
while(!StackEmpty(S)) {
Pop(&S, &e);
c[j++] = e;
}
// 数组中转换后的逆波兰式以"\0"标记结束
c[j] = '\0';
return c;
}
/*
* 判断运算符栈中操作符o1与表达式中的操作符o2的优先级。
*
* 返回'>'、'<'、'='以指示o1和o2的优先级
*/
char Precede(char o1, char o2) {
int x, y;
// 获取指定的运算符在运算符表中的位置
char* p1 = strchr(OP, o1);
char* p2 = strchr(OP, o2);
// 计算出一个运算符优先级表坐标
x = p1 - OP;
y = p2 - OP;
return PrecedeTable[x][y];
}

View File

@@ -0,0 +1,7 @@
# 包含公共库
include_directories(${CMAKE_SOURCE_DIR}/Status)
# 生成可执行文件
add_executable(03.21 SqStack.h SqStack.c 03.21.c)
# 链接公共库
target_link_libraries(03.21 Scanf_lib)

View File

@@ -0,0 +1,106 @@
/*=========================
* 栈的顺序存储结构(顺序栈)
==========================*/
#include "SqStack.h" //**▲03 栈和队列**//
/*
* 初始化
*
* 构造一个空栈。初始化成功则返回OK否则返回ERROR。
*/
Status InitStack(SqStack* S) {
if(S == NULL) {
return ERROR;
}
(*S).base = (SElemType*) malloc(STACK_INIT_SIZE * sizeof(SElemType));
if((*S).base == NULL) {
exit(OVERFLOW);
}
(*S).top = (*S).base;
(*S).stacksize = STACK_INIT_SIZE;
return OK;
}
/*
* 判空
*
* 判断顺序栈中是否包含有效数据。
*
* 返回值:
* TRUE : 顺序栈为空
* FALSE: 顺序栈不为空
*/
Status StackEmpty(SqStack S) {
if(S.top == S.base) {
return TRUE;
} else {
return FALSE;
}
}
/*
* 取值
*
* 返回栈顶元素并用e接收。
*/
Status GetTop(SqStack S, SElemType* e) {
if(S.base == NULL || S.top == S.base) {
return 0;
}
// 不会改变栈中元素
*e = *(S.top - 1);
return OK;
}
/*
* 入栈
*
* 将元素e压入到栈顶。
*/
Status Push(SqStack* S, SElemType e) {
if(S == NULL || (*S).base == NULL) {
return ERROR;
}
// 栈满时,追加存储空间
if((*S).top - (*S).base >= (*S).stacksize) {
(*S).base = (SElemType*) realloc((*S).base, ((*S).stacksize + STACKINCREMENT) * sizeof(SElemType));
if((*S).base == NULL) {
exit(OVERFLOW); // 存储分配失败
}
(*S).top = (*S).base + (*S).stacksize;
(*S).stacksize += STACKINCREMENT;
}
// 进栈先赋值,栈顶指针再自增
*(S->top++) = e;
return OK;
}
/*
* 出栈
*
* 将栈顶元素弹出并用e接收。
*/
Status Pop(SqStack* S, SElemType* e) {
if(S == NULL || (*S).base == NULL) {
return ERROR;
}
if((*S).top == (*S).base) {
return ERROR;
}
// 出栈栈顶指针先递减,再赋值
*e = *(--(*S).top);
return OK;
}

View File

@@ -0,0 +1,66 @@
/*=========================
* 栈的顺序存储结构(顺序栈)
==========================*/
#ifndef SQSTACK_H
#define SQSTACK_H
#include <stdio.h>
#include <stdlib.h> // 提供malloc、realloc、free、exit原型
#include "Status.h" //**▲01 绪论**//
/* 宏定义 */
#define STACK_INIT_SIZE 100 // 顺序栈存储空间的初始分配量
#define STACKINCREMENT 10 // 顺序栈存储空间的分配增量
/* 顺序栈元素类型定义 */
typedef int SElemType;
// 顺序栈元素结构
typedef struct {
SElemType* base; // 栈底指针
SElemType* top; // 栈顶指针
int stacksize; // 当前已分配的存储空间,以元素为单位
} SqStack;
/*
* 初始化
*
* 构造一个空栈。初始化成功则返回OK否则返回ERROR。
*/
Status InitStack(SqStack* S);
/*
* 判空
*
* 判断顺序栈中是否包含有效数据。
*
* 返回值:
* TRUE : 顺序栈为空
* FALSE: 顺序栈不为空
*/
Status StackEmpty(SqStack S);
/*
* 取值
*
* 返回栈顶元素并用e接收。
*/
Status GetTop(SqStack S, SElemType* e);
/*
* 入栈
*
* 将元素e压入到栈顶。
*/
Status Push(SqStack* S, SElemType e);
/*
* 出栈
*
* 将栈顶元素弹出并用e接收。
*/
Status Pop(SqStack* S, SElemType* e);
#endif

View File

@@ -0,0 +1,86 @@
#include <stdio.h>
#include <ctype.h> // 提供isdigit原型
#include "Status.h" //**▲01 绪论**//
#include "SqStack.h" //**▲03 栈和队列**//
/*
* 对逆波兰表达式求值(理论上要求操作数与运算结果均为个位数)
*
*【注】
* 表达式的变量为单字母,操作符只有'+'、'-'、'*'、'/'四则运算
*/
Status Algo_3_22(char c[], SElemType* Value);
/* 计算 a oper b 的值 */
char Operate(char a, char oper, char b);
int main(int argc, char* argv[]) {
char c[] = "124*+93/-";
SElemType value;
printf("已知逆波兰式为:");
printf("%s\n", c);
Algo_3_22(c, &value);
printf("逆波兰式的计算结果为:%d\n", value - 48);
return 0;
}
/*
* 对逆波兰表达式求值(理论上要求操作数与运算结果均为个位数)
*
*【注】
* 表达式的变量为单字母,操作符只有'+'、'-'、'*'、'/'四则运算
*/
Status Algo_3_22(char c[], SElemType* Value) {
int i;
SqStack S;
SElemType a, b;
InitStack(&S);
for(i = 0; c[i]!='\0'; ++i) {
// 如果遇到数字字符
if(isdigit(c[i])) {
Push(&S, c[i]);
} else {
// 先弹出来的在操作数后边
Pop(&S, &b);
Pop(&S, &a);
Push(&S, Operate(a, c[i], b));
}
}
Pop(&S, Value);
if(!StackEmpty(S)) {
return ERROR;
} else {
return OK;
}
}
/* 计算 a oper b 的值 */
char Operate(char a, char oper, char b) {
char c;
switch(oper) {
case '+':
c = (a - 48) + (b - 48) + 48;
break;
case '-':
c = (a - 48) - (b - 48) + 48;
break;
case '*':
c = (a - 48) * (b - 48) + 48;
break;
case '/':
c = (a - 48) / (b - 48) + 48;
break;
}
return c;
}

View File

@@ -0,0 +1,7 @@
# 包含公共库
include_directories(${CMAKE_SOURCE_DIR}/Status)
# 生成可执行文件
add_executable(03.22 SqStack.h SqStack.c 03.22.c)
# 链接公共库
target_link_libraries(03.22 Scanf_lib)

View File

@@ -0,0 +1,90 @@
/*=========================
* 栈的顺序存储结构(顺序栈)
==========================*/
#include "SqStack.h" //**▲03 栈和队列**//
/*
* 初始化
*
* 构造一个空栈。初始化成功则返回OK否则返回ERROR。
*/
Status InitStack(SqStack* S) {
if(S == NULL) {
return ERROR;
}
(*S).base = (SElemType*) malloc(STACK_INIT_SIZE * sizeof(SElemType));
if((*S).base == NULL) {
exit(OVERFLOW);
}
(*S).top = (*S).base;
(*S).stacksize = STACK_INIT_SIZE;
return OK;
}
/*
* 判空
*
* 判断顺序栈中是否包含有效数据。
*
* 返回值:
* TRUE : 顺序栈为空
* FALSE: 顺序栈不为空
*/
Status StackEmpty(SqStack S) {
if(S.top == S.base) {
return TRUE;
} else {
return FALSE;
}
}
/*
* 入栈
*
* 将元素e压入到栈顶。
*/
Status Push(SqStack* S, SElemType e) {
if(S == NULL || (*S).base == NULL) {
return ERROR;
}
// 栈满时,追加存储空间
if((*S).top - (*S).base >= (*S).stacksize) {
(*S).base = (SElemType*) realloc((*S).base, ((*S).stacksize + STACKINCREMENT) * sizeof(SElemType));
if((*S).base == NULL) {
exit(OVERFLOW); // 存储分配失败
}
(*S).top = (*S).base + (*S).stacksize;
(*S).stacksize += STACKINCREMENT;
}
// 进栈先赋值,栈顶指针再自增
*(S->top++) = e;
return OK;
}
/*
* 出栈
*
* 将栈顶元素弹出并用e接收。
*/
Status Pop(SqStack* S, SElemType* e) {
if(S == NULL || (*S).base == NULL) {
return ERROR;
}
if((*S).top == (*S).base) {
return ERROR;
}
// 出栈栈顶指针先递减,再赋值
*e = *(--(*S).top);
return OK;
}

View File

@@ -0,0 +1,59 @@
/*=========================
* 栈的顺序存储结构(顺序栈)
==========================*/
#ifndef SQSTACK_H
#define SQSTACK_H
#include <stdio.h>
#include <stdlib.h> // 提供malloc、realloc、free、exit原型
#include "Status.h" //**▲01 绪论**//
/* 宏定义 */
#define STACK_INIT_SIZE 100 // 顺序栈存储空间的初始分配量
#define STACKINCREMENT 10 // 顺序栈存储空间的分配增量
/* 顺序栈元素类型定义 */
typedef int SElemType;
// 顺序栈元素结构
typedef struct {
SElemType* base; // 栈底指针
SElemType* top; // 栈顶指针
int stacksize; // 当前已分配的存储空间,以元素为单位
} SqStack;
/*
* 初始化
*
* 构造一个空栈。初始化成功则返回OK否则返回ERROR。
*/
Status InitStack(SqStack* S);
/*
* 判空
*
* 判断顺序栈中是否包含有效数据。
*
* 返回值:
* TRUE : 顺序栈为空
* FALSE: 顺序栈不为空
*/
Status StackEmpty(SqStack S);
/*
* 入栈
*
* 将元素e压入到栈顶。
*/
Status Push(SqStack* S, SElemType e);
/*
* 出栈
*
* 将栈顶元素弹出并用e接收。
*/
Status Pop(SqStack* S, SElemType* e);
#endif

View File

@@ -0,0 +1,109 @@
#include <stdio.h>
#include <stdlib.h> // 提供malloc、realloc、free、exit原型
#include <string.h> // 提供strlen原型
#include <ctype.h> // 提供isalpha原型
#include "SqStack.h" //**▲03 栈和队列**//
/*
* 将后缀表达式(逆波兰式)转换为前缀表达式(波兰式)
*
*【注】
* 表达式的变量为单字母,操作符只有'+'、'-'、'*'、'/'四则运算
*/
char* Algo_3_23(char* c);
// 将字符转换为字符串
char* CharToStr(char c);
// 拼接字符串a和b返回拼接后的字符串
char* StrCat(char* a, char* b);
int main(int argc, char* argv[]) {
char* s = "abc+*de/-";
printf("中缀表达式:%s\n", "a*(b+c)-d/e");
printf("后缀表达式:");
printf("%s\n", s);
printf("前缀表达式:");
printf("%s\n", Algo_3_23(s));
return 0;
}
/*
* 将后缀表达式(逆波兰式)转换为前缀表达式(波兰式)
*
*【注】
* 表达式的变量为单字母,操作符只有'+'、'-'、'*'、'/'四则运算
*/
char* Algo_3_23(char* c) {
int i;
char* s, * e1, * e2;
SqStack S;
InitStack(&S);
for(i = 0; c[i] != '\0'; i++) {
s = CharToStr(c[i]);
// 若c[i]为操作符(不是操作数),则栈中至少应当有两个元素
if(!isalpha(c[i])) {
if(Pop(&S, &e2) && Pop(&S, &e1)) {
s = StrCat(s, StrCat(e1, e2));
} else {
return NULL;
}
}
Push(&S, s);
}
Pop(&S, &s);
if(StackEmpty(S)) {
return s;
}
return NULL;
}
// 将字符转换为字符串
char* CharToStr(char c) {
char* s;
s = (char*) malloc(2 * sizeof(char));
s[0] = c;
s[1] = '\0';
return s;
}
// 拼接字符串a和b返回拼接后的字符串
char* StrCat(char* a, char* b) {
char* s;
int i, j, alen, blen;
alen = (int) strlen(a);
blen = (int) strlen(b);
s = (char*) malloc((alen + blen + 1) * sizeof(char));
j = 0;
for(i = 0; i < alen; i++) {
s[j++] = a[i];
}
for(i = 0; i < blen; i++) {
s[j++] = b[i];
}
s[j] = '\0';
return s;
}

View File

@@ -0,0 +1,7 @@
# 包含公共库
include_directories(${CMAKE_SOURCE_DIR}/Status)
# 生成可执行文件
add_executable(03.23 SqStack.h SqStack.c 03.23.c)
# 链接公共库
target_link_libraries(03.23 Scanf_lib)

View File

@@ -0,0 +1,90 @@
/*=========================
* 栈的顺序存储结构(顺序栈)
==========================*/
#include "SqStack.h" //**▲03 栈和队列**//
/*
* 初始化
*
* 构造一个空栈。初始化成功则返回OK否则返回ERROR。
*/
Status InitStack(SqStack* S) {
if(S == NULL) {
return ERROR;
}
(*S).base = (SElemType*) malloc(STACK_INIT_SIZE * sizeof(SElemType));
if((*S).base == NULL) {
exit(OVERFLOW);
}
(*S).top = (*S).base;
(*S).stacksize = STACK_INIT_SIZE;
return OK;
}
/*
* 判空
*
* 判断顺序栈中是否包含有效数据。
*
* 返回值:
* TRUE : 顺序栈为空
* FALSE: 顺序栈不为空
*/
Status StackEmpty(SqStack S) {
if(S.top == S.base) {
return TRUE;
} else {
return FALSE;
}
}
/*
* 入栈
*
* 将元素e压入到栈顶。
*/
Status Push(SqStack* S, SElemType e) {
if(S == NULL || (*S).base == NULL) {
return ERROR;
}
// 栈满时,追加存储空间
if((*S).top - (*S).base >= (*S).stacksize) {
(*S).base = (SElemType*) realloc((*S).base, ((*S).stacksize + STACKINCREMENT) * sizeof(SElemType));
if((*S).base == NULL) {
exit(OVERFLOW); // 存储分配失败
}
(*S).top = (*S).base + (*S).stacksize;
(*S).stacksize += STACKINCREMENT;
}
// 进栈先赋值,栈顶指针再自增
*(S->top++) = e;
return OK;
}
/*
* 出栈
*
* 将栈顶元素弹出并用e接收。
*/
Status Pop(SqStack* S, SElemType* e) {
if(S == NULL || (*S).base == NULL) {
return ERROR;
}
if((*S).top == (*S).base) {
return ERROR;
}
// 出栈栈顶指针先递减,再赋值
*e = *(--(*S).top);
return OK;
}

View File

@@ -0,0 +1,64 @@
/*=========================
* 栈的顺序存储结构(顺序栈)
==========================*/
#ifndef SQSTACK_H
#define SQSTACK_H
#include <stdio.h>
#include <stdlib.h> // 提供malloc、realloc、free、exit原型
#include "Status.h" //**▲01 绪论**//
/* 宏定义 */
#define STACK_INIT_SIZE 100 // 顺序栈存储空间的初始分配量
#define STACKINCREMENT 10 // 顺序栈存储空间的分配增量
/*
* 顺序栈元素类型定义
*
*【注】
* 这里使用字符串类型即SElemType指向一个字符串
*/
typedef char* SElemType;
// 顺序栈元素结构
typedef struct {
SElemType* base; // 栈底指针
SElemType* top; // 栈顶指针
int stacksize; // 当前已分配的存储空间,以元素为单位
} SqStack;
/*
* 初始化
*
* 构造一个空栈。初始化成功则返回OK否则返回ERROR。
*/
Status InitStack(SqStack* S);
/*
* 判空
*
* 判断顺序栈中是否包含有效数据。
*
* 返回值:
* TRUE : 顺序栈为空
* FALSE: 顺序栈不为空
*/
Status StackEmpty(SqStack S);
/*
* 入栈
*
* 将元素e压入到栈顶。
*/
Status Push(SqStack* S, SElemType e);
/*
* 出栈
*
* 将栈顶元素弹出并用e接收。
*/
Status Pop(SqStack* S, SElemType* e);
#endif

View File

@@ -0,0 +1,36 @@
#include <stdio.h>
#include <stdlib.h> // 提供malloc、realloc、free、exit原型
#include "Status.h" //**▲01 绪论**//
/*
* 递归计算g(m,n)
*/
int Algo_3_24(int m, int n);
int main(int argc, char* argv[]) {
int m, n;
m = 5;
n = 2;
printf("g(%d,%d) = %d\n", m, n, Algo_3_24(m, n));
return 0;
}
/*
* 递归计算g(m,n)
*/
int Algo_3_24(int m, int n) {
if(m < 0 || n < 0) {
exit(ERROR);
}
if(m == 0) {
return 0;
} else {
return Algo_3_24(m - 1, 2 * n) + n;
}
}

View File

@@ -0,0 +1,7 @@
# 包含公共库
include_directories(${CMAKE_SOURCE_DIR}/Status)
# 生成可执行文件
add_executable(03.24 03.24.c)
# 链接公共库
target_link_libraries(03.24 Scanf_lib)

View File

@@ -0,0 +1,67 @@
#include <stdio.h>
#include <stdlib.h> // 提供malloc、realloc、free、exit原型
#include "Status.h" //**▲01 绪论**//
/*
* 方法1递归法求解优点是算法简单
*
* 递归计算F(n)
*/
int Algo_3_25_1(int n);
/*
* 方法2消除递归的迭代法优点是存储了上一层计算数值
*
* 迭代计算F(n)
*/
int Algo_3_25_2(int n);
int main(int argc, char* argv[]) {
printf("F(10) = %d\n", Algo_3_25_1(10));
printf("F(10) = %d\n", Algo_3_25_2(10));
return 0;
}
/*
* 方法1递归法求解优点是算法简单
*
* 递归计算F(n)
*/
int Algo_3_25_1(int n) {
if(n < 0) {
exit(ERROR);
}
if(n == 0) {
return n + 1;
} else {
return n * Algo_3_25_1(n / 2);
}
}
/*
* 方法2消除递归的迭代法优点是存储了上一层计算数值
*
* 迭代计算F(n)
*/
int Algo_3_25_2(int n) {
int* a;
int i;
if(n < 0) {
exit(ERROR);
}
a = (int*) malloc((n + 1) * sizeof(int));
for(i = 1, a[0] = 1; i <= n; i++) {
a[i] = i * a[i / 2];
}
return a[n];
}

View File

@@ -0,0 +1,7 @@
# 包含公共库
include_directories(${CMAKE_SOURCE_DIR}/Status)
# 生成可执行文件
add_executable(03.25 03.25.c)
# 链接公共库
target_link_libraries(03.25 Scanf_lib)

View File

@@ -0,0 +1,62 @@
#include <stdio.h>
#include <stdlib.h> // 提供malloc、realloc、free、exit原型
#include "Status.h" //**▲01 绪论**//
/*
* 方法1递归法
*
* 递归计算平方根
*/
float Algo_3_26_1(float A, float p, float e);
/*
* 方法2迭代法
*
* 迭代计算平方根
*/
float Algo_3_26_2(float A, float p, float e);
int main(int argc, char* argv[]) {
printf("√50 = %f\n", Algo_3_26_1(50, 1, 0.000001f));
printf("√50 = %f\n", Algo_3_26_2(50, 1, 0.000001f));
return 0;
}
/*
* 方法1递归法
*
* 递归计算平方根
*/
float Algo_3_26_1(float A, float p, float e) {
if(A < 0.0) {
exit(ERROR);
}
if((p * p - A) > -e && (p * p - A) < e) {
return p;
} else {
return Algo_3_26_1(A, (p + A / p) / 2, e);
}
}
/*
* 方法2迭代法
*
* 迭代计算平方根
*/
float Algo_3_26_2(float A, float p, float e) {
if(A < 0.0) {
exit(ERROR);
}
while((p * p - A) >= e || (p * p - A) <= -e) {
p = (p + A / p) / 2;
}
return p;
}

View File

@@ -0,0 +1,7 @@
# 包含公共库
include_directories(${CMAKE_SOURCE_DIR}/Status)
# 生成可执行文件
add_executable(03.26 03.26.c)
# 链接公共库
target_link_libraries(03.26 Scanf_lib)

View File

@@ -0,0 +1,105 @@
#include <stdio.h>
#include <stdlib.h> // 提供malloc、realloc、free、exit原型
#include "Status.h" //**▲01 绪论**//
/* 栈元素类型定义 */
typedef struct {
int mval;
int nval;
} SElemType;
/*
* (1)递归法
*
* 递归计算阿克曼函数
*/
int Algo_3_27_1(int m, int n);
/*
* (2)利用栈模拟递归
*
* 模拟栈计算阿克曼函数
*/
int Algo_3_27_2(int m, int n);
int main(int argc, char* argv[]) {
printf("akm(3,4) = %d\n", Algo_3_27_1(3, 4));
printf("akm(3,4) = %d\n", Algo_3_27_2(3, 4));
return 0;
}
/*
* (1)递归法
*
* 递归计算阿克曼函数
*/
int Algo_3_27_1(int m, int n) {
int akm, tmp;
if(m < 0 || n < 0) {
exit(ERROR);
}
if(m == 0) {
akm = n + 1;
} else if(n == 0) {
akm = Algo_3_27_1(m - 1, 1);
} else {
akm = Algo_3_27_1(m - 1, Algo_3_27_1(m, n - 1));
}
return akm;
}
/*
* (2)利用栈模拟递归
*
* 模拟栈计算阿克曼函数
*/
int Algo_3_27_2(int m, int n) {
SElemType stack[1000];
int top = -1; // 初始化为-1而不是0
if(m < 0 || n < 0) {
exit(ERROR);
}
// 先递增,再存值
top++;
stack[top].mval = m;
stack[top].nval = n;
while(1) {
// m==0
while(top>0 && stack[top].mval == 0) {
top--;
stack[top].mval = stack[top].mval - 1;
stack[top].nval = stack[top + 1].nval + 1;
}
if(top==0 && stack[0].mval == 0) {
break;
}
// m!=0 n!=0
while(stack[top].nval > 0) {
top++;
stack[top].mval = stack[top - 1].mval;
stack[top].nval = stack[top - 1].nval - 1;
}
// m!=0 n==0
if(stack[top].nval == 0) {
stack[top].mval = stack[top].mval - 1;
stack[top].nval = 1;
}
}
return stack[top].nval + 1;
}

View File

@@ -0,0 +1,7 @@
# 包含公共库
include_directories(${CMAKE_SOURCE_DIR}/Status)
# 生成可执行文件
add_executable(03.27 03.27.c)
# 链接公共库
target_link_libraries(03.27 Scanf_lib)

View File

@@ -0,0 +1,157 @@
#include <stdio.h>
#include <stdlib.h> // 提供malloc、realloc、free、exit原型
#include <limits.h> // 提供一些数值常量
#include "Status.h" //**▲01 绪论**//
/*
* ████ 注意 ████
*
* 这里使用带头结点的循环链表表示队列
*/
/* 队列元素类型 */
typedef int QElemType;
/* 队列结点类型 */
typedef struct QNode {
QElemType data;
struct QNode* next;
} QNode, * QueuePtr;
/* 队列结构 */
typedef struct {
QueuePtr rear; // 队尾指针
} LinkQueue; // 队列的链式存储表示
// 队列初始化
Status InitQueue_3_28(LinkQueue* Q);
// 入队
Status EnQueue_3_28(LinkQueue* Q, QElemType e);
// 出队
Status DeQueue_3_28(LinkQueue* Q, QElemType* e);
// 输出队列元素
void Output(LinkQueue Q);
int main(int argc, char* argv[]) {
LinkQueue Q;
int i;
QElemType e;
printf("████ 初始化队列...\n");
InitQueue_3_28(&Q);
printf("████ 进行 5 次连续入队操作...\n");
for(i = 1; i <= 5; i++) {
EnQueue_3_28(&Q, i);
printf("█ 元素 \"%d\" 入队后,队列中的元素为:", i);
Output(Q);
}
printf("████ 进行 5 次连续出队操作...\n");
for(i = 1; i <= 5; i++) {
DeQueue_3_28(&Q, &e);
printf("█ 元素 \"%d\" 出队后,队列中的元素为:", e);
Output(Q);
}
return 0;
}
// 队列初始化
Status InitQueue_3_28(LinkQueue* Q) {
if(Q == NULL) {
return ERROR;
}
// 创建头结点
(*Q).rear = (QueuePtr) malloc(sizeof(QNode));
if((*Q).rear == NULL) {
exit(OVERFLOW);
}
// 头结点数据
(*Q).rear->data = INT_MAX;
// 循环队列,首尾相接
(*Q).rear->next = (*Q).rear;
return OK;
}
// 入队
Status EnQueue_3_28(LinkQueue* Q, QElemType e) {
QueuePtr p;
if(Q == NULL || (*Q).rear == NULL) {
return ERROR;
}
// 创建新结点,链式队列被认为不存在队满的问题
p = (QueuePtr) malloc(sizeof(QNode));
if(p == NULL) {
exit(OVERFLOW);
}
p->data = e;
p->next = (*Q).rear->next;
(*Q).rear->next = p;
(*Q).rear = p;
return OK;
}
// 出队
Status DeQueue_3_28(LinkQueue* Q, QElemType* e) {
QueuePtr h, p;
if(Q == NULL || (*Q).rear == NULL) {
return ERROR;
}
// 获取头结点
h = (*Q).rear->next;
// 如果只有一个头结点,说明没有元素,无法队列
if(h == (*Q).rear) {
return ERROR;
}
// 指向待移除元素
p = h->next;
*e = p->data;
h->next = p->next;
// 如果只有一个元素
if(p == (*Q).rear) {
// 更新队尾游标
(*Q).rear = h;
}
free(p);
return OK;
}
// 输出队列元素
void Output(LinkQueue Q) {
QueuePtr p;
if(Q.rear == NULL) {
printf("\n");
return;
}
for(p = Q.rear->next->next; p != Q.rear->next; p = p->next) {
printf("%d ", p->data);
}
printf("\n");
}

View File

@@ -0,0 +1,7 @@
# 包含公共库
include_directories(${CMAKE_SOURCE_DIR}/Status)
# 生成可执行文件
add_executable(03.28 03.28.c)
# 链接公共库
target_link_libraries(03.28 Scanf_lib)

View File

@@ -0,0 +1,130 @@
#include <stdio.h>
#include <stdlib.h> // 提供malloc、realloc、free、exit原型
#include "Status.h" //**▲01 绪论**//
/* 宏定义 */
#define MAXQSIZE 100 // 最大队列长度
/* 队列元素类型 */
typedef int QElemType;
/* 顺序循环队列 */
typedef struct {
QElemType* base; // 指向队列存储空间
int front, rear; // 队头和队尾游标
int tag; // 0表示未满1表示满
} SqQueue;
// 队列初始化
Status InitQueue_3_29(SqQueue* Q);
// 入队
Status EnQueue_3_29(SqQueue* Q, QElemType e);
// 出队
Status DeQueue_3_29(SqQueue* Q, QElemType* e);
// 输出队列元素
void Output(SqQueue Q);
int main(int argc, char* argv[]) {
SqQueue Q;
int i;
QElemType e;
printf("████ 初始化队列...\n");
InitQueue_3_29(&Q);
printf("████ 进行 5 次连续入队操作...\n");
for(i = 1; i <= 5; i++) {
EnQueue_3_29(&Q, i);
printf("█ 元素 \"%d\" 入队后,队列中的元素为:", i);
Output(Q);
}
printf("████ 进行 5 次连续出队操作...\n");
for(i = 1; i <= 5; i++) {
DeQueue_3_29(&Q, &e);
printf("█ 元素 \"%d\" 出队后,队列中的元素为:", e);
Output(Q);
}
return 0;
}
// 队列初始化
Status InitQueue_3_29(SqQueue* Q) {
if(Q == NULL) {
return ERROR;
}
(*Q).base = (QElemType*) malloc(MAXQSIZE * sizeof(QElemType));
if((*Q).base == NULL) {
exit(OVERFLOW);
}
(*Q).front = (*Q).rear = 0;
(*Q).tag = 0;
return OK;
}
// 入队
Status EnQueue_3_29(SqQueue* Q, QElemType e) {
// 队列满
if((*Q).tag == 1) {
return ERROR;
}
(*Q).base[(*Q).rear] = e;
(*Q).rear = ((*Q).rear + 1) % MAXQSIZE;
// 如果发现队满,则更新标记
if((*Q).rear == (*Q).front) {
(*Q).tag = 1;
}
return OK;
}
// 出队
Status DeQueue_3_29(SqQueue* Q, QElemType* e) {
// 队列空
if((*Q).front == (*Q).rear && (*Q).tag == 0) {
return ERROR;
}
*e = (*Q).base[(*Q).front];
(*Q).front = ((*Q).front + 1) % MAXQSIZE;
// 如果发现队空,则更新标记
if((*Q).rear == (*Q).front) {
(*Q).tag = 0;
}
return OK;
}
// 输出队列元素
void Output(SqQueue Q) {
int i;
// 队列空
if(Q.front == Q.rear && Q.tag == 0) {
printf("\n");
return;
}
i = Q.front;
do {
printf("%d ", Q.base[i]);
i = (i + 1) % MAXQSIZE;
} while(i != Q.rear);
printf("\n");
}

View File

@@ -0,0 +1,7 @@
# 包含公共库
include_directories(${CMAKE_SOURCE_DIR}/Status)
# 生成可执行文件
add_executable(03.29 03.29.c)
# 链接公共库
target_link_libraries(03.29 Scanf_lib)

View File

@@ -0,0 +1,209 @@
#include <stdio.h>
#include <stdlib.h> // 提供malloc、realloc、free、exit原型
#include "Status.h" //**▲01 绪论**//
#include "SqList.h" //**▲02 线性表**//
/* 宏定义 */
#define MAXQSIZE 5 // 队列长度,同时也是后续斐波那契数列数列的维度
#define MAX 100000
/* 队列元素类型 */
typedef int QElemType;
/* 顺序循环队列 */
typedef struct {
QElemType* base; // 指向队列存储空间
int rear; // 队尾游标
int length; // 队列元素个数
} SqQueue;
// 队列初始化
Status InitQueue_3_30(SqQueue* Q);
// 入队
Status EnQueue_3_30(SqQueue* Q, QElemType e);
// 出队
Status DeQueue_3_30(SqQueue* Q, QElemType* e);
/*
* 求k阶斐波那契数列满足特定条件的前n+1项
*/
Status Algo_3_32(int k, SqList* fib);
// 输出队列元素
void Output(SqQueue Q) {
int head;
if(Q.length == 0) {
printf("\n");
return;
}
// 队头游标
head = (Q.rear - Q.length + MAXQSIZE) % MAXQSIZE;
do {
printf("%d ", Q.base[head]);
head = (head + 1) % MAXQSIZE;
} while(head != Q.rear);
printf("\n");
}
int main(int argc, char* argv[]) {
int i;
printf("████████ 题 3.30 验证...\n");
{
SqQueue Q;
QElemType e;
printf("████ 初始化队列...\n");
InitQueue_3_30(&Q);\
printf("████ 进行 5 次连续入队操作...\n");
for(i = 1; i <= 5; i++) {
EnQueue_3_30(&Q, i);
printf("█ 元素 \"%d\" 入队后,队列中的元素为:", i);
Output(Q);
}
printf("████ 进行 5 次连续出队操作...\n");
for(i = 1; i <= 5; i++) {
DeQueue_3_30(&Q, &e);
printf("█ 元素 \"%d\" 出队后,队列中的元素为:", e);
Output(Q);
}
}
printf("████████ 题 3.32 验证...\n");
{
SqList fib;
Algo_3_32(MAXQSIZE, &fib);
printf("█ %d 阶斐波那契数列的前 %d 项为:\n", MAXQSIZE, fib.length);
for(i = 0; i < fib.length; i++) {
printf("%d ", fib.elem[i]);
}
printf("\n");
}
return 0;
}
// 队列初始化
Status InitQueue_3_30(SqQueue* Q) {
if(Q == NULL) {
return ERROR;
}
(*Q).base = (QElemType*) malloc(MAXQSIZE * sizeof(QElemType));
if((*Q).base == NULL) {
exit(OVERFLOW);
}
(*Q).rear = 0;
(*Q).length = 0;
return OK;
}
// 入队
Status EnQueue_3_30(SqQueue* Q, QElemType e) {
if(Q == NULL) {
return ERROR;
}
// 注意队列满的条件
if((*Q).length == MAXQSIZE) {
return ERROR;
}
(*Q).base[(*Q).rear] = e;
(*Q).rear = ((*Q).rear + 1) % MAXQSIZE;
(*Q).length++;
return OK;
}
// 出队
Status DeQueue_3_30(SqQueue* Q, QElemType* e) {
int head;
if(Q == NULL) {
return ERROR;
}
// 队列空
if((*Q).length == 0) {
return ERROR;
}
// 队头游标
head = ((*Q).rear - (*Q).length + MAXQSIZE) % MAXQSIZE;
*e = (*Q).base[head];
(*Q).length--;
return OK;
}
/*
* 求k阶斐波那契数列满足特定条件的前n+1项
*
*【注】
* 个人感觉这个题出的有些牵强。
* 因为既然要求计算前n+1项但队列只保留后k项这说明那个前n+1项必定需要保存到别的地方。
* 可是既然保存了前n+1项就没必要用到循环队列中的后k项了多余...
* 如果本题改为计算满足条件的【第】n+1项的值那么循环队列是有应用价值的
*/
Status Algo_3_32(int k, SqList* fib) {
int flag;
int i, j, sum;
SqQueue Q;
ElemType e;
if(k < 2 || MAX < 0) {
return ERROR;
}
InitQueue_3_30(&Q);
InitList(fib);
// 前k-1项为0
for(i = 1; i <= k - 1; i++) {
EnQueue_3_30(&Q, 0);
ListInsert(fib, i, 0);
}
// 第k项为1
EnQueue_3_30(&Q, 1);
ListInsert(fib, i, 1);
while((flag = GetElem(*fib, i, &e))==OK && e<=MAX){
/*
* 计算循环队列中现有元素的和
* 其实这一步可以改为计算顺序表中后k项的和这样一来就没循环队列啥事了
*/
for(j = 0, sum = 0; j < Q.length; j++) {
sum += Q.base[j];
}
// 此处的e只是用作临时变量
DeQueue_3_30(&Q, &e);
// 将新计算出的元素入队
EnQueue_3_30(&Q, sum);
// 顺便往顺序表中缓存一份
ListInsert(fib, ++i, sum);
}
return flag;
}

View File

@@ -0,0 +1,7 @@
# 包含公共库
include_directories(${CMAKE_SOURCE_DIR}/Status)
# 生成可执行文件
add_executable(03.30+03.32 SqList.h SqList.c 03.30+03.32.c)
# 链接公共库
target_link_libraries(03.30+03.32 Scanf_lib)

View File

@@ -0,0 +1,105 @@
/*=============================
* 线性表的顺序存储结构(顺序表)
*
* 包含算法: 2.3、2.4、2.5、2.6
=============================*/
#include "SqList.h"
/*
* ████████ 算法2.3 ████████
*
* 初始化
*
* 初始化成功则返回OK否则返回ERROR。
*/
Status InitList(SqList* L) {
// 分配指定容量的内存如果分配失败则返回NULL
(*L).elem = (ElemType*) malloc(LIST_INIT_SIZE * sizeof(ElemType));
if((*L).elem == NULL) {
// 存储内存失败
exit(OVERFLOW);
}
(*L).length = 0; // 初始化顺序表长度为0
(*L).listsize = LIST_INIT_SIZE; // 顺序表初始内存分配量
return OK; // 初始化成功
}
/*
* 取值
*
* 获取顺序表中第i个元素将其存储到e中。
* 如果可以找到返回OK否则返回ERROR。
*
*【备注】
* 教材中i的含义是元素位置从1开始计数但这不符合编码的通用约定。
* 通常i的含义应该指索引即从0开始计数。
*/
Status GetElem(SqList L, int i, ElemType* e) {
// 因为i的含义是位置所以其合法范围是[1, length]
if(i < 1 || i > L.length) {
return ERROR; //i值不合法
}
*e = L.elem[i - 1];
return OK;
}
/*
* ████████ 算法2.4 ████████
*
* 插入
*
* 向顺序表第i个位置上插入e插入成功则返回OK否则返回ERROR。
*
*【备注】
* 教材中i的含义是元素位置从1开始计数
*/
Status ListInsert(SqList* L, int i, ElemType e) {
ElemType* newbase;
ElemType* p, * q;
// 确保顺序表结构存在
if(L == NULL || (*L).elem == NULL) {
return ERROR;
}
// i值越界
if(i < 1 || i > (*L).length + 1) {
return ERROR;
}
// 若存储空间已满,则增加新空间
if((*L).length >= (*L).listsize) {
// 基于现有空间扩容
newbase = (ElemType*) realloc((*L).elem, ((*L).listsize + LISTINCREMENT) * sizeof(ElemType));
if(newbase == NULL) {
// 存储内存失败
exit(OVERFLOW);
}
// 新基址
(*L).elem = newbase;
// 存的存储空间
(*L).listsize += LISTINCREMENT;
}
// q为插入位置
q = &(*L).elem[i - 1];
// 1.右移元素,腾出位置
for(p = &(*L).elem[(*L).length - 1]; p >= q; --p) {
*(p + 1) = *p;
}
// 2.插入e
*q = e;
// 3.表长增1
(*L).length++;
return OK;
}

View File

@@ -0,0 +1,66 @@
/*=============================
* 线性表的顺序存储结构(顺序表)
*
* 包含算法: 2.3、2.4、2.5、2.6
=============================*/
#ifndef SQLIST_H
#define SQLIST_H
#include <stdio.h>
#include <stdlib.h> // 提供malloc、realloc、free、exit原型
#include "Status.h" //**▲01 绪论**//
/* 宏定义 */
#define LIST_INIT_SIZE 100 // 顺序表存储空间的初始分配量
#define LISTINCREMENT 10 // 顺序表存储空间的分配增量
/* 顺序表元素类型定义,跟队列元素类型一致 */
typedef int ElemType;
/*
* 顺序表结构
*
* 注elem在使用前需要先为其分配内存且元素从elem[0]处开始存储
*/
typedef struct {
ElemType* elem; // 顺序表存储空间的基址(指向顺序表所占内存的起始位置)
int length; // 当前顺序表长度(包含多少元素)
int listsize; // 当前分配的存储容量(可以存储多少元素)
} SqList;
/*
* ████████ 算法2.3 ████████
*
* 初始化
*
* 初始化成功则返回OK否则返回ERROR。
*/
Status InitList(SqList* L);
/*
* 取值
*
* 获取顺序表中第i个元素将其存储到e中。
* 如果可以找到返回OK否则返回ERROR。
*
*【备注】
* 教材中i的含义是元素位置从1开始计数但这不符合编码的通用约定。
* 通常i的含义应该指索引即从0开始计数。
*/
Status GetElem(SqList L, int i, ElemType* e);
/*
* ████████ 算法2.4 ████████
*
* 插入
*
* 向顺序表第i个位置上插入e插入成功则返回OK否则返回ERROR。
*
*【备注】
* 教材中i的含义是元素位置从1开始计数
*/
Status ListInsert(SqList* L, int i, ElemType e);
#endif

View File

@@ -0,0 +1,89 @@
#include <stdio.h>
#include <string.h> // 提供strlen函数的原型
#include "Status.h" //**▲01 绪论**//
#include "SqStack.h" //**▲03 栈和队列**//
/*
* 判断序列s是否为回文序列
* 空串也被视为回文序列
*/
Status Algo_3_31(char* s);
int main(int argc, char* argv[]) {
char* a = "abcdedcba@";
char* b = "ababab@";
if(Algo_3_31(a)) {
printf("%s不包括@)是回文序列!\n", a);
} else {
printf("%s不包括@)不是回文序列!!\n", a);
}
if(Algo_3_31(b)) {
printf("%s不包括@)是回文序列!\n", b);
} else {
printf("%s不包括@)不是回文序列!!\n", b);
}
return 0;
}
/*
* 判断序列s是否为回文序列
* 空串也被视为回文序列
*/
Status Algo_3_31(char* s) {
int len;
int i;
int m, n; // 回文串前半段的结尾下标和后半段的开始下标
SqStack S;
SElemType e;
len = (int) strlen(s);
if(len == 0 || s[len - 1] != '@') {
return FALSE;
}
// 空串被认为是回文序列
if(len == 1) {
return TRUE;
}
if(len % 2 == 0) {
m = (len - 2) / 2 - 1;
n = m + 2;
} else {
m = (len - 2) / 2;
n = m + 1;
}
InitStack(&S);
// 先把回文串前半段入栈
for(i = 0; i <= m; i++) {
Push(&S, s[i]);
}
// 取出回文串前半段,与字符串序列后半段比对
for(i = n; i <= len - 2; i++) {
if(!StackEmpty(S)) {
Pop(&S, &e);
} else {
break;
}
if(s[i] != e) {
return ERROR;
}
}
// 完美的状态应该是栈正好为空且i为len-1
if(!(StackEmpty(S) && i == len - 1)) {
return ERROR;
}
return OK;
}

View File

@@ -0,0 +1,7 @@
# 包含公共库
include_directories(${CMAKE_SOURCE_DIR}/Status)
# 生成可执行文件
add_executable(03.31 SqStack.h SqStack.c 03.31.c)
# 链接公共库
target_link_libraries(03.31 Scanf_lib)

Some files were not shown because too many files have changed in this diff Show More