数据结构(C语言实验代码实现)--第三章 栈和队列

3.1 顺序栈

#define _CRT_SECURE_NO_WARNINGS
#include
#include
#include
#include

#define StackSize 100  //栈元素最多100
typedef int DataType;

//顺序栈的存储结构
typedef struct {
	DataType data[StackSize];//存放栈元素的数组
	int top;//栈顶位置,即栈顶元素在数组中的下标
}SeqStack;

//1.顺序栈的初始化(初始化一个空的顺序栈)
void InitStack(SeqStack* S) {
	S->top = -1;
}

//2.入栈操作
int Push(SeqStack* S, DataType x) {    //把x加入到数组中

	if (S->top == StackSize - 1) {    //栈正好已经满了
		printf("栈发生上溢,入栈失败\n");
		return 0;
	}
	//否则,入栈
	S->top++;//先将top+1
	S->data[S->top] = x;//然后在top的位置填入x
	return 1;
}

//3.出栈操作
int Pop(SeqStack* S, DataType* data) {     //*data表示要出栈的元素

	if (S->top == -1) {   //栈中没有元素
		printf("栈发生下溢,出栈失败\n");
		return 0;
	}
	//否则,出栈
	*data = S->data[S->top];//用*data存储栈顶元素(要删除的元素)
	S->top--;//top下移
	return 1;
}

//4.取出栈顶元素
int GetTop(SeqStack* S, DataType* data) {   //用*data存储栈顶元素

	if (S->top == -1) {   //栈中没有元素
		printf("栈发生下溢,取栈顶元素失败\n");
		return 0;
	}
	//否则
	*data = S->data[S->top];
	return 1;
}

//5.判空操作
int Empty(SeqStack* S) {

	if (S->top == -1) {
		return 1;//栈空返回1
	}
	//否则
	return 0;
}

int main() {
	
	DataType x;
	SeqStack S;//定义结构体变量S为顺序栈类型

	InitStack(&S);//初始化顺序栈

	printf("15入栈\n");
	Push(&S, 15);

	printf("20入栈\n");
	Push(&S, 20);

	if (GetTop(&S, &x) == 1) {
		printf("当前栈顶元素是:%d\n", x);
	}

	if (Pop(&S, &x) == 1) {
		printf("执行一次出栈操作,出栈的是:%d\n", x);
	}

	if (GetTop(&S, &x) == 1) {
		printf("当前栈顶元素是:%d\n", x);
	}

	printf("请输入待入栈元素:");
	scanf("%d", &x);
	Push(&S, x);

	if (Empty(&S) == 1) {
		printf("栈为空\n");
	}
	else {
		printf("栈非空\n");
	}

	system("pause");
	return 0;
}

3.2 链栈

#define _CRT_SECURE_NO_WARNINGS
#include
#include
#include
#include

//带头结点的链栈
typedef int elemType;

//链栈的结点定义
typedef struct LinkedStackNode {

	elemType data;
	struct LinkedStackNode* next;
}LStackNode, * LStack;

//初始化链栈
LStack Init_LStack() {   //返回空栈(只有一个头结点)

	LStack top = (LStack)malloc(sizeof(LStackNode));//生成头结点,top为头指针,指向头结点

	if (top != NULL) {  //申请成功
		top->next = NULL;//头结点的next域置为空
	}

	return top;//头指针代表整个栈
}

//判空操作
int Empty_LStack(LStack top) {

	if (top->next == NULL) {
		return 1;//栈为空,返回1
	}
	else {
		return 0;
	}
}

//入栈操作(插入新的数据在栈顶)
int Push_LStack(LStack top,elemType x) {

	LStack newNode = (LStack)malloc(sizeof(LStackNode));//生成新结点
	if (newNode == NULL) {
		return 0;//申请结点空间失败
	}

	//否则
	newNode->data = x;
	newNode->next = top->next;//新结点的next域指向原来的首元结点
	top->next = newNode;//新结点变为首元结点

	return 1;
}

//出栈操作(出栈的元素为栈顶元素,即删除首元结点)
int Pop_LStack(LStack top,elemType* x) {  

	if (top->next == NULL) {
		return 0;//空栈
	}
	//否则
	LStack tempNode = (LStack)malloc(sizeof(LStackNode));//生成临时结点(用于存储栈顶元素)

	tempNode = top->next;//将首元结点赋给临时结点
	*x = tempNode->data;//*x 存储栈顶元素
	top->next = tempNode->next;//删除首元结点
	free(tempNode);//释放临时结点

	return 1;
} 

