引言
- 文章结构:每题是由题目、解析与注意事项和代码三部分组成。在文章的结尾,记录了我的一些做题心得。
- 建议第一次写这些题目的同学可以自己先敲一下代码,然后再参考文章中的代码。
第一题
题目
题目描述
栈是计算机中经典的数据结构,简单的说,栈就是限制在一端进行插入删除操作的线性表。栈有两种最重要的操作,即pop(从栈顶弹出一个元素)和push(将一个元素进栈)。
输入
构造一个顺序栈,输入数据只有3行,第1行是一个整数n,表示顺序栈元素个数;第2行是n个整数,将这n个整数依次入栈构造顺序栈;第3行表示出栈元素个数m(m<n)。
输出
共2行,第一行为出栈前所有栈中元素,元素之间用空格分割,第二行为出栈后栈顶元素和栈的长度,以空格分割。
样例输入
5
10 20 30 40 50
2
样例输出
10 20 30 40 50
30 3
解析与注意事项
- 使用 exit() 要包含头文件 <stdlib.h>。
- 初始化栈的思路:1)栈底指针指向所分配空间的首地址(注意判断是否分配成功);2)置空栈(栈顶等于栈底);3)确定站的大小(staksize)。
- 清空栈操作:「 S.top = S.base; 」
- 判断栈是否为空直接:「 return S.top == S.base; 」即可。
- 求栈中元素个数:「 return S.top - S.base; 」
- 获取栈顶元素操作与出栈操作要先判断是否为空栈;入栈操作要先判断是否栈满(栈满要再分配存储空间,调整指针关系与栈的size)。
- 注意 :S.top 指向的是栈顶元素的下一个位置,不是栈顶元素。
代码
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h> //若用printf,scanf,getchar,putchar,gets,puts函数需包含该头文件
#include<malloc.h> //用malloc,free,realloc函数需包含该头文件
#define MAXSIZE 100
#define STACKINCREMENT 10
typedef int ElemType;
typedef struct STACK//与大话数据结构中栈的结构不同
{
ElemType *base;
ElemType *top;
int stacksize;
}SqStack;//请填写完整栈的数据结构
//函数声明
int InitStack(SqStack& s);
void ClearStack(SqStack& S);
int StackEmpty(SqStack S);
int StackLength(SqStack S);
int GetTop(SqStack s, ElemType& e);
int Push(SqStack& s, ElemType e);
int Pop(SqStack& s, ElemType& e);
//初始化,创建空栈
int InitStack(SqStack& s)
{
//请完善代码......
s.base = (ElemType*)malloc(STACKINCREMENT * sizeof(ElemType));//注意是栈底指针
if (!s.base)
{
printf("存储分配失败!\n");
return 0;
}
s.top = s.base;
s.stacksize = STACKINCREMENT;
return 1;
}
//清空栈
void ClearStack(SqStack& S)
{
//请完善代码......
S.top = S.base;
}
//判栈空
int StackEmpty(SqStack S)
{
//请完善代码......
return S.top == S.base;
}
//求栈中元素个数
int StackLength(SqStack S)
{
//请完善代码......
return S.top - S.base;
}
//获取栈顶元素值
int GetTop(SqStack s, ElemType& e)
{
//请完善代码......
if (s.top == s.base)//先判断是否为空栈
return 0;
e = *(s.top - 1);//S.top 指向的是栈顶元素的下一个位置
return 1;
}
//入栈
int Push(SqStack& s, ElemType e)
{
//请完善代码......
if (s.top - s.base >= s.stacksize)//判断是否栈满
{
s.base = (ElemType*)realloc(s.base,(s.stacksize+STACKINCREMENT) * sizeof(ElemType));
if (!s.base)
{
printf("存储分配失败!\n");
return 0;
}
s.top = s.base+s.stacksize;
s.stacksize += STACKINCREMENT;
}
*s.top = e;
s.top++;
return 1;
}
//出栈
int Pop(SqStack& s, ElemType& e)
{
//请完善代码......
if (s.top == s.base)//先判断是否为空栈
return 0;
s.top--;
e = *s.top;
return 1;
}
//打印栈中元素
void PrintElem(SqStack S)
{
//请完善代码......
int i, L = S.top - S.base;
for (i = 0; i < L;i++)
{
printf("%d ", *(S.base++));
}
}
//主函数
int main() {
ElemType e;
SqStack S;//定义一个顺序栈
int n, m;
InitStack(S);//初始化顺序栈
scanf("%d", &n);//请输入要入栈的元素个数
for (int i = 0; i < n; i++)
{
scanf("%d", &e);
Push(S, e);//入栈
}
PrintElem(S);//输出栈中元素
printf("\n");
scanf("%d", &m);//请输入要出栈的元素个数
for (int i = 0; i < m; i++)
{
Pop(S, e);//出栈
}
GetTop(S, e);//输出栈顶元素
printf("%d %d", e, StackLength(S));
return 0;
}
第二题
题目
题目描述
利用栈实现十进制与二进制、八进制、十六进制之间的转换,其中十六进制数码09,AF。
输入
输入两个数n和R,分别表示十进制数和要转换的进制(2、8或16)。
输出
转换的R进制结果。
样例输入
56 2
样例输出
111000
解析与注意事项
- 数制转换算法原理:
1)十进制数 N 和其他 D 进制数的转换遵循以下原理:
N
=
(
N
d
i
v
D
)
×
D
+
N
m
o
d
D
\boxed{N=(N div D)×D+N mod D}
N=(NdivD)×D+NmodD
(其中div为整除运算,mod为求余运算)
例如:
(
1348
)
10
=
(
2504
)
8
(1348)_{10}=(2504)_8
(1348)10=(2504)8,其运算过程如下:
N | N / 8 | N % 8 |
---|---|---|
1348 | 168 | 4 |
168 | 21 | 0 |
21 | 2 | 5 |
2 | 0 | 2 |
2)假设现要编制一个满足下列要求的程序:对于输入的任意一个非负十进制整数,输出与其等值的八进制数。由于上述计算过程是从低位到高位顺序产生八进制数的各数位,而打印输出,一般来说应从高位到低位进行,恰好和计算过程相反。因此,若将计过程中得到的八进制数的各位顺序进栈,则按出栈序列打印输出的即为与输入对应的进制数。
- 注意:十六进制中第 10 - 15 要用字母 A - F 表示。
- 用该方法转换出来的数,其实不是一个数,而是几个数的有序排列(用几个按一定顺序排列的数,来表示转换进制后所要的那个数)
代码
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h> //若用printf,scanf,getchar,putchar,gets,puts函数需包含该头文件
#include<malloc.h> //用malloc,free,realloc函数需包含该头文件
#define MAXSIZE 100
#define STACKINCREMENT 10
typedef int ElemType;
typedef struct STACK
{
ElemType* base;
ElemType* top;
int stacksize;
}SqStack;//请填写完整栈的数据结构
//函数声明
int InitStack(SqStack& s);
void ClearStack(SqStack& S);
int StackEmpty(SqStack S);
int StackLength(SqStack S);
int GetTop(SqStack s, ElemType& e);
int Push(SqStack& s, ElemType e);
int Pop(SqStack& s, ElemType& e);
//初始化,创建空栈
int InitStack(SqStack& s)
{
//请完善代码......
s.base = (ElemType*)malloc(STACKINCREMENT * sizeof(ElemType));
if (!s.base)
{
printf("存储分配失败!\n");
return 0;
}
s.top = s.base;
s.stacksize = STACKINCREMENT;
return 1;
}
//判栈空
int StackEmpty(SqStack S)
{
//请完善代码......
return S.top == S.base;
}
//求栈中元素个数
int StackLength(SqStack S)
{
//请完善代码......
return S.top - S.base;
}
//入栈
int Push(SqStack& s, ElemType e)
{
//请完善代码......
if (s.top - s.base >= s.stacksize)
{
s.base = (ElemType*)realloc(s.base, (s.stacksize + STACKINCREMENT) * sizeof(ElemType));
if (!s.base)
{
printf("存储分配失败!\n");
return 0;
}
s.top = s.base + s.stacksize;
s.stacksize += STACKINCREMENT;
}
*s.top = e;
s.top++;
return 1;
}
//出栈
int Pop(SqStack& s, ElemType& e)
{
//请完善代码......
if (s.top == s.base)
return 0;
s.top--;
e = *s.top;
return 1;
}
//数制转换函数
void conversion()
{
ElemType e;
SqStack S;
InitStack(S);
//请完善代码......
int n, R;
scanf("%d%d", &n, &R);
//将算好的数入栈
while (n) {
Push(S, n % R);//key1
n = n / R;//key2
}
//将入栈后的数出栈(先入后出)
while (!StackEmpty(S)) {
Pop(S, e);
if (e > 9)
{
printf("%c", 'A' + e - 10);//十六进制中第 10 - 15 要用字母 A - F 表示
}
else
printf("%d", e);
}
printf("\n");
}
//主函数
int main() {
conversion();
return 0;
}
做题心得
- 第一题其实不需要用到清空栈函数与判栈空函数。
- 《大话数据结构》中的栈的结构不同于题目中栈的结构(大话的是用数组实现的)。其中,数组实现的栈,由于事先固定了栈的大小,故不能扩展内存。(如果试图通过修改MAXSIZE值来改变数组长度,那么原先存在数组中的数据就会丢失。因为这不同于动态分配内存的在堆上分配内存,修改长度后原先的数据还在;若数组的长度被修改了,内存就给整个数组重新分配内存了,原先的数据就不在了。)