01_逆序输出
//十进制数n到banse进制的转换(递归版)
void convert(stack<char>& S,__int64_t n,int base){
static char digit[] = {
'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'
};
if(0<n){ //在尚有余数之前,不断
S.push(digit[n % base]);
convert(S,n / base ,base); //通过递归得到最有最高位
}
}
//迭代版
void convert2(stack<char>& S,__int64_t n,int base){
static char digit[] = {
'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'
};
while(n > 0){
int remainder = (int)(n % base);
S.push(digit[remainder]); //余数入栈
n /= base; //你更新为其对base的除商
}
}
02_嵌套循环
02_01 栈混洗
- 这里的栈pop()操作会删除并返回栈顶元素,与c++中的stack标准库不同
- 栈混洗(stack permutation):有三个栈A,B,S.其中A含有n个元素,B和S初始化为空,只允许通过S.push(A.pop())弹出栈A的顶元素并压入栈S中,或通过B.push(S.pop())弹出S的栈顶元素并压入栈B中
- 由n次push和n次pop构成的任何操作序列,只要满足”任意前缀中的push不少于pop”限制,则该序列必然对应于某个栈混洗
02_02 括号匹配
递归版采用的是分治法,但是最坏情况时间复杂度为O(N²)
//括号匹配算法(递归版)
void trim(const char exp[],int& lo,int& hi){ //删除表达式exp[lo,hi]不含括号的最长前缀,后缀
while((lo <= hi) && (exp[lo] != '(') && (exp[lo] != ')'))
lo++;
while((lo <= hi) && (exp[hi] != '(') && (exp[hi] != ')'))
hi--;
}
int divide(const char exp[], int lo, int hi){
int mi = lo,crc = 1; //crc为[lo,mi]范围内左右括号数目之差
while((0 < crc) && (++mi < hi)) {//逐个检查各字符,直到左右括号数目相等,或者越界
if(exp[mi] == ')')
crc--;
if(exp[mi] == '(')
crc++;
}
return mi; //若mi <= hi,合法切分点;否则,意味着局部不可能匹配
}
//检查表达式[lo,hi]是否括号匹配(递归版)
bool paren(const char exp[],int lo,int hi){
trim(exp,lo,hi);
if(lo>hi) return true;
if(exp[lo] != '(')
return false; //首字符不是左括号肯定不匹配
if(exp[hi] != ')')
return false;
int mi = divide(exp,lo,hi); //确定适当的切分点
if(mi >hi) return false; //切分点不合法
return paren(exp,lo+1,mi-1) && paren(exp,mi+1,lo); //分别检查左右子表达式
}
//括号匹配算法(迭代版)
bool paren2(const char exp[],int lo, int hi) {//可兼顾三种括号
stack<char> S;//记录已发现,但未匹配的左括号
for (int i = 0; exp[i]; ++i) { //逐一检查当前字符
switch (exp[i]) { //左括号直接进栈,右括号若与栈顶失配,则返回false;
case '(' :
case '{':
case '[' :
S.push(exp[i]);
break;
case ')' :
if ((S.empty()) || ('(' != S.top()))
return false;
S.pop();
break;
case '}' :
if ((S.empty()) || ('{' != S.top()))
return false;
S.pop();
break;
case ']' :
if ((S.empty()) || ('[' != S.top()))
return false;
S.pop();
break;
default:
break; //非括号字符一律忽略
}
}
return S.empty(); //栈空则匹配
}