//获取栈的长度(从首元结点开始)
int Length_LStack(LStack top)
{
	int count = 0;
	while (top->next != NULL)
	{
		++count;
		top = top->next;
	}

	return count;
}

//取栈顶元素
int GetTop_LStack(LStack top,elemType* x)
{
	if (top->next!=NULL)
	{
		*x = top->next->data;
		return 1;
	}
	//否则
	return -1;
}


int main() {

	int i, t, x, a[20];
	LStack top = Init_LStack();//初始化栈

	
	printf("请依次输入5个数,开始入栈:");

	for (i = 0; i < 5; i++)
	{
		scanf("%d", &a[i]);
		Push_LStack(top, a[i]);

	}

	printf("入栈结束\n");

	printf("当前栈长为%d\n", Length_LStack(top));

	if (GetTop_LStack(top,&x) == 1) {
		printf("当前栈顶元素为:%d\n", x);
	}

	if (Pop_LStack(top, &x) == 1) {
		printf("执行一次出栈操作,出栈的是:%d\n", x);
	}

	printf("当前栈长为%d\n", Length_LStack(top));

	system("pause");
	return 0;
}

3.3 循环顺序队列

#define _CRT_SECURE_NO_WARNINGS
#include
#include
#include
#include

#define QueueSize 100   //最大长度
typedef int DataType;

//循环队列的存储结构定义
typedef struct {

	DataType data[QueueSize];//存放循环队列元素的数组
	int front;//队头元素在数组中的下标
	int rear;//队尾元素在数组中的下标
}CirQueue;

//1.循环队列的初始化(将front和rear指向数组中下标为0的位置)
void InitQueue(CirQueue* Q) {

	Q->front = Q->rear = QueueSize - 1;
}

//2.求队列的长度
int Length(CirQueue* Q) {

	return (Q->rear - Q->front + QueueSize) % QueueSize;
}

//3.入队操作(要入队的元素存放在数组的下标为rear)
int EnQueue(CirQueue* Q, DataType x) {

	if ((Q->rear + 1) % QueueSize == Q->front) {    //队列已满(上溢)
		printf("队列已满,入队失败\n");
		return 0;
	}
	//否则,入队
	Q->data[Q->rear] = x;//新元素插入队尾
	Q->rear = (Q->rear + 1) % QueueSize;//队尾在循环意义上+1(rear上移一位)
	return 1;
}

//4.出队操作(要出队的元素存放在数组的下标为front)
int DeQueue(CirQueue* Q, DataType* data) {  //*data为要出队的元素

	if (Q->rear == Q->front) {  //队列为空(下溢)
		printf("队列已空,出队失败");
		return 0;
	}
	//否则,出队
	*data = Q->data[Q->front];//保存队头元素
	Q->front = (Q->front + 1) % QueueSize;//队头位置在循环意义上+1(front上移一位)
	return 1;
}

//5.取队头元素(在数组中下标为front)
int GetHead(CirQueue* Q, DataType* data) {  //*data为队头元素

	if (Q->front == Q->rear) {
		printf("队列为空,取队头元素失败\n");
		return 0;
	}
	//否则
	*data = Q->data[Q->front];
	return 1;
}

//6.判空操作
int Empty(CirQueue* Q) {

	if (Q->rear == Q->front) {
		return 1;//队列为空返回1
	}
	else {
		return 0;
	}

}


int main() {

	DataType x;
	CirQueue Q;  //定义结构体变量Q为循环队列类型

	InitQueue(&Q);//初始化循环队列

	printf("10入队,");
	EnQueue(&Q, 10);
	printf("20入队\n");
	EnQueue(&Q, 20);

	if (GetHead(&Q, &x) == 1) {
		printf("当前队头元素是:%d\n", x);
	}

	if (DeQueue(&Q, &x) == 1) {
		printf("执行一次出队操作,出队元素是:%d\n", x);
	}

	if (GetHead(&Q, &x) == 1) {
		printf("当前队头元素是:%d\n", x);
	}

	printf("请输入入队元素:");
	scanf("%d", &x);
	EnQueue(&Q, x);

	int length = Length(&Q);
	printf("当前队列的元素个数是:%d\n",length );

	if (Empty(&Q) == 1) {
		printf("队列为空\n");
	}
	else {
		printf("队列非空\n");
	}


	system("pause");
	return 0;
}

3.4 链式队列

#define _CRT_SECURE_NO_WARNINGS
#include
#include
#include
#include

typedef int DataType;

//链队列的结点结构定义
typedef struct Node {

	DataType data;
	struct Node* next;
}Node;

//定义链队列
typedef struct {

	Node* front;//队头指针,始终指向头结点
	Node* rear;//队尾指针,始终指向尾结点
}LinkQueue;

