数据结构——栈

顺序栈

利用一组地址连续的存储单元依次存放自栈底到栈顶的数据元素。
① 一组地址连续的存储单元:数组;
② 附设一个栈顶指针top来动态地指示栈顶元素在顺序栈中的位置。通常以top = -1表示空栈。

进栈与出栈:
在这里插入图片描述

0、存储结构:

#define Stack_Size 50
 typedef struct
{
	StackElementType  elem[Stack_Size]; /*元素数组*/
	int  top;    /*栈顶下标*/
}SeqStack;

1、初始化:

void  InitStack(SeqStack *S) 
{ 
 	S->top = -1;
}

2、判栈空:

int IsEmpty(SeqStack *S)     
{
 	return(S->top == -1);
}

3、判栈满:

int IsFull(SeqStack *S)
{
 	return(S->top == Stack_Size - 1);
}

4、进栈:

int Push(SeqStack * S, StackElementType x)
{
	if(S->top == Stack_Size - 1)
    return(FALSE); /*栈满*/
	S->top++; 	
	S->elem[S->top] = x;
	return(TRUE);
}

5、出栈:

int Pop(SeqStack * S, StackElementType *x)
{
    if(S->top == -1) 
        return(FALSE); /*栈空*/
    else
      {
      	*x = S->elem[S->top];   
      	S->top--;    /* 修改栈顶指针 */
        return(TRUE);  
      }
}

6、取栈顶元素

int GetTop(SeqStack S, StackElementType *x)/* 取栈顶元素到x,栈顶不变 */
{
	if(S->top == -1)  
	    return(FALSE); /*栈为空*/
	else
       {	
         *x = S->elem[S->top];
         return(TRUE);
        }
}

两栈共享技术

同时使用多栈,分别分配空间会造成有些不够用,有些空闲的情况,可以多栈共享空间。
为两个栈申请一个共享的一维数组空间S[M]——双端栈
① 数组两端(0,M-1)分别作为两栈栈底;
top[0]、top[1]分别为两栈顶指示器(两栈移动相反)。

在这里插入图片描述
0、数据结构定义:

#define M 100
typedef struct
{
	 StackElementType Stack[M];
     StackElementType top[2];  
	/*top[0]和top[1]分别为两个栈顶指示器*/
}DqStack;

1、两栈共享的初始化操作算法

void InitStack(DqStack *S)
{
	S->top[0] = -1;
	S->top[1] = M;
}

2、 两栈共享的进栈操作算法

int Push(DqStack *S, StackElementType x, int i)
{
	if(S->top[0]+1 == S->top[1])
	     return(FALSE); /*栈已满*/
	switch(i)
	{
	    case 0:
	      S->top[0]++; 
	      S->Stack[S->top[0]] = x; 
	      break;
	  	case 1:
	  	  S->top[1]--; 
	  	  S->Stack[S->top[1]] = x; 
	  	  break;
		default:  return(FALSE)
 	}
	return(TRUE);
}

3、 两栈共享的出栈操作算法

int Pop(DqStack *S, StackElementType *x, int i)
{
	switch(i)
   	{
   		case 0:
   		  if(S->top[0] == -1)  return(FALSE);//判空
          *x = S->Stack[S->top[0]]; 
          S->top[0]--; 
          break;
        case 1: 
          if(S->top[1] == M)  return(FALSE); //判空
	      *x = S->Stack[S->top[1]]; 
	      S->top[1]++; break;			
	    default:  return(FALSE);
	}
	return(TRUE);
}

在这里插入图片描述
顺序栈缺点:需要预先分配空间。
① 如果数组预分配空间太小,容易造成溢出;
② 如果数组预分配空间太大,又会浪费空间;

链栈

用链表作为存储结构,不用预设栈空间大小。
为便于操作,采用带头结点单链表。
① 链表表头指针作为栈顶指针top,始终指向当前栈顶元素前面的头结点。若top->next=NULL,则代表空栈;
② 链栈在使用完毕时,应该释放其空间。
在这里插入图片描述
0、结构类型:

typedef struct node
{
	StackElementType data;
	struct node *next;
}LinkStackNode;
typedef LinkStackNode *LinkStack;

2、链栈的进栈操作:

int Push(LinkStack top, StackElementType x)
{
  	LinkStackNode * temp;
  	temp = (LinkStackNode *)malloc(sizeof(LinkStackNode));
   	if(temp == NULL)  return(FALSE);   /* 申请空间失败 */
	temp->data = x; 
	temp->next = top->next;  //头插
	top->next = temp;   /* 修改当前栈顶指针 */ 
	return(TRUE);
}

3、链栈的出栈操作:

int Pop(LinkStack top, StackElementType *x)
{  	/* 栈顶元素弹出到x中 */
     LinkStackNode * temp; 
     temp = top->next;
     if(temp==NULL)  return(FALSE);/*栈为空*/
	 top->next = temp->next; 
	 *x = temp->data;//绕过temp
     free(temp);   /* 释放存储空间 */
     return(TRUE);
}

栈的应用举例

1、数制转换:
对任意非负十进制数N,打印其等值二进制数。

void Conversion(int N)   
{
 	Stack S; int x;      /*S为顺序栈或链栈*/
    InitStack(&S);
	while(N>0)
	{
	 	x = N%2; 
	 	Push(&S, x); 
	 	N = N/2; 
	 }
	 while(!IsEmpty(S))
	 {
	 	Pop(&S, &x); 
	 	printf(%d”, x); 
	 }
}

2、 括号匹配问题
设置一个栈,扫描括号串:
① 若读入左括号,则直接入栈,等待相匹配的右括号;
② 若读入右括号,且与当前栈顶左括号匹配,将栈顶左括号出栈,否则属于不合法的情况。
如果输入序列已读尽,栈中仍有等待匹配的左括号,或者读入了一个右括号,而栈中已无等待匹配的左括号,均属不合法的情况。
当输入序列和栈同时变为空时,说明所有括号完全匹配。

void BracketMatch(char *str)
{
    Stack S; int i; char ch; 
    InitStack(&S);
    For(i=0; str[i]!='\0'; i++)
    {
        switch(str[i])
        {
            case '(': case '[': case '{':
               Push(&S,str[i]); 
               break;//逢左进栈
            case ')': case ']': case '}': //逢右出栈
	           if(IsEmpty(S))
	             {  printf("\n右括号多余!");  return;}
               else
                 {
                    GetTop (&S, &ch);
                    if(Match(ch, str[i]))
                       Pop(&S, &ch); 
                	else 
                	 { printf("\n对应的左右括号不同类!");  return;}
         }
      }
    if(IsEmpty(S))
       printf("\n括号匹配!");
    else
       printf("\n左括号多余!")
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值