栈练习题
准备
#include <stdio.h>
#include "string.h"
#include "ctype.h"
#include "stdlib.h"
#include "math.h"
#include "time.h"
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define OK 1
#define MAXSIZE 20 //存储空间初始分配量
#define Stack_Init_Size 100
#define Stack_Increment 10
//顺序栈
typedef struct {
char * base;//栈底指针
char * top;//栈顶指针
int stackSize;//栈MaxSize
} SqStack;
//初始化栈
//思路:
//1、如果栈底为空
//2、分配一个最大容量Stack_Init_Size的数组,栈底/栈顶都指向它
//3、初始化粘的最大容量 Stack_Init_Size.
int InitStack(SqStack *S){
S->base = (char *)malloc(sizeof(char)*Stack_Init_Size);
if (S->base == NULL) return -1;//已初始化无法再初始化{
S->top = S->base;
S->stackSize = Stack_Init_Size;
printf("初始化成功\n");
return 0;
}
//获取栈顶数据
//1、判断是否为空
//2、非空,则栈顶指针 -1,返回栈顶元素
char GetTop(SqStack S){
if (S.base == S.top) return '#';//栈为空
return *(S.top -1);
}
//往栈里插入元素
//思路
//1、判断栈是否已满,若满则返回ERROR。 #问题:如何判断栈是否已满?
//2、栈满,则续容空间。 #问题:如何给已满栈续容空间?
//3、将元素 e(element) 压栈
//4、栈顶指针 加 1
int Push(SqStack *S, char e){
if (S->top - S->base == S->stackSize) {
S->base = (char *)realloc(S->base, sizeof(char)*Stack_Increment);
S->top = S->base + S->stackSize;
S->stackSize += Stack_Increment;
}
*S->top = e;
S->top += 1;
return 0;
}
//删除栈顶元素
//思路
//1、判断是否为空
//2、非空,则获取栈顶元素,并将栈顶减 1
char Pop(SqStack *S){
if (S->top == S->base) return '#';//为空
return *--S->top ;
}
//释放空间
int Destroy(SqStack *S){
free(S->base);
S->stackSize = 0;
return 0;
}
//**********************
typedef struct {
int data[MAXSIZE];
int top;
} SqStack_1;
//4.1 构建一个空栈S
int InitStack_1(SqStack_1 *S){
S->top = -1;
return OK;
}
//4.6 插入元素e为新栈顶元素
int PushData(SqStack_1 *S, int e){
//栈已满
if (S->top == MAXSIZE -1) {
return ERROR;
}
//栈顶指针+1;
S->top ++;
//将新插入的元素赋值给栈顶空间
S->data[S->top] = e;
return OK;
}
//4.7 删除S栈顶元素,并且用e带回
int Pop_1(SqStack_1 *S,int *e){
//空栈,则返回error;
if (S->top == -1) {
return ERROR;
}
//将要删除的栈顶元素赋值给e
*e = S->data[S->top];
//栈顶指针--;
S->top--;
return OK;
}
1、括号匹配问题
假设表达中允许包含两种括号:圆括号与方括号,其嵌套顺序随意,即 ([()][]) 或者([])都是正确的,而 )[])() 类似的是不正确。写一个方法检验括号是否匹配 。
思路
将[ ( 全部入栈,遇到 ) 或 ] 出栈,
如果是 ] 要判断出栈的是否是 [,如果不是就不匹配
如果是 ) 要判断出栈的是否是 (,如果不是就不匹配
int ExecuteData(SqStack S, char * data){
// Push(&S, data[0]);
for (int i=0; i<strlen(data); i++) {
switch (data[i]) {
case '[':
Push(&S, data[i]);
break;
case '(':
Push(&S, data[i]);
break;
case ']':
if (S.top==S.base) return -1;
if (Pop(&S) != '[') return -1;
Pop(&S);
break;
case ')':
if (S.top==S.base) return -1;
if (Pop(&S) != '(') return -1;
Pop(&S);
break;
default:
return -1;
break;
}
}
//全部出栈,释放。返回匹配成功
if (S.top == S.base) {
Destroy(&S);
return 0;
}
Destroy(&S);
return -1;
}
SqStack stack;
InitStack(&stack);
//1、括号匹配问题
printf(" ***** 问题1、括号匹配问题 ***** \n");
// char data[180];
// printf("请输入待匹配的字符串\n");
// scanf("%s",data);
char data[180] = {'[','(',']','[','[',']','[',']',')',']'};
int result = ExecuteData(stack,data);
if(result==0)printf("括号是正确匹配的\n");
else printf("括号匹配不正确\n");
//*****************************************************
***** 问题1、括号匹配问题 *****
括号匹配不正确
2、每日温度问题
根据每日气温列表,请重新生成一个列表,对应位置的输入是你需要再等待多久温度才会升高超过该日的天数。如果之后都不会升高,请在该位置用0来替代。例如:给定一个列表 temperatures = [73,74,75,71,69,72,76,73],输出应该是[1,1,4,2,1,1,0,0];
提示:气温列表的范围是[1,30000]。每个气温的值均为华氏度,都在[30,100]范围内的整数。
分析:
实际就是找到从[i, TSize] 中找当前元素后第一个大于当前元素的值与当前元素的下标差值。
最后一个元素默认是0,因为后面已经没有元素了。
解法一:
暴力法1、 递归(强烈不建议使用)
思路:
1、遍历数组,取出温度,执行递归比较。
2、如果是数组最后一位,直接返回0。
3、如果递归取到的值大于需要比较的温度返回1。否者继续递归,没递归一次进行一次++操作,如果到最后还不大于,将记录标记为 0.
int dailyTemperatures_0(int *a, int n, int count, int an, int num){
if (n == count-1) return 0;
if (an<a[n+1]) return 1;
else{
int x = n+1;
while (x<count) {
int p = dailyTemperatures_0(a, x, count, an, num++);
x++;
if (p == 1) {
return num;
}else if(p == 0 && n == count-1){
return 0;
}
}
}
return 0;
}
暴力法2、
思路:
1、从左到右开始遍历(从第一个数到最后一个数开始遍历)。最后一个元素默认是0,不需要在进行计算
2、从[i+1,TSize]遍历,每个数值知道找到比他大的数,数的次数就是对应值
步骤:
1、创建一个result 结果数组
2、默认result[TSize-1] = 0;
3、从0个元素遍历到最后一个元素[0,TSize-1];
3.1、如果当前i > 0并且当前的元素和上一个元素相等,则没有必要继续循环。则判断一下result[i-1]是否等于0,如果等于则直接将result = 0,否者result[i] = result[i-1]-1;
3.2、遍历元素[i+1,TSzie]如果当前 T[j]>T[i],则result[i] = j-i;如果当前T[j] 已经是最后一个元素,则默认result[i] = 0;
int *dailyTemperatures_1(int* T, int TSize){
int *result = (int *)malloc(sizeof(int)*TSize);//创建结果数组
result[TSize-1] = 0;
// 遍历不需要遍历最后天的,因为直接就是0,没有遍历的意义
for (int i=0; i<TSize-1; i++) {
//如果当前温度与前一天温度相等,无需继续计算,直接返回前一天的值-1
if (i>0 && T[i] == T[i-1]) {
result[i] = (result[i-1] == 0)?0:(result[i-1]-1);
}else{
for (int j=i+1; j<TSize; j++) {
if (T[i] < T[j]) {
result[i] = j-i;
break;
}
if (j == TSize-1) {
result[i] = 0;
}
}
}
}
return result;
}
三、跳跃法
思路:
1、从右到左遍历。因为最后一天默认等于0;
2、i 从[TSzie-2,0]; 从倒数第二天开始遍历比较,每次减 1;
3、j 从[i+1,TSize]遍历,j+=result[j],可以利用已经有结果的位置进行跳跃,从而减少遍历次数
(3.1)、若T[i]<T[j],那么Result[i] = j - i;
(3.2)、若result[j] == 0,则表示后面不会有更大的值,那么当前值就应该也是0;
步骤
1、创建一个 result 结果数组
2、默认result[TSize-1] = 0;
3、从TSize-2个元素开始遍历,遍历到第一个元素。[TSize-2,0]
4、从[i+1,TSize]遍历,j+=result[j];
(4.1)、若T[i]<T[j],那么Result[i] = j-i;
(4.2)、若Result[j] = 0,则表示后面不会有更大的值,那么当前值就应该也是0;
int *dailyTemperatures_2(int* T, int TSize){
int *result = (int *)malloc(sizeof(int)*TSize);
result[TSize-1] = 0;
for (int i=TSize-2; i >=0; i--) {
for (int j = i+1; j<TSize; j+=result[j]) {
if (T[i]<T[j]) {
result[i] = j-i;
break;
}
// 判断i 之后的温度,如果比i 的温度还要低或相等的时候。如果后面不会有更大的值,那么当前值就应该也是0;
if (result[j] == 0) {
result[i] = 0;
break;
}
}
}
return result;
}
四、栈思想实现
思路:
1、初始化一个栈(用来存储索引),value数组
2、栈中存储的是元素的索引index;
3、遍历整个温度数组[0,TSize];
(3.1)、如果栈顶元素<当前元素,则将当前元素索引 index -栈顶元素index,计算完毕则将当前栈顶元素移除,将当前元素索引index 存储到栈中;出栈后,只要栈不为空。继续比较,知道栈顶元素不能满足T[i] > T[stack_index[top-1]]
(3.2)、如果当前的栈为空,则直接入栈;
(3.3)、如果当前的元素小于栈顶元素,则入栈。
(3.4)、while循环结束后,当前元素也需要入栈。
int* dailyTemperatures_3(int* T, int TSize) {
int *result = (int *)malloc(sizeof(int)*TSize);
// 用栈记录 T的下标
int *stack_index = malloc(sizeof(int)*TSize);
// 栈顶指针
int top = 0;
int tIndex;
for (int i=0; i<TSize; i++) {
result[i] = 0;
}
for (int i=0; i<TSize; i++) {
printf("\n 第 %d 次循环\n",i);
// 若当前元素大于栈顶元素,栈顶元素出栈。即温度升高了,所求天数为两者下标的差值
while (top >0 && T[i] > T[stack_index[top-1]]) {
tIndex = stack_index[top -1];
result[tIndex] = i - tIndex;
top--;
printf("tIndex = %d; result[%d] = %d,top = %d\n",tIndex,tIndex,result[tIndex],top);
}
// 当前元素入栈
stack_index[top] = i;
printf("i=%d; stackIndex[%d] = %d",i,top,stack_index[top]);
top++;
printf("top = %d \n",top);
}
return result;
}
//2、每日气温
// 暴力法1 递归
int test[8] = {73,74,75,71,69,72,76,73};
int b[8];
int n = 0;
while (n <8) {
int i = dailyTemperatures_0(test, n, 8, test[n], 1);
b[n] = i;
n++;
printf("%d ",i);
}
int *result1,*result2,*result3;
int returnSize=8;
result1 = dailyTemperatures_1(test, 8);//暴力法
result2 = dailyTemperatures_2(test, 8);//跳跃法
result3 = dailyTemperatures_3(test, 8);//栈思想
printf("\n");
for (int i = 0; i < returnSize;i++ ) {
printf("%d ",test[i]);
}
printf("\n result1: ");
for (int i = 0; i < returnSize;i++ ) {
printf("%d ",result1[i]);
}
printf("\n result2: ");
for (int i = 0; i < returnSize;i++ ) {
printf("%d ",result2[i]);
}
printf("\n result3: ");
for (int i = 0; i < returnSize;i++ ) {
printf("%d ",result3[i]);
}
printf("\n");
//************************************************
1 1 4 2 1 1 0 0
第 0 次循环
i=0; stackIndex[0] = 0top = 1
第 1 次循环
tIndex = 0; result[0] = 1,top = 0
i=1; stackIndex[0] = 1top = 1
第 2 次循环
tIndex = 1; result[1] = 1,top = 0
i=2; stackIndex[0] = 2top = 1
第 3 次循环
i=3; stackIndex[1] = 3top = 2
第 4 次循环
i=4; stackIndex[2] = 4top = 3
第 5 次循环
tIndex = 4; result[4] = 1,top = 2
tIndex = 3; result[3] = 2,top = 1
i=5; stackIndex[1] = 5top = 2
第 6 次循环
tIndex = 5; result[5] = 1,top = 1
tIndex = 2; result[2] = 4,top = 0
i=6; stackIndex[0] = 6top = 1
第 7 次循环
i=7; stackIndex[1] = 7top = 2
73 74 75 71 69 72 76 73
result1: 1 1 4 2 1 1 0 0
result2: 1 1 4 2 1 1 0 0
result3: 1 1 4 2 1 1 0 0
3、爬楼问题
假设你正在爬楼梯。需要 n 阶才能到达楼顶。每次你可以爬1或2个台阶。一共有多少种方法可以爬到楼顶?给定 n 是一个正整数。
方法一:
递归法
分析:
1、一次只能爬1阶或2阶,有固定条件。可以拆分成一样的小块处理
2、给定n 能到达楼顶,有出口
所以第一想到的肯定是递归。在进行分析:
n = 1; 只有1种方式
n = 2; 有 2种方式
n = 3; 有 3种方式
n = 4; 有 5种方式
结论
n <= 3 时 有n 种
n > 3 时 有 f(n-1) + f(n-2) 种
int ClimbStairs_1(int n){
if (n<=3) return n;
return ClimbStairs_1(n-1) + ClimbStairs_1(n-2);
}
方法二:
动态规划法
思路
1、创建一个长度为 n+1 的数组
2、当前的i 有多少种方法 = i-1 + i-2 的方法数量
int ClimbStairs_2(int n){
if (n <= 3) return n;
int num = n+1;
int * sum = (int *)malloc(sizeof(int)*num);
sum[0]=0;
sum[1]=1;
sum[2]=2;
for (int i=3; i<=n; i++) {
sum[i] = sum[i-1] + sum[i-2];
}
return sum[n];
}
//3、爬楼问题
printf(" ***** 问题3、爬楼问题 ***** \n");
int num = 5;
int i_1 = ClimbStairs_1(num);
printf("1、 一共有 %d 级台阶,公有 %d 种爬楼方式\n",num,i_1);
int i_2 = ClimbStairs_2(num);
printf("2、 一共有 %d 级台阶,公有 %d 种爬楼方式\n",num,i_2);
//****************************************
***** 问题3、爬楼问题 *****
1、 一共有 5 级台阶,公有 8 种爬楼方式
2、 一共有 5 级台阶,公有 8 种爬楼方式
4、去除重复字母(LeetCode-困难)
给定一个仅包含小写字母的字符串,请你去除字符串中重复的字母,使得每个字母只出现一次。需保证返回结果的字典序最小(要求不能打乱其他字符的相对位置)
示例1:
输入: ”bcabc“
输出: "abc"
示例2:
输入:"cbacdcbc"
输出:”acdb“
分析:
字典序:例如字典中的排列顺序。例如任意一个a开头的字符串都大于任意一个b开头的字符串
思路:
1、判断字符串可能出现的特殊情况(字符串为空,字符串长度小于等于1)
2、用一个 record(记录) 数组记录字符串字母出现的次数
3、申请一个字符串栈 stack 用来存储去除重复字母之后的结果,并利用他的特性帮助我们找到正确的次序
4、遍历字符串 s
5、从0 - top 空间,遍历stack 判断当前字符s[i]是否已经存在栈中。用一个falg isExist 标记即可,0标识不存在,1标识存在
6、如果isExist 不存在,则:
(1)、如果不存在,则需要循环一个找到一个正确的位置,然后在存储起来;
(2)、如果不存在,跳过栈中所有比当前字符大,且后面还会出现的元素,然后将当前字符入栈
top > -1表示栈非空
stack[top] > s[i] 表示栈顶元素比当前元素大
record[stack[top]] > 1 表示后面还会出现
通过while 循环找到栈中位置错误的数据,出栈。找到当前合适的位置,则结束while循环;找到合理的位置后,则将当前字符s[i]入栈;
8、知道遍历完所有的字符后,则为字符串栈stack 添加一个结束符 '\0',并返回当前字符串首地址;
char *removeDuplicateLetters(char * s){
/*
1、特殊情况处理 s为空,长度为0
2、s长度为1,直接输出
*/
if (s== NULL || strlen(s) ==0) return "";
if (strlen(s) == 1) return s;
// record 数组,用来记录字符串 s 中每个字符未来会出现的次数
char record[26] = {0};
int len = (int)strlen(s);
// 申请一个字符串 stack;(用栈的特性来进行stack 字符串的数据进出)
char *stack = (char *)malloc(sizeof(char)*(len+1));//至少加1,用来放字符串结束符 '\0'
memset(stack, 0, sizeof(char)*(len+1));
// 栈顶赋初值为 -1
int top = -1;
// 统计每个字符的频次
// s[i] - 'a' 得出在数组中对应的索引
int i;
for (i =0; i<len; i++) {
record[s[i] - 'a']++;
}
// 遍历字符串s 入栈
for (i=0; i<len; i++) {
//isExist 标记当前字符是否存在栈中;
int isExist = 0;
// 从0 - top,遍历stack 判断当前字符串s[i] 是否存在栈中
// 当前字符串是否存在栈中falg,0表示不存在,1表示存在
// top 指向栈顶(也就是执行stack 字符串最后一个字符的位置,表示字符串长度上限)
for (int j=0; j<=top; j++) {
if (s[i] == stack[j]) {
isExist = 1;
break;
}
}
// 如果存在,record[s[i]]位置上的出现次数减一,并继续遍历下一个字符
// 如果不存在,则需要循环一个正确位置存储起来
// 如果不存在,跳过栈中多有比当前字符大,且后面还会出现的元素,然后将当前字符入栈
if (isExist == 1) {
record[s[i]-'a']--;
}else{
// top >-1 表示栈非空
// stack[top] > s[i] 表示栈顶元素比当前元素大
// record[stack[top] -'a'] >1 表示后面还会出现当前字符,所以可以出栈
// 循环出栈,直到栈为空 或 栈顶元素不大于当前元素 或 栈顶元素在后面的字符串中没有了为止
while (top >-1 && stack[top] > s[i] && record[stack[top]-'a'] >1) {
// 跳出该元素 频次减一
record[stack[top]-'a']--;
//出栈
top--;
}
// 将当前元素插入到top 的下一个位置
// top往上移动 1 位
// 入栈
top++;
stack[top] = s[i];
}
}
// 结束栈顶添加字符结束符
stack[++top] = '\0';
return stack;
}
// 4、去除重复字符
char *s ;
s = removeDuplicateLetters("bcabcddacb");
printf("%s\n",s);
//*********************************
abcd
总结:
1、用一个数组记录字符串中各个字符出现的次数
2、第一个字符入栈
3、遍历字符串。那当前字符与栈(遍历栈)中元素比较。如果栈中元素等于当前元素,比较为1。表示栈中已存在。同时数组计数-1
4、当前字符,栈中不存在。遍历栈与当前字符比较,如果栈中字符 > 当前字符并且栈中字符 数组中计数 > 1,则数组中栈元素对应的数值减1,同时出栈
5、top++ 将当前字符入栈。继续遍历字符串
6、栈中添加结束符,返回。
5、字符串编码
编码规则:K[encoded_string],表示其中方括号内部的 encoded_string 正好重复K 次。注意 k 保证为正整数。你可以认为输入字符串总是有效的,输入字符串中没有额外的空格,且输入的方括号是符合格式要求的。此外,你可以认为原始数据不包含数字,所有数字只表示重复次数 k。例如不会出现像 3a 或 2[4] 的输入
例如:
s = "3[a]2[bc]",返回 “aaabcbc”
s = "3[a2[c]]",返回 “accaccacc”
s = "3[ab]2[cd]ef",返回 “abababcdcdef”
分析
1、处理问题先从简到难,先用解决最简答的,例如 12[a]
2、12是两位需要注意判断。
思路:
1、遍历字符串 S
2、如果当前字符不为方括号 “]” 则入栈 stack;
3、如果当前字符串遇到了方括号"]" 则:
(3.1)、先找到要复制的字符,例如 stack = "12[a",那么我要首先获取字符串a;将这个a 保存在另外一个栈去 tempStack;
(3.2)、再找到需要备份的数量,例如 stack = “12[a”,因为出栈为字符串"a",则当前的top 指向了"[",也就是等于2;
(3.3)、而12对于字符串是2个字符,我们要通过遍历找到数字12的top上限/下限的位置索引,此时上限 curTop = 2,下限通过出栈,top = -1;
(3.4)、根据范围[-1,2],读取出12保存到strOfInt 字符串中来,并将x字符串”12\0“,转成数字12
(3.5)、当前top = -1,将tempStack中的字符a,复制12份入栈 stack 中来;
(3.6)、为当前的stack 扩容,在stack 字符串的末尾添加字符串结束符号”\0”
char * decodeString(char * S){
/*
1、获取字符串长度
2、设置默认栈长度为50
3、开辟字符串栈(空间为0)
4、设置栈头指针top = -1;
*/
int len = (int)strlen(S);
int stackSize = 50;
char * stack = (char *)malloc(sizeof(char)*stackSize);
int top = -1;
// 遍历字符串,在没有遇到“]”之前入栈
for (int i=0; i<len; i++) {
if (S[i] != ']') {
// 判断top 是否达到了栈的上限,如果达到了栈的上限就进行扩容,扩容到原大小的2倍(根据自己需要进行扩容,不是必须为2倍。只是OC底层的一些代码基本上都是以2倍的形式扩容,所以这里模仿一下)
if (top == stackSize-1) {
stack = realloc(stack, sizeof(char)*(stackSize*2));
}
// 将字符串入栈 stack
stack[++top] = S[i];
printf("(1)、没有遇到‘]’之前。 top = %d\n",top);
}
else{
int tempSize = 10;
char * temp = (char *)malloc(sizeof(char)*tempSize);
int topOfTemp = -1;
printf("(2)、开始获取要复制的字符信息之前。 top= %d\n",top);
// 从栈顶位置开始遍历stack ,直到‘[’结束
// 把[a] 这个字母a 赋值到temp 栈中来;
// 简单说,就是将stack 中方括号里的字符出栈,复制到temp 栈中来;
while (stack[top] != '[') {
// 如果topOfTemp到达了栈的上限,则为栈扩容;
if (topOfTemp == tempSize-1) {
temp = (char *)realloc(temp, sizeof(char)*(tempSize*2));
}
// temp栈的栈顶指针自增
// stack 出栈,则top 栈顶指针递减
temp[++topOfTemp] = stack[top--];
}
printf("(2)、开始获取要复制的字符信息之后。 top= %d\n",top);
// 找到倍数数字.strOfInt 字符串
// 注意:如果是大于1位的情况就处理
char strOfInt[11];
int curTop = top;
printf("(3)、开始获取数字,数字位置上限。 curTop= %d\n",curTop);
// top-- 的目的是吧‘[’ 剔除,才能找到数字;
// 因为上面的 while (stack[top] != '[')将数字入栈了,遇到’[‘会跳出循环,也就是说当前这时候是’[‘,这时候栈顶指针 -- 跳过’[‘
top--;
// 遍历stack 得出数字。跳过’[‘之后(由于出栈是由后向前的,所以’[‘跳过之后就能得到数字)
// 例如39[a] 接要找到这个数字 39.
// p指向当前的top,我就知道上限了;那么接下来通过循环来找到它的数字下限;
while (top != -1 && stack[top] >= '0' && stack[top] <= '9') {
top--;
}
printf("(3)、开始获取数字,数字位置下限。top = %d\n",top);
// 从top-1 遍历到p 之间,把stack[top-1, p]之间的数字复制到到strOfInt 中来;
// 39中 3 和 9都是字符。我们要获取到这2个数字,存储到strOfInt 数组
for (int j = top+1; j<curTop; ++j) {
strOfInt[j - (top +1)] = stack[j];
}
strOfInt[curTop - (top +1)] = '\0';
// 把strOfInt 字符串转换成整数 atoi 函数;
// 把字母复制strOfInt 分到stack 中去;
// 例如 39[a],就需要把a 复制39份存进去。
int curNum = atoi(strOfInt);
for (int k=0; k<curNum; k++) {
//从-1 到topOfTemp 范围内,复制curNum份到stackTop中去;
int kk = topOfTemp;
while (kk != -1) {
// 如果stack 达到了栈的上限,则栈扩容
if (top == stackSize -1) {
stack = realloc(stack, sizeof(char)*(stackSize*2));
}
// 将temp 栈的字符复制到stack 中;
stack[++top] = temp[kk--];
}
}
free(temp);
temp = NULL;
}
}
// realloc 动态内存调整
//void *realloc(void *mem_address, unsigned int newsize);
// 构成字符串stack 后,在stack 的空间扩容
char *ans = realloc(stack, sizeof(char)*(top+1));
ans[++top] = '\0';
// stack 栈不用,则释放;
free(stack);
return ans;
}
// 5、字符编码
char *s1,*s2,*s3,*s4;
s1 = decodeString("12[a]");
printf("字符编码后的结果: %s\n\n\n\n",s1);
s2 = decodeString("3[a]2[bc]");
printf("字符编码后的结果: %s\n\n\n\n",s2);
s3 = decodeString("3[a12[c]]");
printf("字符编码后的结果: %s\n\n\n\n",s3);
s4 = decodeString("2[abc]3[cd]ef");
printf("字符编码后的结果: %s\n\n\n\n",s4);
//********************************************
(1)、没有遇到‘]’之前。 top = 0
(1)、没有遇到‘]’之前。 top = 1
(1)、没有遇到‘]’之前。 top = 2
(1)、没有遇到‘]’之前。 top = 3
(2)、开始获取要复制的字符信息之前。 top= 3
(2)、开始获取要复制的字符信息之后。 top= 2
(3)、开始获取数字,数字位置上限。 curTop= 2
(3)、开始获取数字,数字位置下限。top = -1
字符编码后的结果: aaaaaaaaaaaa
(1)、没有遇到‘]’之前。 top = 0
(1)、没有遇到‘]’之前。 top = 1
(1)、没有遇到‘]’之前。 top = 2
(2)、开始获取要复制的字符信息之前。 top= 2
(2)、开始获取要复制的字符信息之后。 top= 1
(3)、开始获取数字,数字位置上限。 curTop= 1
(3)、开始获取数字,数字位置下限。top = -1
(1)、没有遇到‘]’之前。 top = 3
(1)、没有遇到‘]’之前。 top = 4
(1)、没有遇到‘]’之前。 top = 5
(1)、没有遇到‘]’之前。 top = 6
(2)、开始获取要复制的字符信息之前。 top= 6
(2)、开始获取要复制的字符信息之后。 top= 4
(3)、开始获取数字,数字位置上限。 curTop= 4
(3)、开始获取数字,数字位置下限。top = 2
字符编码后的结果: aaabcbc
(1)、没有遇到‘]’之前。 top = 0
(1)、没有遇到‘]’之前。 top = 1
(1)、没有遇到‘]’之前。 top = 2
(1)、没有遇到‘]’之前。 top = 3
(1)、没有遇到‘]’之前。 top = 4
(1)、没有遇到‘]’之前。 top = 5
(1)、没有遇到‘]’之前。 top = 6
(2)、开始获取要复制的字符信息之前。 top= 6
(2)、开始获取要复制的字符信息之后。 top= 5
(3)、开始获取数字,数字位置上限。 curTop= 5
(3)、开始获取数字,数字位置下限。top = 2
(2)、开始获取要复制的字符信息之前。 top= 14
(2)、开始获取要复制的字符信息之后。 top= 1
(3)、开始获取数字,数字位置上限。 curTop= 1
(3)、开始获取数字,数字位置下限。top = -1
字符编码后的结果: accccccccccccaccccccccccccacccccccccccc
(1)、没有遇到‘]’之前。 top = 0
(1)、没有遇到‘]’之前。 top = 1
(1)、没有遇到‘]’之前。 top = 2
(1)、没有遇到‘]’之前。 top = 3
(1)、没有遇到‘]’之前。 top = 4
(2)、开始获取要复制的字符信息之前。 top= 4
(2)、开始获取要复制的字符信息之后。 top= 1
(3)、开始获取数字,数字位置上限。 curTop= 1
(3)、开始获取数字,数字位置下限。top = -1
(1)、没有遇到‘]’之前。 top = 6
(1)、没有遇到‘]’之前。 top = 7
(1)、没有遇到‘]’之前。 top = 8
(1)、没有遇到‘]’之前。 top = 9
(2)、开始获取要复制的字符信息之前。 top= 9
(2)、开始获取要复制的字符信息之后。 top= 7
(3)、开始获取数字,数字位置上限。 curTop= 7
(3)、开始获取数字,数字位置下限。top = 5
(1)、没有遇到‘]’之前。 top = 12
(1)、没有遇到‘]’之前。 top = 13
字符编码后的结果: abcabccdcdcdef
6、 杨辉三角
思路:
1、第一层循环控制行数i : 默认[i][0] = 1,[i][i] = 1;
2、第二层循环控制列数j : triangle[i][j] = triangle[i-1][j-1] + triangle[i-1][j]
//因为返回的是二维数组,所以要用 **
int ** generate(int numRows, int * returnSize){
* returnSize = numRows;
int ** res = (int **)malloc(sizeof(int*)*numRows);
for (int i=0; i<numRows; i++) {
res[i] = (int *)malloc(sizeof(int)*(i+1));
res[i][0] = 1;
res[i][i] = 1;
for (int j= 1; j<i; j++) {
res[i][j] = res[i-1][j] + res[i-1][j-1];
}
}
return res;
}
// 6、
printf("杨辉三角问题\n");
int numRows = 5;
int returnSize;
int **returnResult;
returnResult = generate(numRows, &returnSize);
for (int i = 0; i < returnSize; i++) {
printf("[");
for (int j = 0; j<=i; j++) {
printf(" %d ",returnResult[i][j]);
}
printf("]\n");
}
//*********************************
杨辉三角问题
[ 1 ]
[ 1 1 ]
[ 1 2 1 ]
[ 1 3 3 1 ]
[ 1 4 6 4 1 ]
7、进制转换
1、初始化一个空栈
2、当十进制N 非零的时候,循环执行以下操作
(1)、把N 与需要的进制数取余 例如:八进制 %8 得到八进制的数压栈入栈S
(2)、N更新为N与 需要的进制数的商 例如:八进制 /8
3、当栈S 非空时,循环执行以下操作
(1)、弹出栈顶元素e;
(2)、输出e;
int conversion(int N, int IntoSystem){
if (IntoSystem <=1) return ERROR;
SqStack_1 S;
int e;
// 1、初始化一个空栈S
InitStack_1(&S);
// 2、
while (N) {
PushData(&S, N % IntoSystem);
N = N / IntoSystem;
}
// 3、
while (S.top != -1) {
Pop_1(&S, &e);
printf("%d \n",e);
}
return OK;
}
// 7、进制转换
conversion(1348,8);
//*************************
2
5
0
4