//1.链队列的初始化(生成一个空链队列)
void InitQueue(LinkQueue* Q) {

	Node* s = (Node*)malloc(sizeof(Node));//生成头结点
	s->next = NULL;//头结点的next域为空
	Q->front = Q->rear = s;//头指针和尾指针均指向头结点
}

//2.入队操作(入队尾)
void EnQueue(LinkQueue* Q, DataType x) {

	Node* s = (Node*)malloc(sizeof(Node));//生成新结点,s指向它
	s->data = x;
	s->next = NULL;//s作为尾结点
	Q->rear->next = s;//头结点的next域指向s结点
	Q->rear = s;//尾指针变为指向s
}

//3.出队操作(首元结点所对应的元素出队)(要判断此时队列中是否只剩头结点和首元结点)
int DeQueue(LinkQueue* Q, DataType* data) {  //*data即为出队元素

	if (Q->front == Q->rear) {  //队空(下溢)
		printf("队列为空,出队失败\n");
		return 0;
	}
	//否则,出队
	Node* p = Q->front->next;//p指向首元结点(队头元素所在结点)
	*data = p->data;//存储队头元素
	Q->front->next = p->next;//头结点的next域指向首元结点的下一个结点

	if (p->next == NULL) {    //首元结点为最后一个结点
		Q->rear = Q->front;//尾指针指向头结点
	}

	free(p);//释放原来的首元结点
	return 1;
}

//4.取队头元素
int GetHead(LinkQueue* Q, DataType* data) {

	if (Q->front == Q->rear) {
		printf("队列为空,取队头元素失败");
		return 0;
	}
	//否则
	Node* p = Q->front->next;//p指向首元结点
	*data = p->data;
	return 1;
}

//5.判空操作
int Empty(LinkQueue* Q) {

	if (Q->rear == Q->front) {
		return 1;//队列为空返回1
	}
	else {
		return 0;
	}

}

//6.链队列的销毁
void Destroy(LinkQueue* Q) {

	Node* p = Q->front;//p指向头结点

	while (p != NULL) {   //依次释放链队列的结点(包括头结点)
		Node* temp = p->next;
		free(p);
		p = temp;
	}
}


int main() {
	
	DataType x;
	LinkQueue Q;//定义结构体变量Q为链队列类型

	InitQueue(&Q);//初始化链队列

	printf("10入队列,");
	EnQueue(&Q, 10);
	printf("20入队列\n");
	EnQueue(&Q, 20);

	if (GetHead(&Q, &x) == 1) {
		printf("当前队头元素是:%d\n", x);
	}

	if (DeQueue(&Q, &x) == 1) {
		printf("执行一次出队操作,出队元素是:%d\n", x);
	}

	if (GetHead(&Q, &x) == 1) {
		printf("当前队头元素是:%d\n", x);
	}

	printf("请输入入队元素;");
	scanf("%d", &x);
	EnQueue(&Q, x);

	if (Empty(&Q) == 1) {
		printf("队列为空\\n");
	}
	else {
		printf("队列不为空\n");
	}


	system("pause");
	return 0;
}

3.5 栈的应用--括号匹配

#define _CRT_SECURE_NO_WARNINGS
#include
#include
#include
#include

//用顺序栈解决括号匹配问题,每当读入一个左括号则直接入栈,等待相匹配的同类右括号;
// 每当读入一个右括号,将栈顶的左括号出栈,若与当前栈顶的左括号类型相同,则二者匹配
//直到表达式扫描完毕,若栈为空,则表达式匹配。

#define StackSize 100  //栈元素最多100
typedef char DataType;  //左括号和右括号都为char类型

//顺序栈的存储结构
typedef struct {
	DataType data[StackSize];//存放栈元素的数组
	int top;//栈顶位置,即栈顶元素在数组中的下标
}SeqStack;

//1.顺序栈的初始化(初始化一个空的顺序栈)
void InitStack(SeqStack* S) {
	S->top = -1;
}

//2.入栈操作
int Push(SeqStack* S, DataType x) {    //把x加入到数组中

	if (S->top == StackSize - 1) {    //栈正好已经满了
		printf("栈发生上溢,入栈失败\n");
		return 0;
	}
	//否则,入栈
	S->top++;//先将top+1
	S->data[S->top] = x;//然后在top的位置填入x
	return 1;
}

//3.出栈操作
int Pop(SeqStack* S, DataType* data) {     //*data表示要出栈的元素

	if (S->top == -1) {   //栈中没有元素
		printf("栈发生下溢,出栈失败\n");
		return 0;
	}
	//否则,出栈
	*data = S->data[S->top];//用*data存储栈顶元素(要删除的元素)
	S->top--;//top下移
	return 1;
}

