数据结构与算法整理4——栈及其操作(C语言)

数据结构与算法整理4——栈及其操作(C语言)

目录

数据结构与算法整理4——栈及其操作

1、栈的基本概念与特点

2、栈的两种存储结构的基本操作,如何入栈,出栈,判空

3、栈的应用举例(进制转换,递归,迷宫,表达式求值等)

4、栈相关的几个例题

5、栈的操作代码实现(C语言)

(1)入栈问题:

(2)顺序存储方式的栈的操作

(3)链式存储方式的栈的操作


1、栈的基本概念与特点

栈和队列也是线性表,只是操作受限制的线性表,他们线性表的区别在于线性表可以在在任意位置插入或删除元素,而栈只能在栈顶操作,队列只能在队尾操作。

1.1栈的特点:后进先出(LIFO)可看做装电池,只能对栈顶进行操作。

1.2存储方式:顺序存储和链式存储。

        

   有n个元素的栈的顺序存储                                  栈的链式存储

 

2、栈的两种存储结构的基本操作,如何入栈,出栈,判空

操作

存储方式类型

顺序栈

链式栈

定义数据类型

Typedef struct{

 Int stack[maxsize];

 Int top;

}sequencestack;

Typedef struct snode{

  Int  data;

  Int  snode  *next;

}singlelinkednode;

初始化

S->top=0;

 

取栈顶

*d=S.stack[S.top-1];

 

Singlelinkednode *p=head->next;

*d=p->data;

入栈

S->stack[S->top]=x;

S->top++;

移动top指针

Singlelinkednode *p;

p->data=x;

p->next=head->next;//先执行

head->next=p;      //后执行

出栈

S->top--;

直接移动top指针,不用删除原栈顶

head->next=head->next->next;

free(p);//需要释放出栈的元素

判空

if(S->top==0)

   printf(“stack is empty”);

If(head->next==null)

   Printf(“stack is empty”);

 

3、栈的应用举例(进制转换,递归,迷宫,表达式求值等)

栈的应用

内容

进制转换

算法原理:辗转相除法算法公式:N=(N div 2) * 2 +N mod 2

递归

 

迷宫

 

表达式求值

例1:A+(B-C/D)*E(也称为中缀表达式)

前缀表达式为:+A*-B/CDE  即运算符在数值前面

后缀表达式为:ABCD/-E*+ 运算符在数值后面

例2:[(a+b)+c*(d+e)+f]*(g+h)

前缀表达式为:*++ab*+cdeg+gh

后缀表达式为:ab+cde+*+f+gh+*

 

4、栈相关的几个例题

 

 

5、栈的操作代码实现(C语言)

(1)入栈问题:

#include "stdio.h"
#include "stdlib.h"

typedef struct stack{
	int data;
	struct stack *next; 
}Lstack,*LinkStrack;   //Lstrack表示链式栈中结点的类型, LinkStrack是申明了一个指向节点的指针数据类型 


int  pushstrack(LinkStrack head,int n){       //将元素n压入栈     此时head指的是直接指向栈顶的头结点 
	LinkStrack p=(Lstack *)malloc(sizeof(Lstack));     //创建一个新的节点  
	if(p==NULL){
		printf("内存不足,无法入站");
		return 0;
	}
		p->data=n;
		p->next=head->next;      //让p结点成为栈顶        
		head->next=p;          //把head结点的指针指向新的栈顶p 保持head始终指向最新的栈顶 
		return 1;            
}

int gettop(LinkStrack top){
	return top->data; 
}

int main(){
	LinkStrack S;
	int e;
	//InitialStack(S);
	pushstrack(S,13);
	pushstrack(S,93);
	pushstrack(S,80);
	printf("栈顶元素为:%d\n",gettop(S));
	return 1; 
	} 

(2)顺序存储方式的栈的操作

#include "stdio.h"
#include "stdlib.h"
//顺序存储的栈的应用
#define  maxsize 30
//定义栈的结构体 
 struct  stack
 {
 	int top;
	int stack[maxsize];
  };              //pseqstack S 相当于 stack *S 
typedef  struct  stack *pseqstack;
//创建一个栈
pseqstack CreatStack(void){
	pseqstack s=(pseqstack)malloc(sizeof(struct  stack));
	if(s==NULL)
		printf("溢出!!");
	else
		s->top=0;
	return s; 
} 

