数据结构_栈和队列

栈是仅在表尾进行插入或删除的线性表,特性是LIFO(last in first out)。

数据结构中的栈属于线性表,是顺序表的操作子集。

顺序栈代码

在这里插入图片描述

ADT

///Sqstack.h
#pragma once

#include<stdbool.h>
#include<stdio.h>
#define MAX 100  //栈最大值

//栈数据元素(更改数据元素,修改基本元素结构体和接口的实现即可)
typedef struct item{
	//数据项
	int data;

	bool operator==(const item& a) {
		return data==a.data;
	}
}Item;

typedef struct {
	Item* top;
	Item* bottom;
	int max;
}Stack;

typedef Stack* Sqstack;

//栈初始化
bool Sqstackinit(Sqstack L);

//入栈
bool Push(Sqstack L, Item e);

//出栈
bool Pop(Sqstack L, Item &e);

//栈取值
bool GetItem(const Sqstack L, Item& e);

接口实现

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

//栈初始化
bool Sqstackinit(Sqstack S) {
	S->bottom = new Item[MAX];
	if (!S->bottom)
		return false;
	S->top = S->bottom;
	S->max = MAX;
	return true;
}

//入栈
bool Push(Sqstack S, Item e) {
	if (S->top - S->bottom == S->max)
		return false;
	*S->top++ = e;
	return true;
}

//出栈
bool Pop(Sqstack S, Item& e) {
	if (S->top == S->bottom)
		return false;
	e = *--S->top;
	return true;
}

//栈取值
bool GetItem(const Sqstack S, Item& e) {
	if (!S->bottom)
		return false;
	e = *(S->top - 1);
	return true;
}

void Sqstackfree(Sqstack S) {
	if (!S->bottom);
	else {
		free(S->bottom);
		fputs("freed\n", stdout);
	}
}

测试

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

int main(int agrc, char* argv[]) {
	extern void Sqstackfree(Sqstack S);

	Item a = { 10 };
	Item a1 = { 11 };
	Item a2 = { 12 };
	Item a3,a4;
	Stack s;
	Sqstackinit(&s);
	Push(&s, a);
	Push(&s, a1);
	Push(&s, a2);
	Pop(&s, a3);
	GetItem(&s, a4);
	printf("%d\n", a4.data);
	Sqstackfree(&s);
}
/*
*vs2019输出
11
freed

D:\vs\Data_Struct\Debug\Data_Struct.exe (进程 4208)已退出,代码为 0。
按任意键关闭此窗口. . .

*/

链栈代码

在这里插入图片描述

ADT

///Lkstack.h
#pragma once

#include<stdbool.h>
#include<stdio.h>

//栈数据元素(更改数据元素,修改基本元素结构体和接口的实现即可)
typedef struct item {
	//数据项
	int data;

	bool operator==(const item& a) {
		return data == a.data;
	}
}Item;

typedef struct Stack{
	Item e;
	struct Stack* next;
}Stack, *Lkstack;

//栈初始化
bool Lkstackinit(Lkstack& L);

//入栈
bool Push(Lkstack& L, Item e);

//出栈
bool Pop(Lkstack& L, Item& e);

//栈取值
bool GetItem(const Lkstack L, Item& e);

接口实现

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

//栈初始化
bool Lkstackinit(Lkstack& L) {
	L = NULL;
	return true;
}

//入栈
bool Push(Lkstack& L, Item e) {
	Lkstack p = new Stack;
	p->e = e;
	p->next = L;
	L = p;
	return true;
}

//出栈
bool Pop(Lkstack& L, Item& e) {
	if (!L)
		return false;
	e = L->e;
	Lkstack p = L;
	L = L->next;
	delete p;
	return true;
}

//栈取值
bool GetItem(const Lkstack L, Item& e) {
	if (!L)
		return false;
	e = L->e;
	return true;
}

void Lkstackfree(Lkstack& L) {
	Lkstack p = NULL;
	while (L) {
		p = L->next;
		delete L;
		L = p;
	}
	if(!p)
		printf("freed");
}

测试

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

int main(int agrc, char* argv[]) {
	void Lkstackfree(Lkstack & L);
	Lkstack s;
	Lkstackinit(s);
	Item a = { 10 };
	Item a1 = { 11 };
	Item a2 = { 12 };
	Item a3,a4;
	Push(s, a);
	Push(s, a1);
	Push(s, a2);
	Pop(s, a3);
	GetItem(s, a4);
	printf("%d\n", a4.data);
	Lkstackfree(s);
}
/*
*vs2019输出
11
freed

D:\vs\Data_Struct\Debug\Data_Struct.exe (进程 4208)已退出,代码为 0。
按任意键关闭此窗口. . .

*/