//4.取出栈顶元素
int GetTop(SeqStack* S, DataType* data) {   //用*data存储栈顶元素

	if (S->top == -1) {   //栈中没有元素
		printf("栈发生下溢,取栈顶元素失败\n");
		return 0;
	}
	//否则
	*data = S->data[S->top];
	return 1;
}

//5.判空操作
int Empty(SeqStack* S) {

	if (S->top == -1) {
		return 1;//栈空返回1
	}
	//否则
	return 0;
}

//6.括号匹配函数
int BracketMatch(SeqStack* S, char* str) {   //字符串str存储表达式

	InitStack(S);//初始化一个空栈

	DataType e;
	int i = 0;

	while (str[i] != '\0') {   //当字符串没扫描结束
		switch (str[i]) {
			//每当读入一个左括号则直接入栈
		case '(':
			Push(S, '(');
			break;
		case '{':
			Push(S, '{');
			break;
		case '[':
			Push(S, '[');
			break;
			//每当读入一个右括号,将栈顶的左括号出栈,若与当前栈顶的左括号类型相同,则二者匹配
		case ')':
			Pop(S, &e);
			if (e != '(') {
				return 0;
			}
				break;
		case ']':
			Pop(S, &e);
			if (e != '[') {
				return 0;
			}
				break;
		case '}':
			Pop(S, &e);
			if (e != '{') {
				return 0;
			}
			break;
		default:
				break;
			}
			i++;//依次扫描表达式中每个字符
		}
	//退出while循环代表表达式扫描完成,如果此时栈为空,说明左右括号数量相等
	int y = Empty(S);
	if (y == 1) {    //栈为空
		return 1;    //匹配成功
	}
	else {
		return 0;
	}

}

int main() {

	SeqStack S;//定义结构体变量S为顺序栈类型

	char str[StackSize];//字符数组接收键盘输入的表达式

	printf("请输入表达式的字符串:");
	scanf("%s", str);

	int result = BracketMatch(&S, str);//调用括号匹配函数
	if (result == 0) {
		printf("括号匹配失败\n");
	}
	else {
		printf("括号匹配成功\n");
	}

	system("pause");
	return 0;
}

3.6 栈的应用--进制转换

#define _CRT_SECURE_NO_WARNINGS
#include
#include
#include
#include

#define StackSize 100  //栈元素最多100
typedef int DataType;

//顺序栈的存储结构
typedef struct {
	DataType data[StackSize];//存放栈元素的数组
	int top;//栈顶位置,即栈顶元素在数组中的下标
}SeqStack;

//1.顺序栈的初始化(初始化一个空的顺序栈)
void InitStack(SeqStack* S) {
	S->top = -1;
}

//2.入栈操作
int Push(SeqStack* S, DataType x) {    //把x加入到数组中

	if (S->top == StackSize - 1) {    //栈正好已经满了
		printf("栈发生上溢,入栈失败\n");
		return 0;
	}
	//否则,入栈
	S->top++;//先将top+1
	S->data[S->top] = x;//然后在top的位置填入x
	return 1;
}

//3.出栈操作
void Pop(SeqStack* S, DataType* data) {     //*data表示要出栈的元素

	if (S->top == -1) {   //栈中没有元素
		printf("栈发生下溢,出栈失败\n");
		return;
	}
	//否则,出栈
	*data = S->data[S->top];//用*data存储栈顶元素(要删除的元素)
	S->top--;//top下移
}

//4.判空操作
int Empty(SeqStack* S) {

	if (S->top == -1) {
		return 1;//栈空返回1
	}
	//否则
	return 0;
}

//5.数制转换函数
void conversion(int num,int M) {   //将10进制数num转换为M进制

	//初始化空栈
	SeqStack S;
	InitStack(&S);

	int x;

	while (num != 0) {   

		Push(&S, num % M);  //将num取模后的M进制数入栈
		num = num / M;//num更新
		
	}
	//取模完成后,依次弹出栈顶元素,得到结果
	while (Empty(&S) != 1) {  //栈非空
		Pop(&S,&x);
		printf("%d", x);
	}
	puts("");
}

int main() {

	int num;
	int M;

	printf("请输入要转换的数:");
	scanf("%d", &num);

	printf("你要将它转换为几进制:");
	scanf("%d", &M);

	printf("将%d转换为%d进制后的结果为:",num,M);
	conversion(num, M);

	system("pause");
	return 0;
}

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