数据结构——链式栈【c语言版】

 栈(stack)是一种只能在一端插入或删除操作的线性表。(既操作受限的线性表)

        栈只能在表尾插入或删除元素,表尾就是栈的栈顶,表头就是栈底

栈的主要特点:LIFO(last in first out) "后进先出"

栈可以采用顺序存储结构(顺序栈)和链式存储结构(链式栈)

既然栈可以用顺序存储结构来实现,那为什么还需要链式栈呢?

    链栈的优点是不存在栈满上溢的情况        

规定,链式栈的所以操作都是在单链表的表头进行的(因为给定链式栈以后,我们可以知道头结点的地址,在其后面插入新结点或删除首结点都很方便,且该操作的时间复杂度为O(1))

数据结构——链式栈【c语言版】_第1张图片

 

        下面是采用链式存储结构来实现的链式栈

链式栈的结点类型LinkStack声明:

typedef int ElemType;

typedef struct Node
{
	ElemType data;//存储栈的元素值(1个) 
	struct Node *next;//存储下一个元素(朝栈底方向)节点的地址 
}LinkStack;

在以s为头结点指针的链式栈中,有以下四个非常重要的要素

        1.栈空条件:s->next==NULL

        2.栈满条件:在不考虑内存溢出的情况下,一般不考虑栈满情况 

        3.进栈操作: 新建一个结点(用于存放元素e),让指针p指向它,将结点p插入到头结点之后

        4.出栈操作:  取出首结点存放的值将其删除,并释放内存

1) 链栈的初始化

        创建一个空的链栈s(实际上是创建头结点),代码如下:

LinkStack *InitStack()
{
	LinkStack *s;
	s=(LinkStack *)malloc(sizeof(LinkStack));
	s->next=NULL;
	return s;
} 

2)销毁栈

       销毁链式栈的方法与销毁单链表的操作完全相同,代码如下:

void DestroyStack(LinkStack *s)
{
	ElemType m;
	int Pop(LinkStack *s,ElemType *e);
	while(s->next!=NULL)//不空
	{
		//出栈
		Pop(s,&m); 
	} 
	free(s); 
}

3)判断栈是否为空

        判断栈是否为空是只需要判断s->next == NULL成立即可,代码如下:

int StackEmpty(LinkStack *s)
{
	if(s->next==NULL)
	{
		return 1;
	}
	else
	{
		return 0;
	}
}

如果你觉得上述代码太过于繁琐,也可以这样写:

int StackEmpty(LinkStack *s)
{
	return (s->next == NULL);
}

4)进栈(push)

        进栈,也称入栈,执行该操作需要无判断栈是否已满,因为链式栈不存在栈满操作,代码如下:

void *Push(LinkStack *s,ElemType e)
{
	LinkStack *t;
	//1.构造一个节点t,存储元素值e 
	t=(LinkStack *)malloc(sizeof(LinkStack));
	t->data=e;
	//2.把t节点添加到头节点的后面 
	t->next=s->next;
	s->next=t;
} 

5)出栈(Pop)

        出栈,也称退栈,执行该操作需要先判断栈是否为空,若栈不空,则将链式栈的首结点的数据域存储到*e,再将其删除,代码如下:

/*
若栈不空,进行相关操作,并返回1;
否则,提示,返回0 
*/
int Pop(LinkStack *s,ElemType *e)
{
	LinkStack *t; 
	if(s->next!=NULL)//不空
	{
		//1.让t指向栈顶元素节点
		t=s->next;
		//2.把栈顶元素值存储到*e中
		*e=t->data;
		//3.删除
		s->next=t->next;
		//4.释放存储空间
		free(t); 
		return 1;
	} 
	else
	{
		printf("栈空,不能出栈!\n");
		return 0;
	}
} 

6)取栈顶元素

        取栈顶元素也需要,判断栈是否为空,以确保操作合法性,代码如下:

/*
若栈不空,进行相关操作,并返回1;
否则,提示,返回0 
*/
int GetTop(LinkStack *s,ElemType *e)
{
	if(s->next!=NULL)//不空
	{
		*e=s->next->data;
		return 1;
	} 
	else
	{
		printf("栈空,不能取栈顶元素!\n");
		return 0;
	}	
}

