数据结构3-栈的实现(C语言)

声明:栈的实现使用的是.cpp文件。

  • 由于我使用的是vs2010,vs2010的编译器不支持函数返回值bool类型,并且不能这样定义for(int i= 0; i < 10; i++),必须在函数的开头声明i=0。为了编写的方便,我使用的是.cpp文件,没有使用.c文件。虽然是c++文件,但是内容是c语言。如果有需要.c文件的,请自行修改这两个地方就可以了。

1. 栈的分类

* 物理结构的不同使得栈的种类不同
	1. 顺序结构
		1. 静态顺序栈
		2. 动态顺序栈
		* 两种实现方式:
			1. 一种是栈顶指针指向栈顶元素
			2. 另一种是栈顶指针指向栈顶元素的下一个位置
	2. 链式结构
		1. 静态链栈
		2. 动态链栈
		* 两种实现方式:
			1. 一种是带头结点
			2. 另一种是不带头结点

2. 动态链式栈的实现(不带头结点)

2.1 项目结构

在这里插入图片描述

2.2 LinkStack.h

/*
* 使用动态链表实现链式栈(不带头结点)
*/


// 1. 定义抽象数据类型
typedef struct {
	int age;
} ElemType;

// 2. 定义链式栈的结点
typedef struct LNode{
	ElemType data;
	struct LNode * next;
} LNode;

// 3. 定义一些接口

/**
* func:初始化链式栈
* @head:头指针
*/
void initStack(LNode ** head);


/**
* func:销毁链式栈
* @head:头指针
*/
bool isStackEmpty(LNode * head);


/**
* func:判断栈是否为空
* @head:头指针
*/
void destroyStack(LNode ** head);


/**
* func:向栈顶压入元素
* @head:头指针
* @x:要添加的元素
*/
bool push(LNode ** head, ElemType x);


/**
* func:弹出栈顶元素
* @head:头指针
* @x:存放要删除的元素
*/
bool pop(LNode ** head, ElemType * x);


/**
* func:查看栈顶元素
* @head:头指针
* @x:存放要查看的元素
*/
bool selectStackTopElem(LNode * head, ElemType * x);

2.3 LinkStack.cpp

#include <stdio.h>
#include <stdlib.h>
#include "LinkStack.h"

/**
* func:初始化链式栈
*/
void initStack(LNode ** head) {
	*head = NULL;
}


/**
* func判断栈是否为空
* @head:头指针
*/
bool isStackEmpty(LNode * head) {
	if (head == NULL)
		return true;
	else
		return false;
}


/**
* func:销毁链式栈
* @head:头指针
*/
void destroyStack(LNode ** head) {
	if (isStackEmpty(*head))
		return;
	LNode * t;
	while(*head != NULL) {
		t = *head;
		*head = (*head)->next;
		free(t);
	}
	*head = t = NULL;
}


/**
* func:向栈顶压入元素
* @head:头指针
* @x:要添加的元素
*/
bool push(LNode ** head, ElemType x) {
	// 先动态分配一个结点
	if (*head == NULL)
		return false;
	LNode * temp = (LNode *)malloc(sizeof(LNode));
	if (temp == NULL)
		return NULL;
	temp->data = x;
	//temp->next = NULL;
	// 再将该结点压入栈中
	temp->next = *head;
	*head = temp;
	return true;
}


/**
* func:弹出栈顶元素
* @head:头指针
* @x:存放要删除的元素
*/
bool pop(LNode ** head, ElemType * x) {
	// 判断栈是否为空
	if (isStackEmpty(*head)) 
		return false;
	// 栈不为空,则删除栈顶元素
	LNode * p = *head;
	*x = p->data;
	*head = (*head)->next;
	free(p);
	return true;
}


/**
* func:查看栈顶元素
* @head:头指针
* @x:存放要查看的元素
*/
bool selectStackTopElem(LNode * head, ElemType * x) {
	// 判断栈是否为空
	if (isStackEmpty(head)) 
		return false;
	// 栈不为空,则查看栈顶元素
	*x = head->data;
	return true;
}

2.4 main.cpp

#include <stdio.h>
#include <stdlib.h>
#include "LinkStack.h"


void main() {
	// 声明链式栈(不带头节点)
	LNode * head = NULL;
	initStack(&head);
	// 往栈中添加3个元素
	ElemType a[3] = {{11}, {12}, {13}};
	printf("初始时,栈是否为空%d\n", isStackEmpty(head));
	push(&head, a[0]);
	push(&head, a[1]);
	push(&head, a[2]);
	printf("添加了3个元素后,栈是否为空%d\n", isStackEmpty(head));
	// 依次删除栈顶两个元素
	ElemType temp;
	pop(&head, &temp);
	printf("删除的第1个元素为%d\n", temp.age);
	pop(&head, &temp);
	printf("删除的第2个元素为%d\n", temp.age);
	printf("此时,栈是否为空%d\n", isStackEmpty(head));

	// 查看栈顶元素
	selectStackTopElem(head, &temp);
	printf("此时,栈顶元素为%d\n", temp.age);
	// 销毁栈
	destroyStack(&head);
}

