您的位置:首页 > 理论基础 > 数据结构算法

算法入门经典之栈和队列篇

2016-07-17 01:55 357 查看
做对的事情比把事情做对重要

/**
*@author StormMaybin
*@Date 2016-07-17
*/


最近一段时间会对数据结构的知识和算法基础进行总结,尽量一天一更!如果时间错不开的话,第二天会补上。

数据结构中,栈和队列是最基础的也是简单的,一种是先进后出的线性数据结构,另外一种是先进先出的线性数据结构!

案例一:卡片游戏(队列)

题目说明:假设桌上有一叠扑克牌,依次编号为1-n(从最上面开始)。当至少还有两张的时候,可以进行操作:把第一张牌扔掉,然后把新的第一张放到整叠牌的最后。输入n,输出每次要扔掉的牌,以及最后剩下的牌。

样例输入:7

样例输出:1 3 5 7 4 2 6

分析:先开始是扔掉1,然后把2排到最后,然后扔掉3,把4排到最后······,我们会很自然的想到队列,就像排队一样,银行柜台前,第一个人先排的队,然后第一个人办完事之后第一个走······

代码实现1:

# include <stdio.h>
const int MAXN = 50;
int queue[MAXN] = {0};
int main (void)
{
int n, front, rear;
scanf ("%d",&n);
for (int i = 0; i < n; i++)
{
queue[i] = i + 1;
}
front = 0;
rear = n;
while (front < rear)
{
printf ("%d ", queue[front++]);
queue[rear++] = queue[front++];
}
return 0;
}


运行结果:



单看这个程序的输出结果,没有任何错误,答案就是我们想要的,现在让我们看看rear的值到最后是多大?



rear 的值是14,恰好是7的2倍,这么看的话,每次数组要开到2n,这就极大的浪费了内存空间。

让我们用c++的STL队列来解决这个问题。

代码实现2:

# include <cstdio>
# include <queue>
using namespace std;

queue <int> q;
int main (void)
{
int n;
scanf ("%d", &n);
for (int i = 0; i < n; i++)
{
//初始化队列
q.push(i+1);
}
while (! q.empty())
{
//打印队首元素
printf ("%d ", q.front());
//抛弃首元素
q.pop();
//把队首元素加到队尾
q.push(q.front());
//抛弃队首元素
q.pop();
}
return 0;
}


代码依旧简单,可读性也增强了不少!对于c++的STL库,不了解的可以去查查资料。

案例二:铁轨(栈)

假设有一个火车站,有n节车厢标记为1-n;现在要按照某种特定的顺序进入B铁轨驶出车站,为了重组车厢的顺序,你现在有一个中转站C(station),在中转站C里面,你可以停放任意数量的车厢,但是有一个规则就是:C的末端是封顶的,驶入C的车厢必须按照相反的顺序驶出中转站C,一旦从A->C,你就不能退回到A,同理C->B!



样例输入:5

1 2 3 4 5

5

5 4 1 2 3

6

6 5 4 3 2 1

样例输出:

Yes

No

Yes

分析:中转站C的规则其实就是栈这个数据结果的特点!

代码实现1:

/**
*@author StormMaybin
*@Date 2016-07-17
*/
# include <stdio.h>
const int MAXN = 1000 + 10;
int n, target[MAXN];

int main (void)
{
while (scanf("%d",&n) == 1)
{
int stack[MAXN];
int top = 0;
int A = 1;
int B = 1;
for (int i = 1; i <= n; i++)
{
scanf ("%d", &target[i]);
}
int ok = 1;
while (B <= n)
{
if (A == target)
{
A++;
B++;
}
else if (top && stack[top] == target[B])
{
top--;
B++;
}
else if (A <= n)
{
stack[++top] = A++;
}
else
{
ok = 0;
break;
}
}
printf ("%s\n",ok ? "Yes" : "No");
}
return 0;
}


[b]打印结果




代码原理也很简单,输出结果是Yes只有两种情况,一种是正序,一种就是逆序!

代码实现2:

接着,用c++STL库来写:

/**
*@author StormMaybin
*@Date 2016-07-17
*/
# include <cstdio>
# include <stack>
using namespace std;
const int MAXN = 1000 + 10;

int n;
int target [MAXN];

int main (void)
{
while (scanf ("%d",&n) == 1)
{
stack<int> s;
int A = 1;
int B = 1;
for (int i = 1; i <= n; i++)
{
scanf ("%d", &target[i]);
}
int ok = 1;
while (B <= n)
{
if (A == target[B])
{
A++;
B++;
}
else if (! s.empty() && s.top() == target[B])
{
s.pop();
B++;
}
else if (A <= n)
{
s.push(A++);
}
else
{
ok = 0;
break;
}
}
printf("%s\n", ok ? "Yes" : "No");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息