栈的实例(进制转换和括号匹配)

实现进制转换
(修改链栈测试的代码即可实现)

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

int main(int agrc, char* argv[]) {
	void Lkstackfree(Lkstack & L);
	Lkstack s;
	Lkstackinit(s);
	
	int n = 15;
	while (n) {
		Item a = { n % 2 };
		Push(s, a);
		n /= 2;
	}
	while (s) {
		Item a;
		Pop(s, a);
		printf("%d", a.data);
	}
	printf("\n");
	Lkstackfree(s);
}
/*
1111
freed
D:\vs\Data_Struct\Debug\Data_Struct.exe (进程 1308)已退出,代码为 0。
按任意键关闭此窗口. . .

*/

实现括号匹配
(修改链栈测试的代码即可实现)

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

int main(int agrc, char* argv[]) {
	void Lkstackfree(Lkstack & L);
	Lkstack s;
	Lkstackinit(s);
	
	int flag = 1;        //匹配flag
	int flag1 = 1;		 //出错位数
	int flag2 = 0;       //无括号匹配成功情况
	printf("输入括号字符串,以#结尾\n");

	char ch;
    ch = getchar();
	while (ch != '#' && flag) {
		Item e = { ch };
		switch (ch) {
		case '{':
		case '[':
		case '(':
			Push(s, e);
			break;
		case ')':
			Item e1;
			GetItem(s, e1);
			if (s && e1.data == '(') {
				Pop(s, e1);
				++flag2;
			}
			else
				flag = 0;
			break;
		case ']':
			Item e2;
			GetItem(s, e2);
			if (s && e2.data == '[') {
				Pop(s, e2);
				++flag2;
			}
			else
				flag = 0;
			break;
		case '}':
			Item e3;
			GetItem(s, e3);
			if (s && e3.data == '{') {
				Pop(s, e3);
				++flag2;
			}
			else
				flag = 0;
			break;
		default:
			printf("the ch of %d input error\n",flag1);
			break;
		}
		ch = getchar();
		++flag1;

		if (ch == '\n') {
			ch = getchar();
			flag1 = 1;
		}
	}
	if (!s && flag && ((flag1)/2) == flag2) {
			printf("匹配成功\n");
	}
	else
		printf("匹配失败\n");

	Lkstackfree(s);
}
/*
输入括号字符串,以#结尾
safd
the ch of 1 input error
the ch of 2 input error
the ch of 3 input error
the ch of 4 input error
asdf{}
the ch of 1 input error
the ch of 2 input error
the ch of 3 input error
the ch of 4 input error
adsf{}#
the ch of 1 input error
the ch of 2 input error
the ch of 3 input error
the ch of 4 input error
匹配失败
freed
D:\vs\Data_Struct\Debug\Data_Struct.exe (进程 1316)已退出,代码为 0。
按任意键关闭此窗口. . .


输入括号字符串,以#结尾
{{{{}(){[]}}}}()#
匹配成功
freed
D:\vs\Data_Struct\Debug\Data_Struct.exe (进程 6760)已退出,代码为 0。
按任意键关闭此窗口. . .


*/

队列

队列是仅在一端插入一端删除的线性表,特性是FIFO(first in first out)。

数据结构中的队列属于线性表,是顺序表的操作子集。

顺序队列

如果使用如下操作表示的话,对于存储空间的利用率低,所以采用类似循环顺序表来实现循环队列。在这里插入图片描述
循环队列:采用取余的方式对于当前取值存储在队列位置的选择。前面说的选择顺序表的实现的话,大小为N的顺序表实现的是对N个数的队列实现,在rear结点达到最大值,而front结点也因为数据的出队列而后移,出现了从基地址开始到front结点之间空间的空闲,所以若到达rear的结点再接受数据时,考虑将这第N+1个数映射到存储空间大小为N的顺序表中,即(N+1)modN位置。这就实现了循环队列。

在这里插入图片描述

ADT

///Sqqueue.h
#pragma once

#include<stdbool.h>
#include<stdio.h>
#define MAX 100  //栈最大值

//栈数据元素(更改数据元素,修改基本元素结构体和接口的实现即可)
typedef struct item {
	//数据项
	int data;

	bool operator==(const item& a) {
		return data == a.data;
	}
}Item;

typedef struct {
	Item* base;
	int front;
	int rear;
}Queue;

//初始化
bool QueueInit(Queue& q);

//求队列长度
int Queuelen(const Queue q);

