数据结构——队列,栈

队列

有时候,我们会遇到一些数字密码游戏,比如,给出一串数字: 4,6,8,3,5,2,2,6,0,解密规则是这样的,首先将第1个数删除,紧接着将第2个数字放到这串数的末尾,再将第3个数删除并将第4个数放到这串数的末尾,再将第5个数删除……如此往复,直到最后一个数也删除。按照刚才删除的顺序,将这些删除的数连在一起就是我们需要得到的目标数字。OK,这时候,拿出纸和笔,或者用一些小便签或者小卡片,将这9个数字分别写下来,开始模拟解密过程~

其实解密的过程就像是将这些数进行排队,每次从最前面拿两个,第1个扔掉,第2个放到末尾,如果不出意外的话,你能得到的目标数字串是:4,8,5,2,0,3,6,2,6。

在算法的世界里,没错,它就是队列,那么我们怎么用代码形式来实现它呢?

首先需要一个容器来存放这些数字,这里我们使用ArrayList,因为它的大小可以随着我们的需要而动态的增加,定义如下:

 1             ArrayList Quenum = new ArrayList();
 2             Quenum.Add(4);
 3             Quenum.Add(6);
 4             Quenum.Add(8);
 5             Quenum.Add(3);
 6             Quenum.Add(5);
 7             Quenum.Add(2);
 8             Quenum.Add(2);
 9             Quenum.Add(6);
10             Quenum.Add(0);

接下来就是模拟解密的过程了。解密的第一步是将第一个数删除,删除一个数最简单的方法是将所有后面的数都往前挪动一位,将前面的数覆盖,比如排队买票的时候,前方买好票的人离开,后面所有人就向前走一步,当然,这么做很耗费时间。

既然是队列,就有队首和队尾。这里引入队首变量head,和队尾变量tail,由于队列的原则是先进先出,因此,如果要删除一个数的话,只需要head++就可以了。而新增一个数也很简单,只需要在队尾加上即可,也就是tail++,按照这个思路,我们可以写出如下代码,代码并不复杂:

 1         public static void Queue(ArrayList num)
 2         {
 3             int head = 0;
 4             int tail = num.Count - 1;
 5             while (head < tail)
 6             {
 7                 Console.Write("{0} ", num[head]);
 8                 head++;
 9                 num.Add(num[head]);
10                 tail++;
11                 head++;
12             }
13             Console.Write("{0}", num[tail]);
14         }

运行得到测试结果:

这串数字有什么含义呢?哈哈,这是QQ群:代码之家--NET的QQ号,有兴趣的朋友们可以考虑加入哦~由于群刚建立不久,目前还没什么人呢~期待大家的到来~

题外话说完了,继续回到话题,什么是队列呢?队列是一种特殊的线性结构,它只允许在队列首部(head)进行删除操作,称为“出队”,而在队列尾部(tail)进行插入操作,称为“入队”。当队列中没有元素时(head==tail),称为空队列。队列是学习广度优先搜索及队列优化的Bellman-Ford最短算法的核心数据结构。

刚刚说到的队列是一种先进先出的数据结构,还有一种是后进先出的数据结构,叫做栈。栈限定为只能在一端进行插入和删除操作。生活中也有很多栈的例子,比如我们在吃桶装薯片的时候,要想吃掉最后一片,就必须先把前面的薯片全部吃完(假设不考虑透明“抽屉”的存在),还有平时我们能见到的弹枪,最后装入的子弹会被第一个打出去。栈的实现也很简单,上面我们用解密qq号的问题来阐述了队列,这里我们继续趣味问题之旅。

这里的例子我们用回文,回文字符串是正读反读都相同的字符序列,比如“上海自来水来自海上”,英文单词里也有不少回文单词,比如:dad, eye, madam...但是像ahah这就不算一个回文了,OK,接下来我们要如何通过栈来判断一串字符串是不是回文呢?

