第4章:3.栈的链式存储结构及其实现

本篇文章参考的是《大话数据结构》,感谢作者程杰先生。

一:
栈的链式存储结构,简称链栈,

由于单链表有头指针,而栈顶指针也是必须的,所以让其合二为一即可;
如下图,把栈顶放在单链表的头部。
在这里插入图片描述

二:
对于链栈来说,基本不存在栈满的情况,除非系统内存已经满了;
对于空栈来说,链表原定义是头指针为空,那么链栈其实就是 top == NULL 的时候;

三:链栈的结构代码;

/* 链栈结构 */
typedef struct StackNode
{
    
    
    SElemType data;
    struct StackNode *next;
}StackNode,*LinkStackPtr;

typedef struct
{
    
    
    LinkStackPtr top;
    int count;
}LinkStack;

链栈的操作绝大部分都和单链表类似,只是在插入和删除上特殊一些。

四: 栈的链式存储结构–进栈操作;
对于链栈的进栈push操作,假设元素值为e的新节点是s,top为栈顶指针,
则进栈操作如下:

在这里插入图片描述

/* 插入元素e为新的栈顶元素 */
Status Push(LinkStack *S,SElemType e)
{
    
    
    LinkStackPtr s=(LinkStackPtr)malloc(sizeof(StackNode)); 
    s->data=e; 
    s->next=S->top;	/* 把当前的栈顶元素赋值给新结点的直接后继,见图中① */
    S->top=s;  		/* 将新的结点s赋值给栈顶指针,见图中② */
    S->count++;
    return OK;
}

五:栈的链式存储结构–出栈操作;
链栈的出栈pop操作,䦹简单的三句操作。
假设变量p用来存储要删除的栈顶节结点,将栈顶指针下移一位,最后释放p即可,如下:
在这里插入图片描述

/* 若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERROR */
Status Pop(LinkStack *S,SElemType *e)
{
    
     
    LinkStackPtr p;
    if(StackEmpty(*S))
    	return ERROR;
    *e=S->top->data;
    p=S->top;				/* 将栈顶结点赋值给p,见图中③ */
    S->top=S->top->next;    /* 使得栈顶指针下移一位,指向后一结点,见图中④ */
    free(p);                /* 释放结点p */        
    S->count--;
    return OK;
}

六:
链栈的进展push和出栈pop操作都很简单,没有任何循环操作,时间复杂度都是O(1).

代码:

/*
 
本篇文章参考的是《大话数据结构》,感谢作者程杰先生。

*/

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <stdlib.h>
#include <time.h>

#include "bigtalk_data_structure.h"


#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define MAXSIZE 20 /* 存储空间初始分配量 */

typedef int Status; 
typedef int SElemType; /* SElemType类型根据实际情况而定,这里假设为int */


/* 链栈结构 */
typedef struct StackNode
{
    
    
        SElemType data;
        struct StackNode *next;
}StackNode,*LinkStackPtr;


typedef struct
{
    
    
        LinkStackPtr top;
        int count;
}LinkStack;

static Status visit(SElemType c)
{
    
    
	printf("%d ",c);
	return OK;
}

/*  构造一个空栈S */
static Status InitStack(LinkStack *S)
{
    
     
	S->top = (LinkStackPtr)malloc(sizeof(StackNode));
	
	if(S->top == NULL)
	{
    
    
		return ERROR;
	}
	
	S->top = NULL;
	S->count = 0;
	return OK;
}

/* 把S置为空栈 */
static Status ClearStack(LinkStack *S)
{
    
     
	LinkStackPtr p,q;
	p = S->top;
	
	while(p != NULL)
	{
    
      
		q = p;
		p = p->next;
		free(q);
	} 
	
	S->count=0;
	
	return OK;
}

/* 若栈S为空栈,则返回TRUE,否则返回FALSE */
static Status StackEmpty(LinkStack S)
{
    
     
	if (S.count == 0)
	{
    
    
		return TRUE;
	}
	else
	{
    
    
		return FALSE;
	}
}

/* 返回S的元素个数,即栈的长度 */
static int StackLength(LinkStack S)
{
    
     
	return S.count;
}

