zoukankan      html  css  js  c++  java
  • 数据结构——队列,栈

    队列

    有时候,我们会遇到一些数字密码游戏,比如,给出一串数字: 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);
    View Code

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

    既然是队列,就有队首和队尾。这里引入队首变量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         }
    View Code

    运行得到测试结果:

    这串数字有什么含义呢?哈哈,这是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;
    View Code

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

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

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

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

    紧接着就是对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             }
    View Code

    因此,全部的代码如下:

     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         }
    View Code

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

     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         }
    View Code

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

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

    作者:Ribbon 出处: http://www.cnblogs.com/Ribbon/ 本文版权归作者和博客园共有,欢迎转载。未经作者同意下,必须在文章页面明显标出原文链接及作者,否则保留追究法律责任的权利。 如果您认为这篇文章还不错或者有所收获,可以点击右下角的【推荐】按钮,因为你的支持是我继续写作,分享的最大动力!
  • 相关阅读:
    npm, node, pm2 使用笔记
    没加证书的域名通过https访问,错误的访问到有证书的域名项目--已解决
    mysql数据库大表加索引
    上传大文件失败
    ifame 与父页面进行数据交互(跨域)
    windows平台编译PHP及扩展 和 踩过的坑
    vim 使用笔记
    git 在pull/push指定密钥文件
    记一次使用Xshell登陆提示所选用户密钥未在远程主机上注册
    学习网站与参考文档
  • 原文地址:https://www.cnblogs.com/Ribbon/p/4798629.html
Copyright © 2011-2022 走看看