从回文的规则我们可以知道,如果一个字符串是回文的话,那么它必须是中间对称的,因此,我们需要求出一个中点mid,假设传入的是string类型的str,那么,中点代码即是:

1             int mid = str.Length / 2 - 1;

定义出原始的字符串,以及需要入栈操作的字符串:

1             char[] originalString = str.ToCharArray();
2             char[] stackString = new char[str.Length];

将mid之前的字符依次入栈:

1             for (int i = 0; i <= mid; i++)
2             {
3                 stackString[top] = originalString[i];
4                 top++;
5             }

紧接着就是对mid前后的字符进行对比了:

 1             for (int i = next; i < str.Length; i++)
 2             {
 3                 top--;
 4                 char x = originalString[i];
 5                 char c = stackString[top];
 6
 7                 if (originalString[i] != stackString[top])
 8                 {
 9                     break;
10                 }
11
12             }
13             if (top == 0)
14             {
15                 Console.WriteLine("{0} is Palin number.", str);
16             }
17             else
18             {
19                 Console.WriteLine("{0} is not Palin number.", str);
20             }

因此,全部的代码如下:

 1         public static void Stack(string str)
 2         {
 3             char[] originalString = str.ToCharArray();
 4             char[] stackString = new char[str.Length];
 5             int top = 0;
 6             int next;
 7             int mid = str.Length / 2 - 1;
 8             for (int i = 0; i <= mid; i++)
 9             {
10                 stackString[top] = originalString[i];
11                 top++;
12             }
13
14             if (mid % 2 == 0)
15             {
16                 next = mid + 1;
17             }
18             else
19             {
20                 next = mid + 2;
21             }
22
23             for (int i = next; i < str.Length; i++)
24             {
25                 top--;
26                 char x = originalString[i];
27                 char c = stackString[top];
28
29                 if (originalString[i] != stackString[top])
30                 {
31                     break;
32                 }
33
34             }
35             if (top == 0)
36             {
37                 Console.WriteLine("{0} is Palin number.", str);
38             }
39             else
40             {
41                 Console.WriteLine("{0} is not Palin number.", str);
42             }
43         }

当然,简单点的话,也可以这么做:

 1         private static bool PalinNumber<T>(T value)
 2         {
 3             string str;
 4             str = value.ToString();
 5             char x, y;
 6             bool flag = true;
 7             for (int i = 0; i < str.Length / 2; i++)
 8             {
 9                 x = str[i];
10                 y = str[str.Length - 1 - i];
11                 if (x != y)
12                 {
13                     flag = false;
14                 }
15             }
16             return flag;
17         }
18
19         public static void Stack<T>(T value)
20         {
21             if (PalinNumber<T>(value))
22             {
23                 Console.WriteLine("{0} is Palin number.", value);
24             }
25             else
26             {
27                 Console.WriteLine("{0} is not Palin number", value);
28             }
29         }

很多人会更乐意使用下面的方法,虽然这里第一种方法略显繁杂,但更好地体现了栈的使用方式。栈也可以用来进行验证括号的匹配,这里就不多赘述了。

简单的两个趣味题阐述简单的队列与栈的概念,也藉由此对队列和栈有一个大致的了解。

时间: 2024-07-29 15:11:55

数据结构——队列,栈的相关文章

数据结构之栈与队列

数据结构的有一个重要结构栈,栈这种数据结构就是满足先进后出的这种规则的数据结构就是栈,引用<大话数据结构>中的一个形象例子就是,子弹的弹夹,最先压入弹夹的子弹最后一个出弹夹,正好往一个栈里添加一个元素叫压栈.入栈,从栈里出来一个元素叫弹栈,出栈.指示器就叫栈帧. 栈图 现在就贴上代码: 栈的几个基本操作: #include<stdio.h> #include<stdlib.h> #include<string.h> typedef struct node{

【数据结构】栈和队列