2.5 运行结果

在这里插入图片描述

3. 动态链式栈的实现(带头结点)

3.1 项目结构

在这里插入图片描述

3.2 LinkStack.h

/*
* 使用动态链表实现链式栈(不带头结点)
*/


// 1. 定义抽象数据类型
typedef struct {
	int age;
} ElemType;

// 2. 定义链式栈的结点
typedef struct LNode{
	ElemType data;
	struct LNode * next;
} LNode;

// 3. 定义一些接口

/**
* func:初始化链式栈
* @head:头指针
*/
void initStack(LNode ** head);


/**
* func:销毁链式栈
* @head:头指针
*/
bool isStackEmpty(LNode * head);


/**
* func:判断栈是否为空
* @head:头指针
*/
void destroyStack(LNode ** head);


/**
* func:向栈顶压入元素
* @head:头指针
* @x:要添加的元素
*/
bool push(LNode * head, ElemType x);


/**
* func:弹出栈顶元素
* @head:头指针
* @x:存放要删除的元素
*/
bool pop(LNode * head, ElemType * x);


/**
* func:查看栈顶元素
* @head:头指针
* @x:存放要查看的元素
*/
bool selectStackTopElem(LNode * head, ElemType * x);

3.3 LinkStack.cpp

#include <stdio.h>
#include <stdlib.h>
#include "LinkStack.h"

/**
* func:初始化链式栈
*/
void initStack(LNode ** head) {
	*head = (LNode *)malloc(sizeof(LNode));
	(*head)->next = NULL;
}


/**
* func判断栈是否为空
* @head:头指针
*/
bool isStackEmpty(LNode * head) {
	if (head->next == NULL)
		return true;
	else
		return false;
}


/**
* func:销毁链式栈
* @head:头指针
*/
void destroyStack(LNode ** head) {
	LNode * t;
	while(*head != NULL) {
		t = *head;
		*head = (*head)->next;
		free(t);
	}
	*head = t = NULL;
}


/**
* func:向栈顶压入元素
* @head:头指针
* @x:要添加的元素
*/
bool push(LNode * head, ElemType x) {
	// 先动态分配一个结点
	if (head == NULL)
		return false;
	LNode * temp = (LNode *)malloc(sizeof(LNode));
	if (temp == NULL)
		return NULL;
	// 再将该结点压入栈中
	temp->data = x;
	temp->next = head->next;
	head->next = temp;
	return true;
}


/**
* func:弹出栈顶元素
* @head:头指针
* @x:存放要删除的元素
*/
bool pop(LNode * head, ElemType * x) {
	// 判断栈是否为空
	if (isStackEmpty(head)) 
		return false;
	// 栈不为空,则删除栈顶元素
	LNode * p = head->next;
	*x = p->data;
	head->next = p->next;
	free(p);
	p = NULL;
	return true;
}


/**
* func:查看栈顶元素
* @head:头指针
* @x:存放要查看的元素
*/
bool selectStackTopElem(LNode * head, ElemType * x) {
	// 判断栈是否为空
	if (isStackEmpty(head)) 
		return false;
	// 栈不为空,则查看栈顶元素
	*x = head->next->data;
	return true;
}

3.4 main.cpp

#include <stdio.h>
#include <stdlib.h>
#include "LinkStack.h"


void main() {
	// 声明链式栈(不带头节点)
	LNode * head = NULL;
	initStack(&head);
	// 往栈中添加3个元素
	ElemType a[3] = {{11}, {12}, {13}};
	printf("初始时,栈是否为空%d\n", isStackEmpty(head));
	push(head, a[0]);
	push(head, a[1]);
	push(head, a[2]);
	printf("添加了3个元素后,栈是否为空%d\n", isStackEmpty(head));
	// 依次删除栈顶两个元素
	ElemType temp;
	pop(head, &temp);
	printf("删除的第1个元素为%d\n", temp.age);
	pop(head, &temp);
	printf("删除的第2个元素为%d\n", temp.age);
	printf("此时,栈是否为空%d\n", isStackEmpty(head));

	// 查看栈顶元素
	selectStackTopElem(head, &temp);
	printf("此时,栈顶元素为%d\n", temp.age);
	// 销毁栈
	destroyStack(&head);
}

3.5 运行结果

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_43546676/article/details/105974182