因为今年考研的原因,所以就根据王道后面的习题进行总结
大致归类了一些顺序、链表存储结构、基本算法实现代码合集,也是为了后续方便复习
1.1顺序栈
1.1.1结点结构
#define MaxSize 50 //定义栈中元素的最大个数
typedef struct
{
ElemType data[MaxSize] ;//存放栈中元素
int top ;//栈顶指针
ElemType base; //栈底指针
int StackSize // 栈长
}SqStack; //顺序栈的简写
1.1.2基本操作
(1)初始化
//初始化顺序栈,构造一个空栈
void InitSqStack (SqStack &S){
S.top = -1; //初始化栈顶指针
}
(2)空栈
bool StackEmpty(SqStack S){
if(s.top == -1) return true ;
else return false ;
}
(3)满栈
//判断是否为满栈
void judgeFull(SqStack &s){
if(s.top-s.base == s.StackSize){
printf("栈满!\n");
}else{
printf("栈未满!\n");
}
}
(4)入栈
bool Push(SqStack &S , ElemType x){
if(S.top == MaxSize-1) return false ;
S.data[++top] = x ;
return true ;
}
(5)出栈
bool Pop(SqStack &S,ElemType &x) {
if(S.top == -1) return false ;
x = S.data[top--] ;
return true ;
}
(6)读取栈顶元素
bool Pop(SqStack &S , ElemType &x){
if(s.top == 1)
return false;
x = S.data[top];
return true;
}
1.2链表栈
1.2.1结点结构
typedef struct SNode
{
ElemType data ;//存放栈中元素
struct SNode *next ; //栈顶指针
}SNode , *SLink; //链栈的结点
typedef struct LinkStack
{
Slink top ; //栈顶指针
int count ; //链栈结点数
}LinkStack, *SqStack; //链栈
1.2.2基本操作
(1)进栈
bool Push(LinkStck &S , ElemType x){
SLink p = (Slink*)malloc(sizeof(Slink));//给新元素分配空间
p->data = x; //新元素的值
p->next = S->top; //p的后继指向栈顶元素
S->top = p; //栈顶指针指向新的元素
S->count++; //栈中元素个数加1
return true;
}
(2)出栈
bool Pop(LinkStack *S , ElemType &x) {
if(S->top == NULL) return false ;
x = S->top->data ; //栈顶元素值
Slink p = S->top ; //辅助指针
S->top = S->top->next ; //栈顶指针后移
free(p); //释放被删除数据的存储空间
S->count-- ; //栈中元素个数减一
return true ;
}
1.3共享栈
1.3.1数据结构
#define MaxSize 100 //定义栈中元素的最大个数
typedef struct{
ElemType daata[MaxSize]; //存放栈中元素
int top1; //栈1栈顶指针
int top2; //栈2栈顶指针
}SqDoubleStack; //顺序共享栈的缩写
1.3.2基本操作
(1)进栈
bool Push(SqDoubleStack &S ,ElemType x , int stackNum){
if(S.top1+1 == S.top2)
return false; //栈满
if(stackNum == 1) //栈1有元素进栈
S.data[++top1] = x;
else(stackNum == 2) //栈2有元素进栈
S.data[--top2] =x;
return true;
}
——————————————————————————————————————————————————
——————————————————————————————————————————————————
int push(int i , elemType x){
//入栈,i为栈号,i=0表示左边的s1栈,i=1表示右边的s2栈,x是入栈元素
//入栈成功则返回1,否则返回0
if(i<0 ||i>1){
printf("栈号输入不对\n");
exit(0);
}
if(S.top1 - S.top2 = 1){
printf("栈已满\n")
exit(0);
}
switch(i){
case 1 : S.data[++top1];
return 1;
break;
case 2 : S.data[++top2];
return 1;
}
}
(2)退栈
int pop(int i){
//退栈算法,i代表栈号,i=0时s1栈,i=1时为s2栈
//退栈成功则返回退栈元素,否则返回-1
if(i<0 || i>1){
printf("栈号输入错误\n");
exit(0);
}
switch(i){
case 0:
if(top1 == -1 ){
printf("栈空\n");
exit(-1);
}
else
return S.data[top1 --];
case 1:
if(top2 == MaxSize){
printf("栈空\n");
return -1;
}
else
return S.data[top2++];
}
}
2.算法
2.1判断是否为合法序列
I为进栈,O为出栈,计算入栈出栈的次数,进行对比来判断,序列为A数组。
bool JudgeStck(char A[]){
int i=0; //记录数组的下标
int j=0; //记录入栈次数
int k=0; //出栈的次数
while(A[i] != '\0'){
switch(A[i]){
case 'I' j++ ; break; //入栈加1
case 'O' k++ ; break; //出栈加1
if(k>j)
return false;
}
i++;
}
if(j != k){
printf("非法序列\n");
return false;
}
else
printf("合法序列\n");
return true;
}
2.2链表是否中心对称
int compareStack(LinkList &L , int n){
//L是具有带头结点的带n个元素的单链表,本算法检测是否中心对车
int i; //记录栈里面的数值
char s[n/2]; //s字符栈
LNode *p = L->next; //p是工作指针,指向待处理的元素
for(i = 0 ; i<n/2 ;i++){//链表前一半入栈
s[i] = p->data;
p = p->next;
}
i--; //恢复到最后的i值
if(n%2 == 1 ) //若链表是奇数链,则后移中心点
p = p->next;
while( p!= NULL && s[i] ==p->data){
//检测是否是中心对称
i--;
p = p->next;
}
if(i == -1) //栈为空栈
return 1; //中心对称
else //非空
return 0; //中心不对称
}
2.3两个栈模仿队列:入队,出队
入队
bool Enqueue(SqStack &S1,SqStack &S2 , int x){//S1入队,S2出队
if( !JudgeFull(S1)){ //确保S1非满才能弹出
Push(S1 , x);
return 1;
}
if(JudgeFull(S1) && !StackEmpty(S2)){
printf("栈满\n");
return 0;
}
if(StackEmpty(S2) && !JudgeFull(S1) ){
while(!StackEmpty(S1)){
Pop(S1 , x);
Push(S2 ,x);
}
}
Push(S1 ,x);
return 1;
}
出队
bool DeQueue(SqStack &S1 , SqStack &S2 , int x){
if(!StackEmpty(S2)){
Pop(S2 , x);
}
else if(StackEmpty(S1)){
printf("队空\n");
}
else{
while(!StackEmpty(S1)){
Pop(S1 ,x);
Push(S2 , x);
}
Pop(S2 ,x):
}
}
2.4括号匹配
bool Check(char *str){
Stack s ;
InitStck(s) ;
int len = strlen(str) ; //字符串长度为len
for (int i = 0; i<len ; i++)
{
char a = str[i] ;
swith(a){
case '(':
case '[':
case '{':
Push(s,a) ;
break ;
case ')':
if(Pop(s) != '(' )
return false ; //出栈顶。如果不匹配直接返回不合法
break ;
case ']':
if(Pop(s) != '[' ) return false ;
break ;
case '}':
if(Pop(s) != '{' ) return false ;
break ;
}
}
if(Empty(s)) return true ;//匹配完所有括号最后要求栈中为空
else return false ;
}
2.5火车变轨换座问题
void Train_Arranger(char *train){
//用train表示火车H为硬座,S为软座
char *p = train , *q = train , c;
SqStack S;
InitStack(S);
while(*p){
if( p == 'H'){
Push(S , p); //把H存入栈中
}
else
*(q++) = *p; //把S接在前部
p++;
}
while(!StackEmty(S)){
Pop(S , c);
*(p++) = *c; //把H接在后部
}
}
非递归运算——用栈实现
struct Recursion {
int no; //保存n
int val; //保存Pn(x)值
};
struct Stack {
Recursion *arr;
int len;
int top;
};
int getP(Stack *s,int n,int x) {//该算法函数,传入栈,n和x
if (n==0) {
return 1;
}
int fv1 = 1, fv2 = 2*x;
for (int i = n; i >= 2;i--) {
//将序号入栈,从上至下,从2到n
s->top++;
s->arr[s->top].no = i;
}
while (s->top>=0) {//边出栈边计算
s->arr[s->top].val = 2 * x*fv2 - 2 * (s->arr[s->top].no - 1)*fv1;
fv1 = fv2;
fv2 = s->arr[s->top].val;
s->top--;
}
return fv2;