【数据结构】(C语言):栈

栈:

  • 线性的集合。
  • 后进先出(LIFO,last in first out)。
  • 两个指针:指向栈顶和栈底。栈顶指向最后进入且第一个出去的元素。栈底指向第一个进入且最后一个出去的元素。
  • 两个操作:入栈(往栈尾添加元素),出栈(从栈尾取出元素)。
  • 可以使用链表实现,也可以使用数组实现。本文使用双链表举例。

入栈:往栈顶(栈尾部)添加元素。

(头指针:指向第一个元素。尾指针:指向最后的元素。)

出栈:从栈顶(栈尾部)删除元素。

(头指针:指向第一个元素。尾指针:指向最后的元素。)


C语言实现(双链表):

创建节点(结构体数据类型),并创建具体节点实例的函数:

cpp 复制代码
// 节点(结构体数据类型)
typedef struct Node
{
	int value;                  // 存储数据为整数
	struct Node *next;          // 指向下一个数据的指针
	struct Node *prev;          // 指向上一个数据的指针
} LinkNode;                     // 别名LinkNode
cpp 复制代码
// 创建具体节点实例的函数
LinkNode * createNode(int data)
{
	LinkNode *node = (LinkNode *)malloc(sizeof(LinkNode));     // 分配内存空间
	if(node == NULL)
	{
		perror("Memory allocation failed");
		exit(-1);
	}
	node->value = data;
	node->prev = NULL;
	node->next = NULL;
	return node;
}

本文将头指针、尾指针和栈长度作为全局变量:

cpp 复制代码
LinkNode *header = NULL;    // 头指针,指向第一个节点,初始化为NULL
LinkNode *tail = NULL;      // 尾指针,指向最后节点,初始化为NULL
int length = 0;             // 统计栈有多少元素,初始化为0

入栈:

cpp 复制代码
// 入栈(往栈顶即尾部添加数据)
void push(int data)
{
	LinkNode *node = createNode(data);
	
	if(length == 0)      // 空栈,头指针和尾指针都指向新节点
	{
		header = node;
		tail = node;
		length++;
		return ;
	}
	
	tail->next = node;           // 原最后节点的下一个为新节点
	node->prev = tail;           // 新节点的上一个为原最后节点
	tail = node;                 // 尾指针指向新节点,即新节点为最后节点   
	length++;                    // 每添加一个元素,length+1
}

获取栈顶元素:

cpp 复制代码
int gettop(void)
{
    // 栈不为空,则栈顶元素为尾指针指向的最后节点的值
	if(length != 0) return tail->value;
}

出栈:

cpp 复制代码
int pop(void)
{
	if(length != 0)
	{
        // 获取最后节点的值
		int top = tail->value;
        // 通过最后节点的prev找到倒数第二个节点,其next指向NULL,则原倒数第二个节点为新的最后节点
		tail->prev->next = NULL;
        // 每删除一个节点,length-1
		length--;
        // 返回原最后节点的值
		return top;
	}
}

遍历栈:

cpp 复制代码
void travel(void)
{
	if(length == 0) return ;

	LinkNode *cur = header;             // 从链表头部开始遍历,直到最后
	printf("stack elements:");
	while(cur != NULL)
	{
		printf("%d \t", cur->value);
		cur = cur->next;
	}
	printf("\n");
}

完整代码:(stack**.**c)

cpp 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

/* structrue */
typedef struct Node         // node structure
{
	int value;
	struct Node *next;
	struct Node *prev;
} LinkNode;

/* global variables */
LinkNode *header = NULL;    // the header pointer
LinkNode *tail = NULL;      // the tailer pointer
int length = 0;             // the number of the stack elements

/* function prototype */
void push(int data);        // add element to the end of the stack
int pop(void);              // delete element from the end of the stack
int gettop(void);           // show element at the end of the stack
void travel(void);          // show element one by one