//入队
bool QueueEn(Queue& q,Item e);

//出队
bool QueueOut(Queue& q, Item &e);

//取头元素
bool GetItem(const Queue q, Item &e);

接口实现

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

//初始化
bool QueueInit(Queue& q) {
	q.base = new Item[MAX];
	if (!q.base)
		return false;
	q.front = q.rear = 0;
	return true;
}

//求队列长度
int Queuelen(const Queue q) {
	return (q.rear-q.front)%MAX;
}

//入队
bool QueueEn(Queue& q, Item e) {
	if ((q.rear + 1) % MAX == q.front)
		return false;
	q.base[q.rear] = e;
	q.rear = (q.rear + 1) % MAX;
	return true;
}

//出队
bool QueueOut(Queue& q, Item& e) {
	if (q.front==q.rear)
		return false;
	e=q.base[q.front];
	q.front = (q.front + 1) % MAX;
	return true;
}

//取头元素
bool GetItem(const Queue q, Item& e) {
	if (q.front == q.rear)
		return false;
	e = q.base[q.front];
	return true;
}

void Sqqueuefree(Queue& q) {
	if (q.base) {
		free(q.base);
		printf("freed");
	}
}

测试

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

int main(int agrc, char* argv[]) {
	extern void Sqqueuefree(Queue& q);

	Item a = { 10 };
	Item a1 = { 11 };
	Item a2 = { 12 };
	Item a3,a4;
	Queue q;
	
	QueueInit(q);
	QueueEn(q, a);
	QueueEn(q, a1);
	QueueEn(q, a2);

	
	QueueOut(q, a3);
	printf("%d\n", a3.data);
	GetItem(q, a4);
	printf("%d\n", a4.data);
	Sqqueuefree(q);
}
/*
*vs2019输出
10
11
freed
D:\vs\Data_Struct\Debug\Data_Struct.exe (进程 1848)已退出,代码为 0。
按任意键关闭此窗口. . .


*/

链式队列

在这里插入图片描述

ADT

///Lkqueue.h
#pragma once

#include<stdbool.h>
#include<stdio.h>


//栈数据元素(更改数据元素,修改基本元素结构体和接口的实现即可)
typedef struct item {
	//数据项
	int data;

	bool operator==(const item& a) {
		return data == a.data;
	}
}Item;

typedef struct Queue{
	Item e;
	struct Queue* next;
}*Lqueue;

struct Lkqueue {
	Lqueue rear;
	Lqueue front;
};

//初始化
bool QueueInit(Lkqueue& q);

//入队
bool QueueEn(Lkqueue& q, Item e);

//出队
bool QueueOut(Lkqueue& q, Item& e);

//取头元素
bool GetItem(const Lkqueue q, Item& e);

接口实现

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

//初始化
bool QueueInit(Lkqueue& q) {
	q.front = q.rear = new Queue;
	q.front->next = NULL;
	return true;
}

//入队
bool QueueEn(Lkqueue& q, Item e) {
	q.rear->e = e;

	Lqueue p = new Queue;
	p->next = NULL;
	q.rear->next = p;
	q.rear = p;
	return true;
}

//出队
bool QueueOut(Lkqueue& q, Item& e) {
	if (q.front == q.rear) {
		printf("false\n");
		return false;
	}
		
	e = q.front->e;
	
	Lqueue q1 = q.front;
	q.front = q.front->next;
	delete q1;
}

//取头元素
bool GetItem(const Lkqueue q, Item& e) {
	if (q.front == q.rear)
		return false;
	e = q.front->e;
	return true;
}

//free
void Queuefree(Lkqueue& q) {
	while (q.front) {
		Lqueue q1 = q.front;
		q.front = q.front->next;
		delete q1;
	}
	if (!q.front)
		printf("freed");
}

测试

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

int main(int agrc, char* argv[]) {
	extern void Queuefree(Lkqueue & q);

	Item a = { 10 };
	Item a1 = { 11 };
	Item a2 = { 12 };
	Item a3,a4;
	Lkqueue q;
	
	QueueInit(q);
	QueueEn(q, a);
	QueueEn(q, a1);
	QueueEn(q, a2);

	
	QueueOut(q, a3);
	printf("%d\n", a3.data);
	GetItem(q, a4);
	printf("%d\n", a4.data);
	Queuefree(q);
}
/*
*vs2019输出
10
11
freed
D:\vs\Data_Struct\Debug\Data_Struct.exe (进程 11912)已退出,代码为 0。
按任意键关闭此窗口. . .


*/

总结区别

区别

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值