• 启迪思维:链式队列


    最近校长火了,微博上各种讽刺校长这个职位信息,还有各种公知转发这些微博(他们无非想说明自己有多么正直,鬼知道背后都干啥)更有可耻人借此炒作。其实根据各种新闻来看,猥琐少女人有企业高管、校长等等人,我们只能谴责这些心理变态的人(让哪些为恶的人下地狱),不能因此讽刺校长这个职位,这个就和有些无良媒体报道有搞IT加班累死(个人观点IT公司里累死的兄弟,应该是不懂调整心态),就判断搞IT是高危行业一样,事实上高危行业应该是挖煤、黑砖厂等等。上周参加一个公益性质的活动,就认识一个很了不起的校长(收养100的个孤儿),我自己小学校长也是非常好的人,可悲的是初中校长因贪污被双规。 

     

    最近网上一贴郭美美的余额短信有闪现我等屌丝的太极眼,其实这个新闻很早都有,是新华社发出,最近因为营销的需要又被炒作起来,腾讯客户端及搜狐客户端都放在头版头条,稍微有点知识的人都知道这是个假新闻,这篇新闻后面全是推销施华洛世奇女鞋的。普通网民只重视情绪,从不管事实,这样就被营销者利用了很成功。这个仅仅是为营销,还更多是坑爹甚至坑爷的新闻,坑着那些不懂得过滤这些垃圾信息的人。

     

    在网络每天都有类似这样假新闻、骗人的广告、公知的装逼(还有电视里各种广告,每次家里亲戚都问是不是真),学习过滤垃圾信息非常重要(多问、多看、多思考),坚持一到两年,就能有很好过滤信息能力(个人觉得过滤垃圾信息是搞IT人一个基本能力)平时也多和家里的亲戚说说,避免他们上当受骗。瞎扯的有点多了,下面进入正题

     

    上一篇博客分析栈的相关知识和分析用数组的方式实现队列(循环顺序队列),循环顺序队列在内存中的存储位置是连续的,且编译器要求我们在编译期就要确定队列的大小,这样对于多数应用都不能很好的确定初始值(设置过大导致浪费内存,设置过小导致频繁分配造成大量内存碎片),使用了链表来实现队列,链表中的元素存储在不连续的地址,由于是动态申请内存(也会造成内存碎片),由于每个节点占用的内存空间一样并且很小,可以用内存池(boostpool)避免频繁向系统申请和释放内存,基于上面的原因很多开源项目对栈的实现都是链式队列。

     

    一、示例图

     链表队列例图

    二:代码分析

    1、节点入队

    过程如示例图:
    入队列例图

    代码分析:

     1 /**
     2  * 节点入队列
     3  */
     4 void EnQueue(const value_type& value){
     5     //创建一个新节点
     6     LNode<T> *p = new LNode<T>(value);
     7 
     8     //判断队列是否为空,如果为空直接赋值给front,back
     9     if(IsEmpty()){
    10         back = front = p;
    11     }else{
    12         //不为空:入口指针指向新的节点
    13         back->next = p;
    14         //改变入口指针为新创建的节点
    15         back = p;
    16     }
    17 
    18 }

    2、节点出队

    过程如示例图:

     出队列例图

    代码分析:

    1 void DeQueue(){
    2     //如果队列不为空,则出队列
    3     if(!IsEmpty()){
    4         //释放删除节点占用内存,更多关于auto_ptr知识,请阅读memory里auto_ptr源码
    5         std::auto_ptr<LNode<T> > new_prt(front);
    6         //修改队列出口指针指向下一个节点
    7         front = front->next;
    8     }
    9 }

    3、获取队列入口和出口元素:

    可以看到在队列类中,GetFrontGetBack函数是发生重载了,而且是合法的。而且在调用时,只用队列类的const对象才能调用const版本的GetFrontGetBack函数,理论而非const对象可以调用任意一种,通常非const对象调用非const版本的GetFrontGetBack函数。 

    具体原因:按照函数重载的定义,函数名相同而形参表有本质不同的函数称为重载。在队列类中,由于隐含的this形参的存在,const版本的函数GetFrontGetBack使得作为形参的this指针的类型变为指向const对象的指针,而非const版本的使得作为形参的this指针就是正常版本的指针。此处是发生重载的本质。重载函数在最佳匹配过程中,对于const对象调用的就选取const版本的成员函数,而普通的对象调用就选取非const版本的成员函数,具体的测试请参考test1和test2函数,代码如下

     1 /**
     2  *获取队列出口元素
     3  */
     4 reference GetFront(){
     5     std::cout<<"GetFront reference"<<std::endl;
     6     return front->data;
     7 }
     8 /**
     9  *获取队列出口元素
    10  */
    11 const_reference GetFront() const{
    12     std::cout<<"GetFront const_reference"<<std::endl;
    13     return front->data;
    14 }
    15 /**
    16  *获取队列入口元素
    17  */
    18 reference GetBack(){
    19     std::cout<<"GetBack reference"<<std::endl;
    20     return back->data;
    21 }
    22 /**
    23  *获取队列入口元素
    24  */
    25 const_reference GetBack() const{
    26     std::cout<<"GetBack const_reference"<<std::endl;
    27     return back->data;
    28 }

    4、清空队列

     1 /**
     2  *清空队列并回收资源
     3  */
     4 void Clear(){
     5     //循环判断队列是否为空
     6     while(!IsEmpty()){
     7         //节点出对并回收资源
     8         this->DeQueue();
     9     }
    10 }

    5、判断队列是否为空

    1 /**
    2  * 判断队列是否为空
    3  */
    4 bool IsEmpty() const{
    5     return front == 0;
    6 }

    6、计算队列长度

     1 /**
     2  *计算机队列大小
     3  */
     4 size_t GetSize() const{
     5 
     6     size_t size = 0;
     7     //获取队列出口
     8     LNode<T> *p = front;
     9     //循环整这个栈大小,当栈==0,表示栈已经遍历完成
    10     while(p != 0){
    11         ++size;
    12         //指向下一个栈节点
    13         p = p->next;
    14     }
    15 
    16     return size;
    17 }

    7、运行结果

     测试队列各方法示例图:

     测试队列各方法例图

     测试const函数重载示例图:

     测试const重载例图

     测试代码如下:

     1 /**
     2  * 测试队列各种方法
     3  */
     4 void test(){
     5     T e;
     6     std::cout<<"-----------EnQueue queue begin------------"<<std::endl;
     7     for(size_t i = 1; i < 5; ++i){
     8         EnQueue(i);
     9         e = GetBack();
    10         std::cout<<"e is value = "<<e<<"\n";
    11     }
    12     std::cout<<"-----------EnQueue queue end------------"<<std::endl;
    13 
    14     std::cout<<"frist queue length="<<GetSize()<<std::endl;
    15 
    16     std::cout<<"-----------DeQueue queue begin------------"<<std::endl;
    17 
    18     for(size_t i = 1; i < 3; ++i){
    19         e = GetFront();
    20         DeQueue();
    21         std::cout<<"e is value = "<<e<<"\n";
    22     }
    23     std::cout<<"-----------DeQueue queue end------------"<<std::endl;
    24 
    25     std::cout<<"-----------GetFront queue begin------------"<<std::endl;
    26 
    27     T  ee = GetFront();
    28 
    29     std::cout<<"ee is value = "<<ee<<"\n";
    30 
    31     std::cout<<"-----------GetFront queue end------------"<<std::endl;
    32 
    33     std::cout<<"secend queue size="<<GetSize()<<std::endl;
    34     Clear();
    35     std::cout<<"third queue size="<<GetSize()<<std::endl;
    36 }
    37 
    38 /**
    39  *测试const函数重载
    40  */
    41 void test1() {
    42     T e;
    43     std::cout<<"-----------method non const GetBack queue begin------------"<<std::endl;
    44     for(size_t i = 1; i < 2; ++i){
    45         EnQueue(i);
    46         e = GetBack();
    47         std::cout<<"e is value = "<<e<<"\n";
    48     }
    49     std::cout<<"-----------method non const GetBack queue end------------"<<std::endl;
    50 
    51     std::cout<<"-----------method non const GetBack const queue begin------------"<<std::endl;
    52     T const ee = GetBack();
    53     std::cout<<"e is value = "<<ee<<"\n";
    54     std::cout<<"-----------method non const GetBack const queue end------------"<<std::endl;
    55 }
    56 
    57 /**
    58  *测试const函数重载
    59  */
    60 void test2() const {
    61     T e;
    62     std::cout<<"-----------method const GetBack queue begin------------"<<std::endl;
    63     for(size_t i = 1; i < 2; ++i){
    64         e = GetBack();
    65         std::cout<<"e is value = "<<e<<"\n";
    66     }
    67     std::cout<<"-----------method const GetBack queue end------------"<<std::endl;
    68 
    69     std::cout<<"-----------method const GetBack const queue begin------------"<<std::endl;
    70     T const ee = GetBack();
    71     std::cout<<"e is value = "<<ee<<"\n";
    72     std::cout<<"-----------method const GetBack const queue end------------"<<std::endl;
    73 }
    View Code

    8、完整代码

    LinkQueue.h 如下:

      1 /*
      2  * ListQuene.h
      3  *
      4  *  Created on: May 16, 2013
      5  *      Author: sunysen
      6  */
      7 
      8 #ifndef LISTQUENE_H_
      9 #define LISTQUENE_H_
     10 #include "core/node/LNode.h"
     11 /**
     12  *基于链表实现的队列
     13  */
     14 template <class T>
     15 class LinkQueue{
     16 private:
     17     LNode<T> *front;//出队口指针
     18     LNode<T> *back;//入队口指针
     19 
     20     typedef T& reference;//引入STL里边萃取概率,在目前的别名仅有的作用便于理解
     21     typedef const T&  const_reference;//引入STL里边萃取概率,在目前的别名仅有的作用便于理解
     22     typedef T value_type;//引入STL里边萃取概率,在目前的别名仅有的作用便于理解
     23 public:
     24     /**
     25      * 构造函数,初始化入队和出队指针
     26      */
     27     LinkQueue():front(0),back(0){
     28     }
     29 
     30     /**
     31      *析构函数,离开作用域回收资源
     32      */
     33     ~LinkQueue(){
     34         Clear();
     35     }
     36 
     37     /**
     38      *清空队列并回收资源
     39      */
     40     void Clear(){
     41         //循环判断队列是否为空
     42         while(!IsEmpty()){
     43             //节点出对并回收资源
     44             this->DeQueue();
     45         }
     46     }
     47     /**
     48      *获取队列出口元素
     49      */
     50     reference GetFront(){
     51         std::cout<<"GetFront reference"<<std::endl;
     52         return front->data;
     53     }
     54     /**
     55      *获取队列出口元素
     56      */
     57     const_reference GetFront() const{
     58         std::cout<<"GetFront const_reference"<<std::endl;
     59         return front->data;
     60     }
     61     /**
     62      *获取队列入口元素
     63      */
     64     reference GetBack(){
     65         std::cout<<"GetBack reference"<<std::endl;
     66         return back->data;
     67     }
     68     /**
     69      *获取队列入口元素
     70      */
     71     const_reference GetBack() const{
     72         std::cout<<"GetBack const_reference"<<std::endl;
     73         return back->data;
     74     }
     75 
     76     /**
     77      * 节点入队列
     78      */
     79     void EnQueue(const value_type& value){
     80         //创建一个新节点
     81         LNode<T> *p = new LNode<T>(value);
     82 
     83         //判断队列是否为空,如果为空直接赋值给front,back
     84         if(IsEmpty()){
     85             back = front = p;
     86         }else{
     87             //不为空:入口指针指向新的节点
     88             back->next = p;
     89             //改变入口指针为新创建的节点
     90             back = p;
     91         }
     92 
     93     }
     94 
     95     void DeQueue(){
     96         //如果队列不为空,则出队列
     97         if(!IsEmpty()){
     98             //释放删除节点占用内存,更多关于auto_ptr知识,请阅读memory里auto_ptr源码
     99             std::auto_ptr<LNode<T> > new_prt(front);
    100             //修改队列出口指针指向下一个节点
    101             front = front->next;
    102         }
    103     }
    104     /**
    105      * 判断队列是否为空
    106      */
    107     bool IsEmpty() const{
    108         return front == 0;
    109     }
    110     /**
    111      *计算机队列大小
    112      */
    113     size_t GetSize() const{
    114 
    115         size_t size = 0;
    116         //获取队列出口
    117         LNode<T> *p = front;
    118         //循环整这个栈大小,当栈==0,表示栈已经遍历完成
    119         while(p != 0){
    120             ++size;
    121             //指向下一个栈节点
    122             p = p->next;
    123         }
    124 
    125         return size;
    126     }
    127     /**
    128      * 测试队列各种方法
    129      */
    130     void test(){
    131         T e;
    132         std::cout<<"-----------EnQueue queue begin------------"<<std::endl;
    133         for(size_t i = 1; i < 5; ++i){
    134             EnQueue(i);
    135             e = GetBack();
    136             std::cout<<"e is value = "<<e<<"\n";
    137         }
    138         std::cout<<"-----------EnQueue queue end------------"<<std::endl;
    139 
    140         std::cout<<"frist queue length="<<GetSize()<<std::endl;
    141 
    142         std::cout<<"-----------DeQueue queue begin------------"<<std::endl;
    143 
    144         for(size_t i = 1; i < 3; ++i){
    145             e = GetFront();
    146             DeQueue();
    147             std::cout<<"e is value = "<<e<<"\n";
    148         }
    149         std::cout<<"-----------DeQueue queue end------------"<<std::endl;
    150 
    151         std::cout<<"-----------GetFront queue begin------------"<<std::endl;
    152 
    153         T  ee = GetFront();
    154 
    155         std::cout<<"ee is value = "<<ee<<"\n";
    156 
    157         std::cout<<"-----------GetFront queue end------------"<<std::endl;
    158 
    159         std::cout<<"secend queue size="<<GetSize()<<std::endl;
    160         Clear();
    161         std::cout<<"third queue size="<<GetSize()<<std::endl;
    162     }
    163 
    164     /**
    165      *测试const函数重载
    166      */
    167     void test1() {
    168         T e;
    169         std::cout<<"-----------method non const GetBack queue begin------------"<<std::endl;
    170         for(size_t i = 1; i < 2; ++i){
    171             EnQueue(i);
    172             e = GetBack();
    173             std::cout<<"e is value = "<<e<<"\n";
    174         }
    175         std::cout<<"-----------method non const GetBack queue end------------"<<std::endl;
    176 
    177         std::cout<<"-----------method non const GetBack const queue begin------------"<<std::endl;
    178         T const ee = GetBack();
    179         std::cout<<"e is value = "<<ee<<"\n";
    180         std::cout<<"-----------method non const GetBack const queue end------------"<<std::endl;
    181     }
    182 
    183     /**
    184      *测试const函数重载
    185      */
    186     void test2() const {
    187         T e;
    188         std::cout<<"-----------method const GetBack queue begin------------"<<std::endl;
    189         for(size_t i = 1; i < 2; ++i){
    190             e = GetBack();
    191             std::cout<<"e is value = "<<e<<"\n";
    192         }
    193         std::cout<<"-----------method const GetBack queue end------------"<<std::endl;
    194 
    195         std::cout<<"-----------method const GetBack const queue begin------------"<<std::endl;
    196         T const ee = GetBack();
    197         std::cout<<"e is value = "<<ee<<"\n";
    198         std::cout<<"-----------method const GetBack const queue end------------"<<std::endl;
    199     }
    200 };
    201 
    202 
    203 
    204 #endif /* LISTQUENE_H_ */
    View Code

    Common.h

     1 /*
     2  * Common.h
     3  *
     4  *  Created on: May 17, 2012
     5  *      Author: sunysen
     6  */
     7 
     8 #ifndef COMMON_H_
     9 #define COMMON_H_
    10 
    11 #include <iostream>
    12 #include "memory"
    13 #include "string"
    14 #include "string.h"
    15 #include <math.h>
    16 
    17 
    18 using namespace std;
    19 #endif /* COMMON_H_ */
    View Code

    三:环境

    1、运行环境:Ubuntu 10.04 LTS+VMware8.0.4+gcc4.4.3

    2、开发工具:Eclipse+make

    四:题记

    1、上面的代码难免有bug,如果你发现代码写的有问题,请你帮忙指出,让我们一起进步,让代码变的更漂亮和更健壮;

    2、鼓励自己能坚持把更多数据结构方面的知识写出来,让自己掌握更深刻,也顺便冒充下"小牛"

    3、感谢Vamei老大的指导,把博客弄漂亮,不被女朋友鄙视了。

    4、后续数据结构方面的代码命名规则会严格按照STL的标准,期待这样能有缘人看更明白

     

    欢迎继续阅读“启迪思维:数据结构和算法”系列

    一根球杆,几行代码,品世间酸甜苦辣

    如果你喜欢这篇文章,欢迎推荐

    年轻人有理想、有野心,更需要脚踏实地做事情

  • 相关阅读:
    Pro ASP.NET Core MVC2
    vscode
    git命令使用
    单行函数
    过滤和排序
    oracle基本查询
    斐波那契数列的递归实现
    队列的顺序存储结构
    队列的链式存储结构
    折半查找法
  • 原文地址:https://www.cnblogs.com/sunysen/p/3122643.html
Copyright © 2020-2023  润新知