/* main function */
int main(void)
{
	// cycle input a number until 'q' or non-numeric, add the number to the stack
	while(1)                              // 循环输入数字,并入栈,输入q退出输入循环
	{
		int data = 0, c;
		printf("if quit,input 'q'. Input a number: ");
		c = getchar();                     // 获取输入的一个字符
		if(tolower(c) == 'q') break;       // 若输入q,则退出输入循环
		if(c < '0' || c > '9') break;      // 输入的不是数字,则退出输入循环
		while(c != '\n')	     // 若整数为多位数,通过一位一位计算最终获得多位整数
		{
			data *= 10;
			data += c - 48;      // ASCII码表中,0对应码值48
			c = getchar();
		}
		
		push(data);             // 入栈
		printf("length is %d \n", length);           // 输出栈元素个数
		travel();                                    // 遍历栈
	}

	// when stack not empty,cycle look and delete the top element until input 'n'
	if(length == 0) exit(-1);
	char k;
	printf("if you want to look and delete the top element? (y/n) ");
	scanf(" %c", &k);             // 获取输入的内容
	while(tolower(k) == 'y' && length != 0)          // 循环输入是否查看并删除栈顶元素
	{
		printf("top element is %d \n", gettop());    // 输出栈顶元素
		pop();                                       // 出栈
		printf("length is %d \n", length);           // 输出栈元素个数
		travel();                                    // 遍历栈

		printf("if you want to look and delete the top element? (y/n) ");
		scanf(" %c", &k);                            // 获取下一个输入的内容
	}
}

/* subfunction */
LinkNode * createNode(int data)         // create a node
{
	LinkNode *node = (LinkNode *)malloc(sizeof(LinkNode));
	if(node == NULL)
	{
		perror("Memory allocation failed");
		exit(-1);
	}
	node->value = data;
	node->prev = NULL;
	node->next = NULL;
	return node;
}

void push(int data)        // add element to the end of the stack
{
	LinkNode *node = createNode(data);
	
	if(length == 0)
	{
		header = node;
		tail = node;
		length++;
		return ;
	}
	
	tail->next = node;
	node->prev = tail;
	tail = node;
	length++;
}

int pop(void)              // delete element from the end of the stack
{
	if(length != 0)
	{
		int top = tail->value;
		tail->prev->next = NULL;
		length--;
		return top;
	}
}

int gettop(void)           // show element at the end of the stack
{
	if(length != 0) return tail->value;
}

void travel(void)          // show element one by one
{
	if(length == 0) return ;

	LinkNode *cur = header;
	printf("stack elements:");
	while(cur != NULL)
	{
		printf("%d \t", cur->value);
		cur = cur->next;
	}
	printf("\n");
}

编译链接: gcc -o stack stack**.**c

执行可执行文件: ./stack

相关推荐
小灰灰搞电子24 分钟前
C语言 <time.h> 头文件详解
c语言·time.h
C++ 老炮儿的技术栈2 小时前
sizeof操作符
c语言·c++·人工智能·mfc·c
wuminyu2 小时前
ForkJoinPool内部WorkQueue的Lock-Free数组操作以及并发任务窃取原理剖析
java·linux·c语言·jvm·c++
code2cat2 小时前
Java进阶篇之AtomicMarkableReference:引用还在,标记已经改变
java·开发语言·cas·并发编程·逻辑删除
CappuccinoRose2 小时前
FormData数据处理
开发语言·前端·javascript·表单数据
她说彩礼65万2 小时前
C语言 堆区和栈区
java·linux·c语言
Zguigo3 小时前
【CUDA8】第一个CUDA C++ Kernel --vector add
java·开发语言·c++
-Marks-3 小时前
【C++编程】STL容器(二)--- vector底层模拟实现(常用接口实现 | 扩容机制 | 深浅拷贝 | 迭代器失效)
开发语言·c++·vector·内存管理·迭代器失效·vector底层模拟实现
Shadow(⊙o⊙)3 小时前
C++11并发支持库
开发语言·c++
一技安身3 小时前
【java】JDK8 + JDK17 绿色解压共存方案-全程不修改任何系统环境变量
java·开发语言