栈
栈是仅在表尾进行插入或删除的线性表,特性是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。
按任意键关闭此窗口. . .
*/