7)输出栈



void display(LinkStack *s)
{

	while(s->next != NULL)
	{
		printf("%d",s->next->data);
		s = s->next;
	}
}

下面是入栈、退栈和取栈顶元素以及输出栈的元素的操作,代码如下:

int main()
{
	LinkStack s;
	s = *InitStack();
    Push(&s,1);
	Push(&s,2);
	Push(&s,3);
	Push(&s,4);
	Push(&s,5);
	Push(&s,6);
	Push(&s,7);
	
	ElemType *e;
	e = (ElemType *)malloc(sizeof(ElemType));
	    
	GetTop(&s,e);
 	printf("%d\n",*e);
 	Pop(&s,e);
 
 	GetTop(&s,e);
 	printf("%d\n",*e);	
 	
 	display(&s);
 	printf("\n");
 	
 	GetTop(&s,e);
 	printf("%d\n",*e); 
	return 1;
}

测试结果如下:

数据结构——链式栈【c语言版】_第2张图片

 

最后在附上完整代码:

#include 

typedef int ElemType;

typedef struct Node
{
	ElemType data;//存储栈的元素值(1个) 
	struct Node *next;//存储下一个元素(朝栈底方向)节点的地址 
}LinkStack;


/*
空:s->next==NULL 
*/

/*
1.初始化 
*/
LinkStack *InitStack()
{
	LinkStack *s;
	s=(LinkStack *)malloc(sizeof(LinkStack));
	s->next=NULL;
	return s;
} 

/*
2.销毁

*/
void DestroyStack(LinkStack *s)
{
	ElemType m;
	int Pop(LinkStack *s,ElemType *e);
	while(s->next!=NULL)//不空
	{
		//出栈
		Pop(s,&m); 
	} 
	free(s); 
}

/*
3.判断栈是否为空
若为空,返回1;
否则,返回0 
*/
int StackEmpty(LinkStack *s)
{
	if(s->next==NULL)
	{
		return 1;
	}
	else
	{
		return 0;
	}
}

/*
4.进栈
*/
void *Push(LinkStack *s,ElemType e)
{
	LinkStack *t;
	//1.构造一个节点t,存储元素值e 
	t=(LinkStack *)malloc(sizeof(LinkStack));
	t->data=e;
	//2.把t节点添加到头节点的后面 
	t->next=s->next;
	s->next=t;
} 

/*
5.出栈 
若栈不空,进行相关操作,并返回1;
否则,提示,返回0 
*/
int Pop(LinkStack *s,ElemType *e)
{
	LinkStack *t; 
	if(s->next!=NULL)//不空
	{
		//1.让t指向栈顶元素节点
		t=s->next;
		//2.把栈顶元素值存储到*e中
		*e=t->data;
		//3.删除
		s->next=t->next;
		//4.释放存储空间
		free(t); 
		return 1;
	} 
	else
	{
		printf("栈空,不能出栈!\n");
		return 0;
	}
} 

/*
6.取栈顶元素 
若栈不空,进行相关操作,并返回1;
否则,提示,返回0 
*/
int GetTop(LinkStack *s,ElemType *e)
{
	if(s->next!=NULL)//不空
	{
		*e=s->next->data;
		return 1;
	} 
	else
	{
		printf("栈空,不能取栈顶元素!\n");
		return 0;
	}	
}

/*
7.输出
从栈顶 至 栈底

*/
void display(LinkStack *s)
{

	while(s->next != NULL)
	{
		printf("%d",s->next->data);
		s = s->next;
	}
}

int main()
{
	LinkStack s;
	s = *InitStack();
    Push(&s,1);
	Push(&s,2);
	Push(&s,3);
	Push(&s,4);
	Push(&s,5);
	Push(&s,6);
	Push(&s,7);
	
	ElemType *e;
	e = (ElemType *)malloc(sizeof(ElemType));
	    
	GetTop(&s,e);
 	printf("%d\n",*e);
 	Pop(&s,e);
 
 	GetTop(&s,e);
 	printf("%d\n",*e);	
 	
 	display(&s);
 	printf("\n");
 	
 	GetTop(&s,e);
 	printf("%d\n",*e); 
	return 1;
} 

你可能感兴趣的:(数据结构,数据结构,c语言,栈)