/* 若栈不空,则用e返回S的栈顶元素,并返回OK;否则返回ERROR */
static Status GetTop(LinkStack S,SElemType *e)
{
    
    
	if (S.top == NULL)
	{
    
    
		return ERROR;
	}
	else
	{
    
    
		*e = S.top->data;
	}

	return OK;
}

/* 插入元素e为新的栈顶元素 */
static Status Push(LinkStack *S,SElemType e)
{
    
    
	LinkStackPtr s = (LinkStackPtr)malloc(sizeof(StackNode)); 
	if (s == NULL)
	{
    
    
		return ERROR;
	}
	
	s->data = e;
	
	s->next = S->top;	/* 把当前的栈顶元素赋值给新结点的直接后继,见图中① */
	S->top = s;         /* 将新的结点s赋值给栈顶指针,见图中② */
	S->count++;

	return OK;
}

/* 若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERROR */
static Status Pop(LinkStack *S,SElemType *e)
{
    
     
	LinkStackPtr p;
	
	if(StackEmpty(*S))
	{
    
    
		return ERROR;
	}
	
	*e = S->top->data;

	p = S->top;					/* 将栈顶结点赋值给p,见图中③ */
	S->top = S->top->next;    /* 使得栈顶指针下移一位,指向后一结点,见图中④ */
	free(p);                   /* 释放结点p */        

	S->count--;

	return OK;
}

static Status StackTraverse(LinkStack S)
{
    
    
	LinkStackPtr p;
	p = S.top;
	
	while(p != NULL)
	{
    
    
		visit(p->data);
		p = p->next;
	}
	printf("\n");
	
	return OK;
}

//栈:栈的链式存储结构
void test_main_4_6()
{
    
    
	printf("[%s:%d]:[yang] ******************* 我是分割线******************* \n",__FUNCTION__,__LINE__);	

	int j;
	LinkStack s;
	int e;
	
	if(InitStack(&s) == OK)
	{
    
    
		for(j = 1;j <= 10;j++)
		{
    
    
			Push(&s,j);
		}
	}

	printf("栈中元素依次为:");
	StackTraverse(s);

	printf("StackLength(s) = %d\n",StackLength(s));
	

	printf("[%s:%d]:[yang] ******************* 我是分割线******************* \n",__FUNCTION__,__LINE__);	

	Pop(&s,&e);
	printf("弹出的栈顶元素 e = %d\n",e);
	printf("StackLength(s) = %d\n",StackLength(s));



	printf("[%s:%d]:[yang] ******************* 我是分割线******************* \n",__FUNCTION__,__LINE__);	

	printf("栈空否:%d(1:空 0:否)\n",StackEmpty(s));

	printf("[%s:%d]:[yang] ******************* 我是分割线******************* \n",__FUNCTION__,__LINE__);	

	GetTop(s,&e);
	printf("栈顶元素 e = %d 栈的长度为 %d\n",e,StackLength(s));

	printf("栈中元素依次为:");
	StackTraverse(s);




	printf("[%s:%d]:[yang] ******************* 我是分割线******************* \n",__FUNCTION__,__LINE__);	

	ClearStack(&s);
	printf("清空栈后,栈空否:%d(1:空 0:否)\n",StackEmpty(s));

	#if 0
	

	#endif

}




打印:

[main:14]:[yang] ***************************************** 
[test_main_4_6:170]:[yang] ******************* 我是分割线******************* 
栈中元素依次为:10 9 8 7 6 5 4 3 2 1 
StackLength(s) = 10
[test_main_4_6:190]:[yang] ******************* 我是分割线******************* 
弹出的栈顶元素 e = 10
StackLength(s) = 9
[test_main_4_6:198]:[yang] ******************* 我是分割线******************* 
栈空否:0(1:0:)
[test_main_4_6:202]:[yang] ******************* 我是分割线******************* 
栈顶元素 e = 9 栈的长度为 9
栈中元素依次为:9 8 7 6 5 4 3 2 1 
[test_main_4_6:213]:[yang] ******************* 我是分割线******************* 
清空栈后,栈空否:1(1:0:)

猜你喜欢

转载自blog.csdn.net/yanghangwww/article/details/110847766
今日推荐