精华内容
下载资源
问答
  • 华为2019年2月份HCIE教材 OSPF双栈原理,OSPF(Open Shortest Path First)是IETF组织开发的一个基于链路状态的内部网关协议(Interior Gateway Protocol)。OSPF作为基于链路状态的协议,具有收敛快、路由无环、可...
  • 华为2019年2月份HCIE教材 ISIS双栈原理,本章将围绕ISIS协议重点介绍其高级特性和IPv6下的ISIS特性与配置,并且围绕现网介绍双栈ISIS在现网的部署与实现。
  • 双栈实现计算器

    2017-05-12 21:26:18
    用双向栈实现一个计算器,可完成 2+3*(9-3)= 的计算
  • 双栈

    千次阅读 多人点赞 2018-10-11 13:46:24
    初始化双栈s,长度为n: void Init(DblStack &S,int n) { S.m = n; S.V = new int [n+10]; S.bot[0] = S.top[0] = -1; S.bot[1] = S.top[1] = S.m; } 判空: int EmptyStack0(DblStack S) { if(S...

    利用栈底位置相对不变的特性,可以让两个顺序栈共享一个空间。

    具体实现方法大概有两种:

    一种是奇偶栈,就是所有下标为奇数的是一个栈,偶数是另一个栈。但是这样一个栈的最大存储就确定了,并没有起到互补空缺的作用,我们实现了也就没有太大意义。

    还有一种就是,栈底分别设在数组的头和尾。进栈往中间进就可以了。这样,整个数组存满了才会真的栈满。

     

    那我们直接开始代码实现

     

    首先定义结构体:

    typedef struct
    {
      int top[2], bot[2];    //栈顶和栈底指针
      int *V;      //栈数组
      int m;     //栈最大可容纳元素个数
    }DblStack;

     

    初始化双栈s,长度为n:

    void Init(DblStack &S,int n)
    {
        S.m = n;
        S.V = new int [n+10];
        S.bot[0] = S.top[0] = -1;
        S.bot[1] = S.top[1] = S.m;  
    }

    判空:

    int EmptyStack0(DblStack S)
    {
        if(S.top[0]==-1)return 0;
        else return 1;
    }
    int EmptyStack1(DblStack S)
    {
        if(S.top[1]==S.m)return 0;
        else return 1;
    }

    判满:(没有单独判断一个栈的,是判断整个储存空间还有没有地方)

    int FullStack(DblStack S)
    {
        if(S.top[1]-S.top[0]==1)return 1;
        else return 0;
    }

    进栈:

    void Push0(DblStack &S,int e)
    {
        if(S.top[1]-S.top[0]!=1)
        {
            S.top[0]++;
            S.V[S.top[0]] = e;
        }
    }
    
    void Push1(DblStack &S,int e)
    {
        if(S.top[1]-S.top[0] != 1)
        {
            S.top[1]--;
            S.V[S.top[1]] = e;
        }
    }

    出栈:

    void Pop0(DblStack &S,int &e)
    {
        if(S.top[0]!=-1)
        {
            e = S.V[S.top[0]];
            S.top[0]--;
        }
    }
    
    void Pop1(DblStack &S,int &e)
    {
        if(S.top[1]!=S.m)
        {
            e = S.V[S.top[1]];
            S.top[1]++;
        }
    }

     

    展开全文
  • centos 双栈路由的配置

    2015-02-05 09:45:48
    一个简单双栈路由的配置方式,如果是三栈的话一样的配置方法只需要增加路由条目就可以了。
  • 华为路由器同时实现与IPV4网络和IPV6网络通信技术,本文档内包含了网络设备拓扑图,可以直接下载解压查看完整的配置命令。
  • 华为2019年2月份HCIE教材 BGP双栈原理Advance+Internet设计 本章将介绍BGP原理以及BGP对IPv6的扩展性——BGP4+。 BGP提供各种高级特性与技术供使用,合理运用各种特性与技术可提升网络性能,BGP网络可能存在的问题。
  • 介绍IPv6环境下PPPoE接入控制的基本流程;针对家庭网关不同的工作模式,分析双栈用户在家庭网关桥接模式和路由模式下的接入流程;研究双栈环境下部署PPPoE接入控制方式对相关设备及系统的要求和网络部署方案。
  • 通过分析IPv6 的原理和新特性、NAT-PT 的地址转换及协议转换功能等IPv4 向IPv6 过渡技术,结合校园网光缆和设备,研究使用NAT-PT 和双栈技术规划部署IPv6 校园网和解决校园网内IPv4 与IPv6 资源互访的问题,提出了符合...
  • 本源码实现了Java双栈式科学型计算器,参考了Win10附件中科学型计算器的功能。无GUI界面,改包名即可运行。
  • ISIS双栈原理

    2021-10-25 18:53:40
    ATT为1的LSP: 由level-1-2路由器生成,同区域level-1收到后,生成指向level-1-2的缺省路由 ATT为1条件:level-1-2和level-2必须处于不同区域 ISIS LSP:实现拓扑路由分离 LSP使用LSP-id唯一标识 ...

    ATT为1的LSP:
    由level-1-2路由器生成,同区域level-1收到后,生成指向level-1-2的缺省路由
    ATT为1条件:level-1-2和level-2必须处于不同区域

    ISIS LSP:实现拓扑路由分离
    LSP使用LSP-id唯一标识
    LSP-id组成:systeam-id + 伪节点编号 + LSP分片编号
    伪节点编号全为0,标识实节点LSP
    不为0,标识伪节点LSP

    实节点LSP:既有拓扑信息又有路由信息
    描述自身连接到哪些路由器和自身有哪些网段
    拓扑信息:is-reachability TLV(邻居可达TLV)(窄模式)

           路由信息:IP internal reachability TLV(域内路由信息可达TLV)描述域内路由信息(窄模式)
    			![](https://img-blog.csdnimg.cn/aaffb59da9144a6080091a40c7844be8.png)
    
                           IP external reachability TLV(域外路由可达TLV)(窄模式)
    			![](https://img-blog.csdnimg.cn/8b73d2ee359b49b4af5329d17b5954ef.png)
    

    伪节点LSP(DIS):只携带拓扑信息
    描述DIS连接到哪些路由器
    is-reachability TLV

    isis产生一个新的LSP并且把他传递给对端路由器计算成路由信息所花费的所有时间
    延迟:(ISIS震荡开始到完成收敛所需要的时间)
    检查故障需要的时间+生成LSP需要的时间+泛洪LSP的时间+对端SPF算法的时间+对端ISIS路由加表需要的时间+设备从主控板向数据板卡下发路由信息的时间

    ISIS高级特性:
    ISIS快速收敛:
    ISIS收敛步骤:

                        IGP的收敛可以总体描述为如下状态D+O+F+SPT+RIB+DD:
                                     D状态为从链路出现故障以后到路由器发现链路故障所用的时间
                                     O状态为生成LSP,用来描述新的网络拓扑结构所需要的时间
                                     F状态为从发现链路故障一直到向邻居发布FIB更新的时间
                                     SPT状态为运行SPF算法,计算最短路径树的时间
                                     RIB状态为用主CPU更新RIB表象和FIB表象的时间
                                     DD状态为从主控板向线卡上发布更新路由信息的延迟
                              RIB状态和DD状态一般与路由器的硬件有关,如主CPU、线卡CPU、内存、网络处理器有关,这两个状态人为无法对收敛时间做出很大的改变。所以本文基本上以讨论前四个状态为主
    

    链路故障检测:ISIS链路故障检测时间:30s
    ISIS hello报文:
    P2P:首次发送按照接口的MTU发送
    邻居关系建立后,hello消息不再填充
    MA:永远按照接口MTU发送
    华为设备默认MTU1500字节
    ISIS small-hello包:通过命令配置让hello包不再填充
    接口下:ISIS small-hello //设备不再发送填充到MTU的hello报文

          现有的故障检测方法主要包括:
                      硬件检测:例如通过SDH(同步数字体系)告警检测链路故障。硬件检测的优点是可以很快发现故障,但并不是所有介质都能提供硬件检测
                      慢Hello机制:通常是指路由协议的Hello机制。这种机制检测到故障所需时间为秒级。对于高速数据传输,例如吉比特速率级,超过1秒的检测时间将导致大量数据丢失;对于时延敏感的业务,例如语音业务,超过1秒的延迟也是不能接受的。并且,这种机制依赖于路由协议。IS-IS协议一般通过IIH报文,用来做邻居发现和失效性检测,这个检测的速度是秒级的
                      其他检测机制:不同的协议或设备制造商有时会提供专用的检测机制,但在系统间互联互通时,这样的专用检测机制通常难以部署,如BFD
    

    ISIS hello包是秒级收敛,和BFD进行联动实现ISIS毫秒级收敛
    BFD:检测到链路故障,把故障通知给ISIS,ISIS中断邻居关系
    BFD单臂回声:发送源目IP地址相同的控制消息,用来检测不支持BFD功能的邻居

    GR:平滑重启特性,帮助重启的设备快速同步LSDB(ISIS不协商GR)
    MT:多拓扑能力,默认所有设备支持多拓扑(ISIS不协商多拓扑)

    ISIS邻居建立协商参数:
    1.最大区域地址数必须一致
    2.systerm id不能一致
    3.MTU必须一致
    4.如果是level-1,要求area id至少有一个相同
    5.MA网络必须要检查掩码
    6.支持的协议必须有一个相同

    生成LSP的间隔时间:
    ISIS生成新的LSP后,必须等待2s的间隔才会生成新的LSP(产生LSP的延迟时间过长,则会导致本地路由信息的变化无法及时通告给邻居路由器,使网络的收敛速度变慢)

          智能定时器:可以根据路由信息的变化频率自动调整延迟时间(ISIS LSP生成定时器:对于LSP-id相同的LSP,在网络震荡时,将会延长LSP生成间隔)
                 作用:加快网络的收敛速度,同时又不影响系统性能(可以对于突发事件(如接口Up/Down)快速响应,加快网络的收敛速度。同时,当网络变化频繁时,智能定时器的间隔时间会自动延长,避免过度占用CPU资源)
                 配置:timer lsp-generation + 最大生成间隔+首次生成间隔+后续生成间隔
                                          第一次:首生成间隔
                                          第二次及后续:后续生成间隔^2(N-1)一直到最大生成间隔
                                          三次之后回到首次生成间隔
    

    加快泛洪LSP的时间:

                    ISIS会将小于指定数目的LSO向外发送,剩余LSP等待5s(华为默认发送LSP的间隔)发送
                    用户可以指定每次扩散的LSP数量,这个数量是针对所有接口的。如果需要发送的LSP的数量大于这个数,则就发送lsp-count个LSP。如果配置了定时器,在路由计算之前如果这个定时器未超时,则立即扩散;否则在该定时器超时时发送
                    如果命令中没有指定级别,则缺省同时在Level-1和Level-2中使能此功能
    

    加快SPF的计算时间:

                          SPF智能定时器(Flash flood):收到新的LSP,首次立即计算,后续如果重复收到新的LSP,延长计算间隔
                                          一个正常运行的IS-IS网络是稳定的,发生大量的网络变动的几率很小,IS-IS路由器不会频繁的进行路由计算,所以第一次触发的时间可以设置的非常短(毫秒级)。如果拓扑变化比较频繁,智能定时器会随着计算次数的增加,间隔时间也会逐渐延长,避免占用大量的CPU资源
                          timer spf 最大间隔 首次间隔 后续间隔
    

    改进SPF的计算方法:

                          I-SPF:除了第一次计算时需要计算全部节点外,每次只计算影响的节点,而最后生成的最短路径树SPT与原来的算法所计算的结果相同,大大降低了CPU的占用率,提高了网络收敛速度
                         在路由计算中,路由代表叶子,路由器则代表节点
                         如果I-SPF计算后的SPT改变,PRC会只处理那个变化的节点上的所有叶子;如果经过I-SPF计算后的SPT并没有变化,则PRC只处理变化的叶子信息
                         比如一个IS接口,则整个网络拓扑的SPT是不变的,这时PRC只更新这个节点的接口路由,从而节省CPU占用率
                         PRC和I-SPF节点使能一个IS-配合使用可以将网络的收敛性能进一步提高,它是原始SPF算法的改进,所以已经代替了原有的算法
                         默认情况下华为路由器采用I-SPF和PRC进行计算,不需要命令配置
    

    ISIS快收敛配置:

    ISIS 管理标记:引入外部路由后,只有宽模式(扩展的TLV)才能携带tag(管理标记),携带在路由信息TLV的子选项中(stub TLVs)
    ISIS开销模式:
    窄模式(Narrow)(默认):计算的开销范围:(0-63)
    使用的TLV:
    128号TLV(IP Internal Reachability TLV):用来携带路由域内的IS-IS路由信息
    130号TLV(IP External Reachability TLV):用来携带路由域外的IS-IS路由信息
    2号TLV(IS Neighbors TLV):用来携带邻居信息
    宽模式(Wide):TLV发生改变:Extended(扩展的)
    使用的TLV:
    135号TLV(Extended IP Reachability TLV):用来替换原有的IP reachability TLV,携带IS-IS路由信息,它扩展了路由开销值的范围,并可以携带sub TLV(不区分内外部路由)
    22号TLV(IS Extended Neighbors TLV):用来携带邻居信息

                 import-route Direct tag 100 //将引入的直连路由打上标记100
                 import-route level 2 into level 1 tag 100 //只将携带标记100的路由引入到level-1
    

    基本特性:只有宽模式(扩展的TLV)才能携带tag(管理标记)
    管理标记特性允许在IS-IS域中通过管理标记对IP地址前缀进行控制,可以达到简化管理。其用途包括控制不同级别和不同区域间的路由引入,以及在同一路由器上运行的IS-IS多实例
    管理标记值与某些属性相关联。当cost-sytle为wide、wide-compatible或compatible时,如果发布可达的IP地址前缀具有该属性,IS-IS会将管理标记加入到该前缀的IP可达信息TLV中。这样,管理标记就会随着前缀发布到整个路由域
    使能管理标记时,必须使能IS-IS wide metric属性:cost-sytle wide

    工作原理:

    ISIS LSP分片扩展:使IS-IS路由器生成更多的LSP分片,用来携带更多的IS-IS路由信息
    基本概念:
    初始系统(Originating System):初始系统是实际运行IS-IS协议的路由器。允许一个单独的IS-IS进程像多个虚拟路由器一样发布LSP,而“Originating System”指的是那个“真正”的IS-IS进程
    系统ID(Normal System-ID):初始系统的系统ID
    虚拟系统(Virtual System):由附加系统ID标识的系统,用来生成扩展LSP分片。这些分片在其LSP ID中携带附加系统ID
    附加系统ID(Additional System-ID):虚拟系统的系统ID,由网络管理器统一分配。每个附加系统ID都允许生成256个扩展的LSP分片

    工作原理:(使能分片扩展后,必须重启ISIS进程)
    在IS-IS中,每个系统ID都标识一个系统,每个系统都最多可生成256个LSP分片。通过增加附加系统ID,可以最多配置50个虚拟系统,从而使得IS-IS进程最多可生成13056个LSP分片。
    使能分片扩展功能之后,如果存在由于报文装满而丢失的信息,系统会提醒重启IS-IS。重启之后,初始系统会尽最大能力装载路由信息,装不下的信息将放入虚拟系统的LSP中发送出去,并通过24号TLV来告知其他路由器此虚拟系统和自己的关系(24号TLV携带真实路由器的系统id)

    创建虚拟systerm id(最多50个,虚拟系统id全网唯一),使能LSP分片功能,必须重启ISIS分片功能才能正常运行,分片功能正常运行之后,所有虚拟系统产生的LSP都会携带真实设备的路由信息

    工作模式:

            Mode-1:
                       应用场景:网络中的部分路由器不支持LSP分片扩展特性(兼容无法识别LSP分片功能的设备)
                       工作原理:虚拟系统参与路由SPF计算,初始系统发布的LSP中携带了到每个虚拟系统的链路信息;虚拟系统发布的LSP也包含到初始系统的链路信息。这样,在网络中虚拟系统看起来与初始系统相连的真实路由器是一样的。
    

    每个虚拟系统产生的LSP和真实设备的flag(att level-1-2)完全相同
    真实系统到虚拟系统的开销都为0,保证SPF计算,真实系统的下游节点一定是虚拟系统
    Mode-2:
    应用场景:网络中所有路由器都支持(识别)LSP分片扩展特性
    工作原理:虚拟系统不参与路由SPF计算,网络中所有路由器都知道虚拟系统生成的LSP实际属于初始系统。在该模式下工作的IS-IS,可以识别IS Alias ID TLV的内容,并作为计算树和路由的依据。
    虚拟系统产生的LSP分片将会携带24号TLV(存放真实系统id),对端设备收到后,首先查看24号TLV,查看虚拟系统属于哪个真实设备,在SPF计算时,虚拟系统不参与SPF计算,虚拟系统携带的路由信息全部都依附于真实设备

           说明:无论在哪种方式下,初始系统和虚拟系统的LSP零分片中,都必须包含IS Alias ID TLV来表示初始系统是谁
    

    配置:ISIS进程下:LSP-fragment-extend mode-1 //使能ISIS mode-1分片功能
    virtual-systerm 2222.2222.2222 //配置虚拟系统id
    用户视图下:reset ISIS all //重启进程

    ISIS 路由过滤:
    Filter-policy acl/ip-prefix/route-policy import
    从协议路由表加入IP路由表时,执行import策略,但是不会影响LSP的信息

    Filter-policy export
    部署在引入外部路由的设备上,在外部路由引入ISIS时执行过滤操作,生成的LSP将不会携带外部路由信息

    ISIS 路由渗透:
    把level-2的路由信息引入level-1中执行路由渗透,目的是为了避免次优路径

    ISISv6基本原理与配置:
    ISIS 协议扩展:
    ISIS的报文采用TLV结构,因此扩展性很好:
    为支持新的协议和特性,只需要扩展新的TLV或子TLV
    可以轻松扩展支持IPv6,TE,MT等协议和特性
    IS-IS对IPv6的支持不需要对协议做大的改动,因此协议的继承性很好;不像OSPF,为支持IPv6需要开发全新的协议OSPFv3

    扩展的TLV类型:设计两个新的TLV支持IPv6
    1.IPv6 Reachability TLV [Type 236] [0xEC]:IPv6路由可达TLV;携带在LSP消息中
    IPv6 Reachability:类型值为236(0xEC),通过前缀、度量、标记等来描述可达的IPv6前缀/路由信息
    在IPv4中有IPv4内部可达性TLV和IPv4外部可达性TLV,在IPv6的扩展当中使用一个“X”bit来区分“内部”和“外部”

                        U:up/down bit ,标识这个前缀是否是从高level通告下来的(用来防环路)
                                      Up:表明level-2路由引入level-1,U置位,防止路由环路
                                      Down:表明level-1不再引入level-2
                        X:external original bit ,标识这个前缀/路由是否是从外部路由(其他路由协议)引入过来的
                        S:subtlv present bit,标识是否携带子TLV位。(可选)(tag标记TLV)
    
      2.IPv6 Interface Address TLV [Type 232] [0xE8]:IPv6接口地址TLV;携带在Hello消息中
               IPv6 Interface Address:类型值为232(0xE8)
               它相当于IPv4中的“IP Interface Address” TLV,只不过把原来的32比特的IPv4地址改为128比特的IPv6地址
    					![](https://img-blog.csdnimg.cn/c955b74095ee4fd1b9eda9db1389a2b3.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5pif56m65LqI6JOd,size_17,color_FFFFFF,t_70,g_se,x_16)
    
                     在hello PDU中,“接口地址TLV”只包含发送hello包的接口的链路本地地址;对于LSP,“接口地址TLV”只包含IS的全球单播地址
                     这个TLV结构是直接从TLV132映射过来的,因此,原来TLV132最多可以64个IPv4地址(32位),在TLV232中,最多只能有16个IPv6地址(128位)
    

    ISIS ST和MT:
    IS-IS ST单拓扑:
    IS-IS为所有协议维护相同的SPT (Shortest Path Tree)
    IPv4和IPv6的拓扑必须一致

      ST单拓扑缺点:
            不足之处:
                   网络可维护性的需求在目前的运营商中越来越被重视,独立拓扑的维护网络,即带内维护网络的需求开始出现
                   IS-IS为所有协议维护相同的SPT,这意味着IPv4和IPv6的拓扑必须一致
            有什么问题?
                   不适合分离拓扑的网络部署
                   为维护相同的拓扑,所有接口都必须同时运行IS-IS IPv4和IS-IS IPv6,部署不灵活
                   不能使用IPv4区域来链接不同的IPv6区域,否则IPv4区域会丢弃IPv6的流量
    

    MT(多拓扑):分离的拓扑:若支持MT,IS-IS可以为IPv4和IPv6维护分离的拓扑,使IS-IS在一个路由域中维护多个拓扑(ISIS支持同时部署IPv4和IPv6,并且可以实现一套物理拓扑,多套不同逻辑拓扑)
    (华为设备只支持IPv4和IPv6多拓扑)
    ISIS在产生LSP时,每个协议都会产生独立的拓扑信息和独立的路由信息
    ISIS路由协议主要可以分为以下几个方面:
    邻居的建立
    路由可达(Prefix Reachable)与路由器可达(IS Reachable)的发布
    SPF计算以及路由计算
    为了达到多拓扑的相互隔离,以上几个方面均要求携带MT参数以满足这一要求(SPF计算与路由计算在路由器内识别完成)
    新增四种新的TLV分别满足以上过程,实现了通用环境下的ISIS MT的交互过程:
    TLV 229 – Multi-Topology Identifier:携带接口地址
    TLV 222 – Multi-Topologies Intermediate System:中间系统TLV,携带MT拓扑信息
    TLV 235 – Multi-Topologies Reachable IPv4 Prefixes:携带IPv4的路由
    TLV 237 – Multi-Topologies Reachable IPv6 Prefixes:携带IPv6的路由

    ISISv6配置:
    使能ISIS进程多拓扑:[Huawei-isis-1]ipv6 enable topology ipv6
    接口上使能ISIS:[Huawei-GigabitEthernetX/Y/Z]isis ipv6 enable
    查看ISIS邻居关系:[Huawei]dis isis peer
    查看ISIS路由:[Huawei]dis isis route

    双栈ISIS应用案例:
    Area id:运营商获取
    Systerm id:环回接口演绎得到
    例:172.16.1.0
    172.016.001.000—高位补0,补够3位
    1720.1600.1000—四位一组

    ISIS默认开销cost:10

    快速收敛特性:
    智能生成计时器
    快速泛洪LSP
    SPF智能生成计时器
    I-SPF、PRC
    Small-hello

    ISIS 认证特点:
    和OSPFv2比较:
    OSPFv2配置认证后,所有报文都会携带认证信息,不灵活还消耗设备资源
    ISIS认证比较灵活,接口认证只认证hello消息
    区域认证针对level-1的LSP或SNP报文认证
    路由域认证针对level-2的LSP或SNP报文认证
    区域认证和路由域认证共同的功能:
    发LSP 收LSP
    发SNP 收SNP
    管理员可以针对其中的任意一个设置认证功能,非常灵活

    P2P邻居建立:
    三次握手机制:
    新的TLV:P2P状态判断TLV
    本地电路id (电路id:标识一台设备)
    对端电路id
    对端systerm id
    两次握手机制:
    只要收到对端的hello消息就UP

    ISIS如何支持P2MP:
    子接口+P2P

    展开全文
  • 使用双栈实现的队列,含有如下功能: 1.创建队列; 2.销毁队列; 3.清空队列; 4.进队列; 5.出队列; 6.获取队头元素; 7.获取队列的长度。
  • 双栈(Dual Stack)

    2019-11-21 12:25:28
    双栈(Dual Stack) 1. 双栈的概念 1.1 双栈的定义 双栈是指两个顺序栈,是一种特殊的顺序栈。 1.2 双栈中各元素的逻辑及存储关系 双栈共享一个地址连续的存储单元。即程序同时需要两个栈时,可以定义一个足够大的栈...

    双栈(Dual Stack)
    1. 双栈的概念
    1.1 双栈的定义
    双栈是指两个顺序栈,是一种特殊的顺序栈。
    1.2 双栈中各元素的逻辑及存储关系
    双栈共享一个地址连续的存储单元。即程序同时需要两个栈时,可以定义一个足够大的栈空间,该空间的两端分别设为两个栈的栈底,用bottom[0]=-1和bottom[1]=maxSize指示。
    压入数据时,让两个栈的栈顶top[0]和top[1]都向中间伸展,如果指示栈顶的指针top[0]+1等于另一个栈顶的指针top[1]时两栈已满。
    每次进栈时top[0]加1或top[1]减1,而退栈时top[0]减1或top[1]加1。
    如果top[0] == -1且top[1] == maxSize两栈为空。
    双栈的模型: 

    在双栈的情形下: 
    (1)栈的初始化语句:bottom[0]=top[0]=-1,bottom[1]=top[1]=maxSize。 
    (2)栈满的条件:top[0]+1 == top[1]。 
    (3)栈空的条件:bottom[0]==top[0]==-1且bottom[1]==top[1]==maxSize。
    2. 双栈的实现
    2.1 双栈的类定义及其操作的实现
    文件:DualStack.h


    #ifndef DUAL_STACK_H_


    #define DUAL_STACK_H_

    #include <iostream>


    #include <string>


    #include <strstream>


    using namespace std;

    const int defaultSize = 50;         //默认栈空间大小
    const int stackIncreament = 20;     //栈溢出时扩展空间的增量
    const int n = 2;                    //设置n=2个栈共有一个栈空间

    template <class T>
    class DualStack
    {
    public:
        DualStack(int sz = defaultSize);        //构造函数
        ~DualStack();                           //析构函数
    public:
        bool Push(const T& x, int d) ;      //新元素x进栈
        bool Pop(T& x, int d);              //栈顶元素出栈,并将该元素的值保存至x
        bool getTop(T& x, int d) const;     //读取栈顶元素,并将该元素的值保存至x
        bool IsEmpty() const;               //判断栈是否为空
        bool IsFull() const;                //判断栈是否为满
        int getSize() const;                //计算栈中元素个数
        void MakeEmpty();                   //清空栈的内容
        void overflowProcess();             //栈的溢出处理
    public:
        template <class T>
        friend ostream& operator<<(ostream& os, const DualStack<T>& s); //输出栈中元素的重载操作<<
    private:
        T *Vector;      //存放栈中元素的栈数组
        int top[n];     //栈顶指针
        int maxSize;    //栈最大可容纳元素个数
    };

    //构造函数
    template <class T>
    DualStack<T>::DualStack(int sz)
    {
        cout << "$ 执行构造函数" << endl;
        if (sz >= 0)
        {
            maxSize = sz;           
            top[0] = -1;
            top[1] = maxSize;
            Vector = new T[maxSize];
        }
    }                       

    //析构函数
    template <class T>
    DualStack<T>::~DualStack()
    {
        cout << "$ 执行析构函数" << endl;
        delete[] Vector;
        Vector = NULL;
    }   

    //新元素x进栈
    template <class T>
    bool DualStack<T>::Push(const T& x, int d)
    {
        if (true == IsFull())
        {
            return false;
        }
        if (0 == d)
        {
            top[0]++;
        }
        else
        {
            top[1]--;
        }
        Vector[top[d]] = x;
        return true;
    }

    //栈顶元素出栈,并将该元素的值保存至x
    template <class T>
    bool DualStack<T>::Pop(T& x, int d)
    {
        if (true == IsEmpty())
        {
            return false;
        }
        x = Vector[top[d]];
        if (0 == d)
        {
            top[0]--;
        }
        else
        {
            top[1]++;
        }
        return true;
    }

    //读取栈顶元素,并将该元素的值保存至x
    template <class T>
    bool DualStack<T>::getTop(T& x, int d) const
    {
        if (true == IsEmpty())
        {
            return false;
        }
        x = Vector[top[d]];
        return true;
    }

    //判断栈是否为空
    template <class T>
    bool DualStack<T>::IsEmpty() const
    {
        return ((-1 == top[0]) && (maxSize == top[1])) ? true : false;
    }

    //判断栈是否为满
    template <class T>
    bool DualStack<T>::IsFull() const
    {
        return (top[0] + 1 == top[1]) ? true : false;
    }

    //计算栈中元素个数
    template <class T>
    int DualStack<T>::getSize() const
    {
        return (top[0] + 1) + (maxSize - top[1]);
    }

    //清空栈的内容
    template <class T>
    void DualStack<T>::MakeEmpty()
    {
        delete[] Vector;
        top[0] = -1;
        top[1] = maxSize;
        Vector = new T[maxSize];
    }

    //栈的溢出处理
    template <class T>
    void DualStack<T>::overflowProcess()
    {
        int newSize = maxSize + stackIncreament;
        T *neweVector = new T[newSize];
        for (int i = 0; i <= top[0]; i++)
        {
            neweVector[i] = Vector[i];
        }
        for (int i = maxSize - 1; i >= top[1]; i--)
        {
            neweVector[i + stackIncreament] = Vector[i];
        }
        delete[] Vector;
        Vector = neweVector;
        maxSize = newSize;
        top[1] += stackIncreament;
    }

    //输出栈中元素的重载操作<<
    template <class T>
    ostream& operator<<(ostream& os, const DualStack<T>& s)
    {
        os << "top[0]=" << s.top[0] << endl;    //输出栈1顶位置
        for (int i = 0; i <= s.top[0]; i++)
        {
            os << "[" << i << "]" << " : " << s.Vector[i] << endl;
        }
        os << "top[1]=" << s.top[1] << endl;    //输出栈2顶位置
        for (int i = s.maxSize - 1; i >= s.top[1]; i--)
        {
            os << "[" << i << "]" << " : " << s.Vector[i] << endl;
        }
        return os;
    }


    #endif /* DUAL_STACK_H_ */
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    2.2 主函数(main函数)的实现
    文件:main.cpp


    #include "DualStack.h"

    #define EXIT 0              //退出


    #define PUSH 1              //新元素x进栈


    #define POP  2              //栈顶元素出栈,并将该元素的值保存至x


    #define GETTOP 3            //读取栈顶元素,并将该元素的值保存至x


    #define ISEMPTY  4          //判断栈是否为空


    #define ISFULL 5            //判断栈是否为满


    #define GETSIZE 6           //计算栈中元素个数


    #define MAKEEMPTY 7         //清空栈的内容


    #define OPERATOR_OSTREAM 8  //输出栈中元素的重载操作<<


    #define OVERFLOWPROCESS 9   //栈的溢出处理


    void print_description()
    {
        cout << "------------------------------>双栈<------------------------------" << endl;
        cout << "功能选项说明:" << endl;
        cout << "#0: 退出" << endl;
        cout << "#1: 新元素x进栈" << endl;
        cout << "#2: 栈顶元素出栈,并将该元素的值保存至x" << endl;
        cout << "#3: 读取栈顶元素,并将该元素的值保存至x" << endl;
        cout << "#4: 判断栈是否为空" << endl;
        cout << "#5: 判断栈是否为满" << endl;
        cout << "#6: 计算栈中元素个数" << endl;
        cout << "#7: 清空栈的内容" << endl;
        cout << "#8: 输出栈中元素的重载操作<<" << endl;
        cout << "#9: 栈的溢出处理" << endl;
        cout << "--------------------------------------------------------------------" << endl;
    }

    //判断输入的字符串每个字符是否都是数值0~9
    bool IsStackNumber(const string& s_num)
    {
        if (s_num.size() > 1)
        {
            return false;
        }

        if ((s_num[0] != '0') && (s_num[0] != '1'))
        {
            return false;
        }

        return true;
    }

    //判断输入的字符串每个字符是否都是数值0~9
    bool IsNumber(const string& s_num)
    {
        for (size_t i = 0; i < s_num.size(); i++)
        {
            if ((s_num[i] < '0') || (s_num[i] > '9'))
            {
                return false;
            }
        }
        return true;
    }

    //类型转换——将string型转为模板类型T
    template <class T>
    T StrToTtype(const string& s_num)
    {
        T n_num;
        strstream ss_num;
        ss_num << s_num;
        ss_num >> n_num;
        return n_num;
    }

    //输入栈编号
    template <class T>
    int get_item()
    {
        cout << "> 请输入栈编号,item = ";
        string s_item;
        cin >> s_item;
        while (false == IsStackNumber(s_item))
        {
            cout << "* 输入有误,请重新输入:";
            cin >> s_item;
        }
        return atoi(s_item.c_str());
    }

    //输入数据值
    template <class T>
    T get_data()
    {
        cout << "> 请输入数据值,data = ";
        string s_data;
        cin >> s_data;
        return StrToTtype<T>(s_data);
    }

    //输入数组的最大长度
    template <class T>
    int get_maxsize()
    {
        cout << "> 请输入数组的最大长度,maxsize = ";
        string s_maxsize;
        cin >> s_maxsize;
        while (false == IsNumber(s_maxsize))
        {
            cout << "* 输入有误,请重新输入:";
            cin >> s_maxsize;
        }
        return atoi(s_maxsize.c_str());
    }

    //构造双栈
    template <class T>
    DualStack<T>* construct_dualstack()
    {
        cout << "\n==> 创建双栈" << endl;
        int n_maxsize = get_maxsize<T>();
        DualStack<T> *dualStack = new DualStack<T>(n_maxsize);
        return dualStack;
    }

    //析构双栈
    template <class T>
    void destory_seqstack(DualStack<T>* dualStack)
    {
        cout << "\n==> 释放双栈在堆中申请的空间,并将指向该空间的指针变量置为空" << endl;
        delete dualStack;
        dualStack = NULL;
    }

    //新元素x进栈
    template <class T>              
    void push(DualStack<T>* dualStack)
    {
        cout << "$ 执行新元素x进栈函数" << endl;
        T data = get_data<T>();
        int d = get_item<T>();
        if (false == dualStack->Push(data, d))
        {
            cout << "* 进栈失败" << endl;
            return;
        }
        cout << "* 进栈成功,data = " << data << endl;
    }

    //栈顶元素出栈,并将该元素的值保存至x
    template <class T>  
    void pop(DualStack<T>* dualStack)
    {
        cout << "$ 执行栈顶元素出栈并将该元素的值保存至x函数" << endl;
        T data;
        int d = get_item<T>();
        if (false == dualStack->Pop(data, d))
        {
            cout << "* 出栈失败" << endl;
            return;
        }
        cout << "* 出栈成功,data = " << data << endl;
    }

    //读取栈顶元素,并将该元素的值保存至x
    template <class T>  
    void gettop(DualStack<T>* dualStack)
    {
        cout << "$ 执行读取栈顶元素并将该元素的值保存至x函数" << endl;
        T data;
        int d = get_item<T>();
        if (false == dualStack->getTop(data, d))
        {
            cout << "* 读取栈顶元素失败" << endl;
            return;
        }
        cout << "* 读取栈顶元素成功,data = " << data << endl;
    }

    //判断栈是否为空
    template <class T>  
    void isempty(DualStack<T>* dualStack)
    {
        cout << "$ 执行判断栈是否为空函数,IsEmpty = " << dualStack->IsEmpty() << endl;
    }

    //判断栈是否为满
    template <class T>  
    void isfull(DualStack<T>* dualStack)
    {
        cout << "$ 执行判断栈是否为满函数,IsFull = " << dualStack->IsFull() << endl;
    }

    //计算栈中元素个数
    template <class T>  
    void getsize(DualStack<T>* dualStack)
    {
        cout << "$ 执行计算栈中元素个数函数,Size = " << dualStack->getSize() << endl;
    }

    //清空栈的内容
    template <class T>  
    void makeempty(DualStack<T>* dualStack)
    {
        cout << "$ 执行清空栈的内容函数" << endl;
        dualStack->MakeEmpty();
    }

    //输出栈中元素的重载操作<<
    template <class T>  
    void operator_ostream(DualStack<T>* dualStack)
    {
        cout << "$ 执行输出栈中元素的重载操作<<函数" << endl;
        cout << *dualStack;//或operator<<(cout, *dualStack);
    }

    //栈的溢出处理
    template <class T>
    void overflowprocess(DualStack<T>* dualStack)
    {
        cout << "$ 执行栈的溢出处理函数" << endl;
        dualStack->overflowProcess();
    }

    //双栈操作选择
    template <class T>
    void select_operation(DualStack<T>* dualStack)
    {
        if (NULL == dualStack)
        {
            cout << "* 没有构造双栈,请先构造双栈。" << endl;
            return;
        }

        string s_operation;
        while (s_operation != "0")
        {
            cout << "\n==> 请输入功能选项编号(按\"0\"退出程序):";
            cin >> s_operation;
            while (false == IsNumber(s_operation))
            {
                cout << "* 输入有误,请重新输入:";
                cin >> s_operation;
            }
            int n_operation = atoi(s_operation.c_str());
            switch (n_operation)
            {
                case EXIT://退出
                {
                    cout << "$ 退出程序" << endl;
                    break;
                }
                case PUSH://新元素x进栈
                {
                    push(dualStack);
                    break;
                }
                case POP://栈顶元素出栈,并将该元素的值保存至x
                {
                    pop(dualStack);
                    break;
                }
                case GETTOP://读取栈顶元素,并将该元素的值保存至x
                {
                    gettop(dualStack);
                    break;
                }
                case ISEMPTY://判断栈是否为空
                {
                    isempty(dualStack);
                    break;
                }
                case ISFULL://判断栈是否为满
                {
                    isfull(dualStack);
                    break;
                }
                case GETSIZE://计算栈中元素个数
                {
                    getsize(dualStack);
                    break;
                }
                case MAKEEMPTY://清空栈的内容
                {
                    makeempty(dualStack);
                    break;
                }
                case OPERATOR_OSTREAM://输出栈中元素的重载操作<<
                {
                    operator_ostream(dualStack);
                    break;
                }
                case OVERFLOWPROCESS://栈的溢出处理
                {
                    overflowprocess(dualStack);
                    break;
                }
                default:
                {
                    cout << "* 请输入正确的功能选项编号" << endl;
                    break;
                }
            }
        }
    }

    int main(int argc, char* argv[])
    {
        print_description();
        DualStack<int> *dualStack = construct_dualstack<int>();
        select_operation(dualStack);
        destory_seqstack(dualStack);
        system("pause");
        return 0;
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    304
    305
    306
    307
    308
    309
    310
    311
    312
    313
    314
    315
    316
    317
    318
    319
    320
    321
    322
    323
    324
    325
    326
    327
    328
    329
    330
    331
    332
    3. 双栈的优缺点
    3.1 优点
    两栈的大小不是固定不变的,在实际运算过程中,一个栈有可能进栈元素多而体积大些,另一个则可能小些。
    两个栈共用一个栈空间,相互调剂,灵活性强。
    3.2 缺点
    运算较为复杂。
    长度为定值,中途不易扩充。
    注:n(n>2)个栈的情况更有所不同,采用多个栈共享栈空间的顺序存储表示方式,处理十分复杂,在插入时元素的移动量很大,因而时间代价较高。特别是当整个存储空间即将充满时,这个问题更加严重。
    解决上述问题的办法就是采用链接方式作为栈的存储表示方式。
    3.3 双栈的适用情况
    当栈满时要发生溢出,为了避免这种情况,需要为栈设立一个足够大的空间。但如果空间设置得过大,而栈中实际只有几个元素,也是一种空间浪费。此外,程序中往往同时存在几个栈,因为各个栈所需的空间在运行中是动态变化着的。如果给几个栈分配同样大小的空间,可能实际运行时,有的栈膨胀得快,很快就产生了溢出,而其他的栈可能此时还有许多空闲空间。这时就可以利用双栈,两个栈共用一个栈空间,相互调剂,灵活性强。
    参考文献: 
    [1]《数据结构(用面向对象方法与C++语言描述)(第2版)》殷人昆——第三章 
    [2]《C/C++常用算法手册》秦姣华、向旭宇——第二章 
    [3] 百度搜索关键字:双栈
    ————————————————
    版权声明:本文为CSDN博主「Cainv89」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/cainv89/article/details/51398148

    展开全文
  • 双栈共享

    2019-12-26 19:39:58
    双栈共享之数组实现 双栈的结构体构建 typedef struct SNode{ int *Data; int MaxSize;//栈的总长 int Top1,Top2;//两个栈的栈顶 }SNode,*Stack; 初始化创建 Stack CreateStack( int MaxSize ) { Stack S=...

    双栈共享之数组实现

    在这里插入图片描述
    双栈的结构体构建

    typedef struct SNode{
    	int *Data;
    	int MaxSize;//栈的总长
    	int Top1,Top2;//两个栈的栈顶
    }SNode,*Stack;
    

    初始化创建

    Stack CreateStack( int MaxSize )
     {
     	Stack S=(Stack)malloc(sizeof(struct SNode));
     	S->Data=(int *)malloc(MaxSize*sizeof(int));
     	//为动态数组分配空间
     	S->MaxSize=MaxSize;
     	S->Top1=-1;//第一个栈的栈顶指向头
     	S->Top2=MaxSize;//第二个栈的栈顶指向尾
     	return S;
     }
    

    双栈判空

    int IsEmpty(Stack S,int Tag)
    {//分别判断两个栈的空的条件
    	if(Tag==1&&S->Top1==-1)
    	return 1;
    	else if(Tag==2&&S->Top2==S->MaxSize)
    	return 1;
    	return 0;
    }
    

    双栈判满

    int IsFull(Stack S)
    {
    	if(S->Top2-S->Top1==1&&(S->Top1!=-1||S->Top2!=S->MaxSize))
    	//两个栈不空且位置之差为1
    	return 1;
    	return 0;
    }
    

    入栈

    bool Push( Stack S, int X, int Tag )
    {
    	if(S->Top2-S->Top1==1)
    	//if(S->top==S->MaxSize)
    	{//先判满
    		printf("Stack Full\n");
    		return false;
    	}
    	switch(Tag)
    	{//分情况入栈
    		case 1:
    			{
    				S->Data[++(S->Top1)]=X;
    				return true;
    				break;
    			}
    			case 2:
    				{
    					S->Data[--(S->Top2)]=X;
    					return true;
    					break;
    				}
    				default:
    					break;
    	}
    }
    int Pop( Stack S, int Tag )
    {
    	if(Tag==1)
    	{
    		if(S->Top1==-1)
    		{
    			printf("Stack %d Empty\n",Tag);
                return ERROR;
    		}
    		 return S->Data[(S->Top1)--];
    	}
    	else{
    		if(S->Top2==S->MaxSize)
    		{
    			printf("Stack %d Empty\n",Tag);
                return ERROR;
    		}
    		return S->Data[(S->Top2)++];
    	}
    	
    }
    

    出栈

    int Pop( Stack S, int Tag )
    {
    	if(Tag==1)
    	{
    		if(S->Top1==-1)//空
    		{
    			printf("Stack %d Empty\n",Tag);
                return ERROR;
    		}
    		 return S->Data[(S->Top1)--];
    	}
    	else{
    		if(S->Top2==S->MaxSize)//空
    		{
    			printf("Stack %d Empty\n",Tag);
                return ERROR;
    		}
    		return S->Data[(S->Top2)++];
    	}
    	
    }
    
     #include<stdio.h>
    #include<stdlib.h>
    #define ERROR 1e8
    typedef struct SNode{
    	int *Data;
    	int MaxSize;
    	int Top1,Top2;
    }SNode,*Stack;
     Stack CreateStack( int MaxSize )
     {
     	Stack S=(Stack)malloc(sizeof(struct SNode));
     	S->Data=(int *)malloc(MaxSize*sizeof(int));
     	S->MaxSize=MaxSize;
     	S->Top1=-1;
     	S->Top2=MaxSize;
     	return S;
     }
    bool Push( Stack S, int X, int Tag )
    {
    	if(S->Top2-S->Top1==1)
    	//if(S->top==S->MaxSize)
    	{
    		printf("Stack Full\n");
    		return false;
    	}
    	switch(Tag)
    	{
    		case 1:
    			{
    				S->Data[++(S->Top1)]=X;
    				return true;
    				break;
    			}
    			case 2:
    				{
    					S->Data[--(S->Top2)]=X;
    					return true;
    					break;
    				}
    				default:
    					break;
    	}
    }
    int Pop( Stack S, int Tag )
    {
    	if(Tag==1)
    	{
    		if(S->Top1==-1)
    		{
    			printf("Stack %d Empty\n",Tag);
                return ERROR;
    		}
    		 return S->Data[(S->Top1)--];
    	}
    	else{
    		if(S->Top2==S->MaxSize)
    		{
    			printf("Stack %d Empty\n",Tag);
                return ERROR;
    		}
    		return S->Data[(S->Top2)++];
    	}
    	
    }
    int IsEmpty(Stack S,int Tag)
    {
    	if(Tag==1&&S->Top1==-1)
    	return 1;
    	else if(Tag==2&&S->Top2==S->MaxSize)
    	return 1;
    	return 0;
    }
    int IsFull(Stack S)
    {
    	if(S->Top2-S->Top1==1&&(S->Top1!=-1||S->Top2!=S->MaxSize))
    	return 1;
    	return 0;
    }
    int main()
    {
    	int n,Tag,X;
    	scanf("%d",&n);
    	struct SNode *S;
    	S=CreateStack(n);
         for(int i=0;i<n;i++)
         { 
    		scanf("%d%d",&X,&Tag);
    			Push(S,X,Tag);
    	}
    	scanf("%d",&Tag);
    	int y;
    	while(!IsEmpty(S,Tag))
    	{
    			y=Pop(S,Tag);
    	printf("%d\n",y);
    	}
    
    	return 0;
    }
    
    展开全文
  • ENSP实现IPV4与IPV6的双栈

    千次阅读 2019-11-17 13:29:12
    双栈:设备能同时工作在IPV4与IPV6两种网络中,能同时与IPV4和IPV6网络中的设备进行通信。 IPV6的特点: 1:全球单播地址—IPV6网络中没有NAT。 2:可聚合性—IANA组织对全球的IPV6地址进行合理分配。 3:多宿主—在...
  • 双栈的基本操作

    2021-11-11 00:13:12
    双栈的基本操作 描述 将编号为0和1的两个栈存放于一个数组空间V[m]中,栈底分别处于数组的两端。当第0号栈的栈顶指针top[0]等于-1时该栈为空;当第1号栈的栈顶指针top[1]等于m时,该栈为空。两个栈均从两端向中间...
  • 题目 ...试编写双栈初始化,判断栈空、栈满、进栈 和出栈等算法的函数。双栈数据结构的定义如下: 代码 #include <stdio.h> #include <stdlib.h> #include <iostream> using na
  • 牛客题面:双栈排序 题面大意: 给定一个整数 nnn 和一个初始序列 aaa,其中序列 aaa 的值为[1,n]不重复的正整数。 现在有以下四个操作,希望能够凭借这四个操作使得序列 aaa 成为一个升序的序列。 操作a:如果输入...
  • BGP双栈原理Basic

    2021-10-26 18:46:20
    NLRI:网络层可达信息<前缀,前缀长度> MP-NLRI:携带IPv6和VPNv4、VPNv6路由信息 BGP原理: BGP工作原理: BGP特点: 1.使用TCP作为传输协议,端口号179 2.BGP路由聚合方式:静态路由(直接在network聚合路由...
  • 双栈共享空间

    2021-07-16 16:39:46
    //双栈共享空间 typedef struct { int data[MAXSIZE];//双栈共享数组; int top1; int top2; }sqdoubleStack; //插入元素 void Push(sqdoubleStack*s,int num,int stacknumber){ if(top1+1==top2) return ; ...
  • Dijkstra双栈算术表达式求值算法 什么是stack Stack,下压栈是基于后进先出(LIFO,Last In First Out)策略的集合类型,就像一叠邮件,每次从最顶端的邮件开始看起一样。 Dijkstra双栈算术表达式求值算法 我是用Java写...
  • 双栈模拟队列: 用两个栈来实现队列的功能,即先进先出,而栈存取数据的特点就是先进后出。有人会说,干嘛非要这么麻烦,用栈的时候创建一个栈,用队列的时候创建一个队列,这不是很容易吗,但在实际操作上中,...
  • IPv6实践 - IPv6双栈改造环境简介(拓扑)网络设备v6配置系统IPv6配置(Ubuntu/Windows) 环境简介(拓扑) 完整环境如上图,本次改造不涉及互联网部分 三台 cisco三层交换: sw1、sw2、sw3 一台 Windows2012: server1...
  • 重点分析固定网络向IPv6演进过程中,用户侧家庭网关设备在双栈接入场景下面临的3个新的安全问题,包括IPoE 业务通道防护、双栈用户地址溯源、管理口双栈地址防护。针对性地提出了3个安全防护技术方案,并给出了相应...
  • IPv6双栈技术方案

    千次阅读 2020-12-06 20:26:45
    IPv6双栈配置及功能实现 主要介绍IPv6双栈配置包括vlan的配置,创建v6网络、创建IPv6虚机、验证IPv6网络是否可达。
  • SAP PI - 单栈与双栈

    千次阅读 2019-07-09 08:31:40
    在PI初次发布的时候,不是所有的组件都是在同一个平台上构建的。...因此PI需要Java和ABAP环境来运行,这被称为双栈。 ABAP Stack Java Stack Integration Engine Business Proces...
  • IPV6、IPV4双栈配置

    2021-09-28 10:30:49
    一、配置要求 1、IPV6、IPV4都存在一台路由器内 2、配置各个接口的IP地址,要求各设备可以互访。 3、IPV4使用OSPF协议。IPV6使用RIPNG协议。 二、配置拓扑图 三、配置命令 ...interface Gig...
  • //为双栈分配一个大小为m的数组空间 if(!S.V){ printf(“初始化失败”);//存储分配失败 return ; } S.top[0]=-1; S.bot[0]=-1; S.top[1]=m; S.bot[1]=m; } int DblstackEmpty(SDblStack S)//判空 { if(S.top[0]==S....

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 5,334
精华内容 2,133
关键字:

双栈