求解栈元素排序问题
目的:掌握栈应用的算法设计
内容:按升序对一个字符栈进行排序,即最小元素位于栈顶,最多只能使用一个额外的栈存放临时数据,并输出栈排序过程。
思路:因为没有限制排队人数,故采用链队结构,然后利用队列的基本操作实现程序的功能。
定义结构体:
#define MaxSize 9999
typedef char Elemtype; //该链栈中的元素为字符
typedef struct Stack* SqList; //将该链栈类型的指针命名为SqList
typedef struct Stack //定义链栈
{
Elemtype data; //存放栈中的数据元素
SqList next;
};
将字符串放入栈中
bool Test(SqList& s, Elemtype* str)
{
if (*str == '\0') { //如果没有输入字符
printf("请输入正确的字符串。\n");
return false;
}
InitStack(s); //建立一个链栈
int i;
for (i = 0; str[i] != '\0'; i++) {
Push(s, str[i]); //将字符串的各个元素依次入栈
}
return true;
}
算法实现
bool Sort(SqList& s)
{
if (!s) //当栈为空时无法执行算法,返回false
return false;
Elemtype e1, e2;
SqList p = NULL; //建立一个临时栈
InitStack(p);
while (!StackEmpty(s)) // s栈不空循环
{
Pop(s, e1); // 出栈元素e1
printf("\ts:出栈%c => ", e1);
while (!StackEmpty(p)) // 临时栈不空循环
{
GetTop(p, e2); // 取栈顶元素e2
printf(" p:取栈顶元素%c ", e2);
if (e2 > e1)
{
printf(" 因%c>%c ", e2, e1);
printf(" p:退栈%c ", e2);
Pop(p, e2);
printf(" s:进栈%c ", e2);
Push(s, e2);
}
else
{
printf(" 因%c<%c,退出循环 ", e2, e1);
break;
}
}
Push(p, e1);
printf(" p:进栈%c\n", e1);
}
//将临时栈中的元素按顺序全部放入原栈中
while (!StackEmpty(p))
{
Pop(p, e1);
Push(s, e1);
}
DestroyStack(p); //销毁临时栈
return true;
}
与主函数相结合
#include<stdio.h> //输入输出头文件
#include<stdlib.h> //标准头文件
#include<stdbool.h> //布尔类型头文件
#define MaxSize 9999
typedef char Elemtype; //该链栈中的元素为字符
typedef struct Stack* SqList; //将该链栈类型的指针命名为SqList
typedef struct Stack //定义链栈
{
Elemtype data; //存放栈中的数据元素
SqList next;
};
bool InitStack(SqList& s); //初始化栈
bool DestroyStack(SqList& s); //销毁栈
bool StackEmpty(SqList& s); //判断栈是否为空
bool Push(SqList& s, Elemtype e); //进栈
bool Pop(SqList& s, Elemtype& e); //出栈
bool GetTop(SqList s, Elemtype& e); //取栈顶元素
bool Test(SqList& s, Elemtype* str);//将字符串存入到一个栈中
bool Sort(SqList& s); //按升序对一个字符栈进行排序
int main(int argc, const char* argv[])
{
SqList s = NULL;
bool flag;
Elemtype e;
Elemtype str[MaxSize];
printf("请输入一个字符串:\n");
gets_s(str, MaxSize);
Test(s, str); //将字符串存入到一个栈中
flag = Sort(s); //按升序对一个字符栈进行排序
if (flag) { //若排序成功,将栈遍历
printf("排序成功!结果如下:\n");
while (!StackEmpty(s)) {
Pop(s, e);
printf(" %c", e);
}
printf("\n");
}
else
printf("排序失败!\n");
free(s); //销毁栈
return 0;
}
bool Test(SqList& s, Elemtype* str)
{
if (*str == '\0') { //如果没有输入字符
printf("请输入正确的字符串。\n");
return false;
}
InitStack(s); //建立一个链栈
int i;
for (i = 0; str[i] != '\0'; i++) {
Push(s, str[i]); //将字符串的各个元素依次入栈
}
return true;
}
bool Sort(SqList& s)
{
if (!s) //当栈为空时无法执行算法,返回false
return false;
Elemtype e1, e2;
SqList p = NULL; //建立一个临时栈
InitStack(p);
while (!StackEmpty(s)) // s栈不空循环
{
Pop(s, e1); // 出栈元素e1
printf("\ts:出栈%c => ", e1);
while (!StackEmpty(p)) // 临时栈不空循环
{
GetTop(p, e2); // 取栈顶元素e2
printf(" p:取栈顶元素%c ", e2);
if (e2 > e1)
{
printf(" 因%c>%c ", e2, e1);
printf(" p:退栈%c ", e2);
Pop(p, e2);
printf(" s:进栈%c ", e2);
Push(s, e2);
}
else
{
printf(" 因%c<%c,退出循环 ", e2, e1);
break;
}
}
Push(p, e1);
printf(" p:进栈%c\n", e1);
}
Elemtype e;
while (!StackEmpty(p))
{
Pop(p, e1);
Push(s, e1);
}
DestroyStack(p); //销毁栈
return true;
}
bool InitStack(SqList& s)
{
s = (SqList)malloc(sizeof(Stack));
//malloc有一定几率申请空间失败,此时继续申请,直到申请成功
while (!s) {
s = (SqList)malloc(sizeof(Stack));
}
s->next = NULL; //此时栈内无元素
return true;
}
bool DestroyStack(SqList& s)
{
SqList p;
p = s; //将p指向头结点
while (p) { //从头结点开始挨个释放,直到全部完成
s = s->next;
free(p);
p = s;
}
return true;
}
bool StackEmpty(SqList& s)
{
if (s->next == NULL) //当栈为空时返回“真”,否则返回“假”
return true;
else
return false;
}
bool Push(SqList& s, Elemtype e)
{
SqList p = (SqList)malloc(sizeof(Stack));
//malloc有一定几率申请空间失败,此时继续申请,直到申请成功
while (!p) {
p = (SqList)malloc(sizeof(Stack));
}
p->data = e; //把将要入栈的元素放入新的结点
p->next = s->next; //将新的结点用头插法插入
s->next = p;
return true;
}
bool Pop(SqList& s, Elemtype& e)
{
if (s->next == NULL) //当栈为空时无法出栈,返回“假”
return false;
SqList p; //p为工作指针
p = s->next; //将工作指针指向要出栈的结点
e = p->data; //记录出栈元素,通过引用参数带回
s->next = p->next; //将要出栈的结点从链栈中删除
free(p); //释放出栈的结点
return true;
}
bool GetTop(SqList s, Elemtype& e)
{
if (s->next == NULL) //当栈为空时栈内没有元素,返回“假”
return false;
e = s->next->data; //记录出栈的元素,并以引用参数带回
return true;
}