//进栈(先进后出)
void pushstack(pseqstack s,int n){
	if(s->top>=maxsize)
	{
		printf("栈已满,无法插入!");
	}
	else 
	{	
		s->top++;	 //top上移  s->top指的是栈顶的位置   注意两者顺序 
		s->stack[s->top]=n;  //把栈顶的位置的值放入n  
	

	 } 
} 
   
//删除栈顶(出栈)
int popstack(pseqstack s,int e){
 	if(s->top<0)
	{
		printf("栈已空,无法删除!");
		return 0; 
	}
	else
	{
	
		e=s->stack[s->top];   //注意两者顺序 
		s->top--;	//直接把top向下移一个单位,被删除的栈点(原栈顶)存储位置没有变没有被释放  
		printf("取出的元素为%d",e); 
		return 1;
	 } 
} 

//取出栈顶的元素
int  gettopele(pseqstack s){
	return s->stack[s->top];
} 
 
 
//main测试函数
main(){
	pseqstack S;
	int e;
	//Initialstack(S);
	S=CreatStack();
	pushstack(S,11);
	pushstack(S,23);
	printf("栈顶元素为:%d",gettopele(S));
	popstack(S, e);

} 

(3)链式存储方式的栈的操作

#include "stdio.h"
#include "stdlib.h"

typedef struct stack{
	int data;
	struct stack *next; 
}Lstack,*LinkStrack;   //Lstrack表示链式栈中结点的类型, LinkStrack是申明了一个指向节点的指针数据类型 

void InitialStack(Lstack * * head){                 //初始化带头结点的链式栈 但是 Lstack * * head是什么意是呢? 
	if((*head=(Lstack *)malloc(sizeof(Lstack)))==NULL){
		exit(1);
	}
	(*head)->next=NULL;
} 

//入栈 
LinkStrack pushstrack(LinkStrack top,int n){   //将元素n压入栈     此时top指的是直接指向栈顶的指针 
	LinkStrack temp=(Lstack *)malloc(sizeof(Lstack));  //创建一个新的节点 
	if(temp==NULL){
		printf("内存不足,无法入站");
		return 0;
	}
		temp->data=n;
		temp->next=top;           //把栈顶指针指向新入栈的元素 
		top=temp;
		return top;             //返回栈顶指针 
}

//入栈方法二 
//int  pushstrack(LinkStrack head,int n){       //将元素n压入栈     此时head指的是直接指向栈顶的头结点 
//	LinkStrack p=(Lstack *)malloc(sizeof(Lstack));     //创建一个新的节点  
//	if(p==NULL){
//		printf("内存不足,无法入站");
//		return 0;
//	}
//		p->data=n;
//		p->next=head->next;      //让p结点成为栈顶        
//		head->next=p;          //把head结点的指针指向新的栈顶p 保持head始终指向最新的栈顶 
//		return 1;            
//}


//出栈  方法一 可以成功 
//LinkStrack popstack(LinkStrack top,int e){
//	LinkStrack temp;
//	if(top==NULL)
//	{
//		printf("error\n");
//		return NULL;
//	}
//	e=top->data;                 //将栈顶元素返回给e 
//    temp=top;                //将栈顶指针暂时存放在temp指针里面,使temp指针也指向栈顶 
//    top=temp->next;           //temp->next的值是原栈顶的下面一个元素的data域的地址,所以 top=temp->next就是把top指向原栈顶的下一个元素的data域,由此打到出栈的目的 
//	free(temp);                  //释放中间指针temp  但是没有释放掉原栈顶 
//	printf("栈顶元素为:%d\n",top->data);
//	return top;	
//} 

//出栈方法二 
int  popstack(Lstack *head,int e){  //head是头指针,指向栈顶 
	LinkStrack  p=head->next;           //p就是head->next是原栈顶 
	if(p==NULL)
	{
		printf("error\n");
		return NULL;
	}
	e=p->data;                 //将栈顶元素返回给e 
	printf("栈顶元素为:%d\n",e);        
    head->next=p->next;            //将头指针指向原栈顶的下一个元素的data域 
	free(p);                  //释放原栈顶的内存p 
	return 1;	
} 
//取栈顶元素 
int gettop(LinkStrack top){
	return top->data; 
}

int main(){
	LinkStrack S;
	int e;
	//InitialStack(S);
	S=pushstrack(S,13);
	S=pushstrack(S,93);
	S=pushstrack(S,80);
	printf("栈顶元素为:%d\n",gettop(S));
	popstack(S,e);
	printf("栈顶元素为:%d\n",gettop(S));
	return 1;	
}
 


版权声明:本文为weixin_40695088原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。