栈和队列 容器数据结构是指一些包含了若干个其他相同或不同的数据结构的数据结构,被包含的这些每一个独立的数据结构都被称为一个元素,在一个容器中的元素往往支持相同的操作,具有类似的性质.之前说到过的线性表其实就是一种容器数据结构,本文中介绍的两种最常用的容器数据结构是栈和队列. 从功能上看,栈和队列大多用于计算过程中保存临时数据,这些数据是在计算过程中发现或产生的.在而后的计算中可能会用到这些数据.如果这些数据是固定的个数以及大小的话,可以构建几个变量来储存它们,但是如果这些数据不确定的话,就需要一

数据结构之背包,队列,栈

1:数据抽象 概念: 抽象数据类型,是一种能够对使用者隐藏数据表示的数据类型,抽象数据类型之所以重要,是因为他在程序设计上支持封装. 本节目标:本节将介绍三种抽象类型,用java实现,背包,堆栈,队列等最简单的数据结构. 背包   背包是一种不支持从中删除元素的集合数据类型.他的目的就是帮助用例手机元素并迭代遍历所有收集到的元素.API图示参考1.1 import java.util.Iterator; import java.util.NoSuchElementException; /** b

二、数据结构之栈、队列、循环队列

二.数据结构之栈.队列.循环队列 顺序栈 Stack.h 结构类型,函数声明: #ifndef _STACK_H_ #define _STACK_H_ typedef int SElementType; ///顺序栈 #define STACK_INIT_SIZE 20 #define STACK_INCREMENT 10 typedef struct { SElementType * base; SElementType * top; int stackSize;///当前栈的大小 }SqSt

线性数据结构---队列,栈 随笔

我们从四个简单但重要的概念开始研究数据结构.栈,队列,deques(双向队列), 列表是一类数据的容器,它们数据元素之间的顺序由添加或删除的顺序决定.一旦一个数据元素被添加,它相对于前后元素一直保持该位置不变.诸如此类的数据结构被称为线性数据结构. 线性数据结构有两端,有时被称为左右,某些情况被称为前后.你也可以称为顶部和底部,名字都不重要.将两个线性数据结构区分开的方法是添加和移除元素的方式,特别是添加和移除元素的位置.例如一些结构允许从一端添加元素,另一些允许从另一端移除元素. 栈 概念:栈

数据结构 之 栈与队列

栈 队列 栈的实现 顺序表实现 class Stack(object): """栈""" def __init__(self): self.__list = [] # 选用顺序表或链表 def push(self,item): """压栈""" self.__list.append(item) # 时间复杂度O(1) self.__list.insert(0,item) #头部插入,时间

基本数据结构-队列的实现及其运用

二.队列 队列是一种先进先出的数据结构,元素只能添加到队尾,而对元素的删除,修改,检索只能在队头进行.与栈的差异是很明显的.同样队列的实现可以基于链表,也可以基于数组.和栈的基本操作差不多,但队列多了一个指针(标号)指向末尾的元素,因为需要在末尾插入元素. 1.队列的链表实现 #ifndef QUEUE_H #define QUEUE_H #include <iostream> template <class T> class queue { public: queue(); ~q

数据结构—队列

数据结构-队列 1.队列的定义 队列(Queue)也是一种运算受限的线性表,它的运算限制与栈不同,是两头都有限制,插入只能在表的一端进行(只进不出),而删除只能在表的另一端进行(只出不进),允许插入的一端称为队尾(rear),允许删除的一端称为队头 (Front) 队列模型 2.队列的操作 队列的操作原则是先进先出的,所以队列又称作FIFO表(First in First out) 置空队:InitQueue(Q) 判队空:QueueEmpty(Q) 判队满:QueueFull(Q) 入队:En

Java数据结构之栈

package com.xingej.algorithm.datastructure.stack; /**  * 数据结构之栈Stack  *   * 以long类型为测试用例  *   * @author erjun 2017年12月4日 下午10:22:34  */ public class LongStack {     // 底层数据存储     private long[] arr; // 最大元素数量     private int maxSize; // 当前元素的指针     p