Qz学算法-数据结构篇(链表、栈)

简介: 数据结构的链表和栈

链表(Linked List)

链表是有序的列表,但是它在内存中是存储如下

网络异常,图片无法展示
|

介绍

  • 链表是以节点的方式来存储,是链式存储
  • 每个节点包含data域,next域:指向下一个节点.
  • 如图:发现链表的各个节点不一定是连续存储
  • 链表分带头节点的链表和没有头节点的链表,根据实际的需求来确定

1.单链表

单链表(带头结点)逻辑结构示意图如下

网络异常,图片无法展示
|

1.1单链表的创建和遍历

网络异常,图片无法展示
|

  • 添加
  • 先创建一个head头节点,作用就是表示单链表的头
  • 后面我们每添加一个节点,就直接加入到链表的最后
  • 遍历
  • 通过一个辅助变量遍历,帮助遍历整个链表

代码实现

要创建两个对象一个是节点对象,一个是链表对象

做add添加时,先找到链表的最后,如果这个链表没有最后,那么我们加入的这个node节点就是这次的头指针指向下一个节点

publicclassSingleLinkedListDemo {
publicstaticvoidmain(String[] args) {
//进行测试//先创建节点HeroNodehero1=newHeroNode(1, "宋江", "及时雨");
HeroNodehero2=newHeroNode(2, "卢俊义", "玉麒麟");
HeroNodehero3=newHeroNode(3, "吴用", "智多星");
HeroNodehero4=newHeroNode(4, "林冲", "豹子头");
//创建一个链表SingleLinkedListsingleLinkedList=newSingleLinkedList();
//加入singleLinkedList.add(hero1);
singleLinkedList.add(hero2);
singleLinkedList.add(hero3);
singleLinkedList.add(hero4);
singleLinkedList.list();
    }
}
//定义SingleLinkedList 管理我们的HeroclassSingleLinkedList{
//先初始化一个头节点,头节点不要动,不存放具体的数据privateHeroNodehead=newHeroNode(0,"","");
//返回头节点publicHeroNodegetHead(){
returnhead;
    }
//添加节点到单向链表//思路:当不考虑编号顺序时//1.找到当前链表的最后节点//2.将最后这个节点的next 指向新的节点publicvoidadd(HeroNodeheroNode){
//因为head节点不能动,因此我们需要一个辅助变量tempHeroNodetemp=head;
//遍历链表.找到最后while(true){
//找到链表的最后if(temp.next==null){
break;
            }
//如果没有找到最后,将temp后移temp=temp.next;
        }
//当退出while循环时,temp就指向了链表的最后//将最后这个节点的next指向新的节点temp.next=heroNode;
    }
//显示链表[遍历]publicvoidlist(){
//判断链表是否为空if (head.next==null){
System.out.println("链表为空");
return;
        }
//因为头节点不能动,因此我们需要一个辅助变量来遍历HeroNodetemp=head.next;
while(true){
//判断是否到链表最后if (temp==null){
break;
            }
//输出节点信息System.out.println(temp);
//将temp后移,一定注意temp=temp.next;
        }
    }
}
//定义一个HeroNode,每个HeroNode对象就是一个节点classHeroNode{
publicintno;
publicStringname;
publicStringnickName;
publicHeroNodenext;//指向下一个节点publicHeroNode(intno, Stringname, StringnickName) {
this.no=no;
this.name=name;
this.nickName=nickName;
    }
//为了显示方法,我们重新toString@OverridepublicStringtoString() {
return"HeroNode{"+"no="+no+", name='"+name+'\''+", nickName='"+nickName+'\''+'}';
    }
}

1.2按顺序插入

代码实现

//第二种方式在添加英雄时,根据排名将英雄插入到指定位置publicvoidaddByOrder(HeroNodeheroNode){
//因为头节点不能动,因此我们仍然通过一个辅助指针(变量)来帮助找到添加的位置//因为单链表,因此我们找的temp是位于添加位置的前一个节点,否则插入不了HeroNodetemp=head;
booleanflag=false; //flag标志添加的编号是否存在,默认为falsewhile(true){
if (temp.next==null) break;  //说明temp已经在链表最后if (temp.next.no>heroNode.no){  //位置找到,就在temp的后面插入break;
        }elseif (temp.next.no==heroNode.no){//说明希望添加的heroNode的编号已然存在flag=true;  //说明编号存在break;
        }
temp=temp.next;//后移.遍历当前链表    }
//判断当前flag的值if (flag){  //不能添加,说明编号存在System.out.printf("准备插入的英雄编号%d,已经存在,不能添加\n",heroNode.no);
    }else{
//插入到链表中,temp后面heroNode.next=temp.next;
temp.next=heroNode;
    }
}
heroNode.next = temp.next;
        temp.next = heroNode;

这里我们把hero.next=temp.next操作是因为,我们要插入一个节点,那么就需要让索引后移一维,即插入位置的后一个节点指向临时变量节点指向的后一个节点,临时变量指向的节点等于要插入的节点

我们按照1423的顺序插入

singleLinkedList.addByOrder(hero1);
singleLinkedList.addByOrder(hero4);
singleLinkedList.addByOrder(hero2);
singleLinkedList.addByOrder(hero3);

image.png

1.3修改节点信息

代码实现

//修改节点信息  根据no编号来修改,即no编号不能改,//说明//1. 根据根据newHeroNode的no来修改即可publicvoidupdate(HeroNodenewHeroNode){
//判断是否为空if (head.next==null){
System.out.println("链表为空");
return;
    }
//找到需要修改的节点,根据no编号//定义一个铺助变量HeroNodetemp=head.next;
booleanflag=false; //表示是否找到节点while(true){
if (temp==null){
break;  //已经遍历完链表        }
if (temp.no==newHeroNode.no){
//找到flag=true;
break;
        }
temp=temp.next;
    }
//根据flag 判断是否找到要修改的节点if (flag){
temp.name=newHeroNode.name;
temp.nickName=newHeroNode.nickName;
    }else{//没有找到System.out.printf("没有找到编号%d的节点",newHeroNode.no);
    }
}

网络异常,图片无法展示
|

1.4删除节点

思路

  • 我们先找到需要删除的这个节点的前一个节点temp
  • temp.next =temp.next.next
  • 被删除的节点,将不会有其它引用指向,会被垃圾回收机制回收

代码实现

//删除节点
public void del(int no){
    HeroNode temp = head;
    boolean flag = false; //标志是否找到待删除节点
    while(true){
        if (temp.next == null) break;//已经到链表的最后
        if (temp.next.no == no){
            //找到了待删除的节点的前一节点temp
            flag = true;
            break;
        }
        temp = temp.next;   //temp后移,遍历
    }
    //判断flag
    if (flag){//找到
        //可以删除
        temp.next = temp.next.next;
    }else {
        System.out.printf("要删除的%d节点不存在",no);
    }
}
复制代码

2.双向链表

2.1单链表的缺点

  • 单向链表,查找的方向只能是一个方向,而双向链表可以向前或者向后查找。
  • 单向链表不能自我删除,需要靠辅助节点,而双向链表,则可以自我删除,所以前面我们单链表删除时节点,总是找到temp的下一个节点来删除的

2.2双向链表的操作思路

  • 遍历方式和单链表一样,只是可以向前查找.也可以向后查找
  • 添加(默认添加到双线链表的最后)
  • 先找到双线链表的最后这个节点
  • temp.next = newHeroNode
  • newHeroNode.pre=temp
  • 修改思路和原来的单向链表一样
  • 删除
  • 因为是双向链表,因此,我么可以实现自我删除某个节点
  • 直接找到要删除的这个节点,比如temp
  • temp.pre.next = temp.next
  • temp.next.pre = temp.pre

2.3代码实现

publicclassDoubleLinkedListDemo {
publicstaticvoidmain(String[] args) {
System.out.println("双向链表的测试");
HeroNode2hero1=newHeroNode2(1, "宋江", "及时雨");
HeroNode2hero2=newHeroNode2(2, "卢俊义", "玉麒麟");
HeroNode2hero3=newHeroNode2(3, "吴用", "智多星");
HeroNode2hero4=newHeroNode2(4, "林冲", "豹子头");
//创建一个双向链表DoubleLinkedListdoubleLinkedList=newDoubleLinkedList();
doubleLinkedList.add(hero1);
doubleLinkedList.add(hero2);
doubleLinkedList.add(hero3);
doubleLinkedList.add(hero4);
doubleLinkedList.list();
//修改HeroNode2newHeroNode=newHeroNode2(4,"公孙胜","入云龙");
doubleLinkedList.update(newHeroNode);
System.out.println("修改后的链表情况");
doubleLinkedList.list();
//删除doubleLinkedList.del(3);
System.out.println("删除后的链表情况");
doubleLinkedList.list();
    }
}
//创建一个双线链表的类classDoubleLinkedList{
//先初始化一个头节点,头节点不要动,不存放具体的数据privateHeroNode2head=newHeroNode2(0,"","");
//返回头节点publicHeroNode2getHead(){
returnhead;
    }
//遍历双向链表的方法//显示链表[遍历]publicvoidlist(){
//判断链表是否为空if (head.next==null){
System.out.println("链表为空");
return;
        }
//因为头节点不能动,因此我们需要一个辅助变量来遍历HeroNode2temp=head.next;
while(true){
//判断是否到链表最后if (temp==null){
break;
            }
//输出节点信息System.out.println(temp);
//将temp后移,一定注意temp=temp.next;
        }
    }
//添加一个节点到双向链表的最后publicvoidadd(HeroNode2heroNode){
//因为head节点不能动,因此我们需要一个辅助变量tempHeroNode2temp=head;
//遍历链表.找到最后while(true){
//找到链表的最后if(temp.next==null){
break;
            }
//如果没有找到最后,将temp后移temp=temp.next;
        }
//当退出while循环时,temp就指向了链表的最后//形成一个双向链表temp.next=heroNode;
heroNode.pre=temp;
    }
//修改一个节点的内容,可以看到双向链表的节点内容修改和单向链表一样//知识节点类型改成了HeroNode2publicvoidupdate(HeroNode2newHeroNode){
//判断是否为空if (head.next==null){
System.out.println("链表为空");
return;
        }
//找到需要修改的节点,根据no编号//定义一个铺助变量HeroNode2temp=head.next;
booleanflag=false; //表示是否找到节点while(true){
if (temp==null){
break;  //已经遍历完链表            }
if (temp.no==newHeroNode.no){
//找到flag=true;
break;
            }
temp=temp.next;
        }
//根据flag 判断是否找到要修改的节点if (flag){
temp.name=newHeroNode.name;
temp.nickName=newHeroNode.nickName;
        }else{//没有找到System.out.printf("没有找到编号%d的节点",newHeroNode.no);
        }
    }
//从双向链表中删除一个节点//说明//1 对于双向链表,我们可以直接找到要删除的这个节点//2 找到后,自我删除即可publicvoiddel(intno){
//判断当前链表是否为空if (head.next==null){
System.out.println("链表为空,无法删除");
return;
        }
HeroNode2temp=head.next;//辅助变量(指针)booleanflag=false; //标志是否找到待删除节点while(true){
if (temp==null) break;//已经到链表的最后if (temp.no==no){
//找到了待删除的节点的前一节点tempflag=true;
break;
            }
temp=temp.next;   //temp后移,遍历        }
//判断flagif (flag){//找到//可以删除//temp.next = temp.next.next; [单向链表]temp.pre.next=temp.next;
//这里代码有风险//如果是最后一个节点,就不需要执行下面这句话,否则出现空指针异常if (temp.next==null){
temp.next.pre=temp.pre;
            }
        }else {
System.out.printf("要删除的%d节点不存在",no);
        }
    }
}
//定义一个HeroNode2,每个HeroNode对象就是一个节点classHeroNode2{
publicintno;
publicStringname;
publicStringnickName;
publicHeroNode2next;//指向下一个节点,默认为nullpublicHeroNode2pre;//指向前一个节点,默认为nullpublicHeroNode2(intno, Stringname, StringnickName) {
this.no=no;
this.name=name;
this.nickName=nickName;
    }
//为了显示方法,我们重新toString@OverridepublicStringtoString() {
return"HeroNode{"+"no="+no+", name='"+name+'\''+", nickName='"+nickName+'\''+'}';
    }
复制代码

3.环形链表和约瑟夫问题

3.1引入

Josephus(约瑟夫、约瑟夫环)问题

Josephus问题为:设编号为1,2,…n的n个人围坐一圈,约定编号为(1<=k<=n)的人从1开始报数,数到m的那个 人出列,它的下一位又从1开始报数,数到m的那个人又出列,依次类推,直到所有人出列为止,由此产生一个出队编号的序列。

提示:

用一个不带头结点的循环链表来处理Josephus问题:先构成一个有个结点的单循环链表,然后由结点起从1开始计数,计到m时,对应结点从链表中删除,然后再从被删除结点的下一个结点又从1开始计数,直到最后一个结点从链表中册则除算法结束。

网络异常,图片无法展示
|

网络异常,图片无法展示
|

3.2思路

构建一个单向的环形链表思路

  • 先创建第一个节点,让first指向该节点,并形成环形
  • 后面当我们每创建一个新的节点,就把该节点,加入到已有的环形链表中即可

遍历环形链表

  • 先让一个辅助指针(变量)curBoy,指向first节点
  • 然后通过一个while循环遍历该环形链表即可curBoy.next=first结束

3.3代码实现(构建环形链表和遍历)

publicclassJosephus {
publicstaticvoidmain(String[] args) {
//测试一把看看构建环形链表,和遍历是否QkCircleSingleLinkedListcircleSingleLinkedList=newCircleSingleLinkedList();
circleSingleLinkedList.addBoy(5);
circleSingleLinkedList.showBoy();
    }
}
//创建一个环形单向链表classCircleSingleLinkedList{
//创建一个first节点,当前没有编号的privateBoyfirst=null;
//添加小孩的节点,构建成一个环形链表publicvoidaddBoy(intnums){
//nums 做一个数据校验if (nums<1){
System.out.println("nums的值不正确");
return;
        }
BoycurBoy=null;//辅助指针,帮助构建环形链表//使用for循环来创建环形链表for (inti=1; i<=nums; i++) {
//根据编号,创建小孩节点Boyboy=newBoy(i);
//如果是第一个小孩if (i==1){
first=boy;
first.setNext(first); //构成环curBoy=first;//让curBoy指向第一个小孩            }else {
curBoy.setNext(boy);
boy.setNext(first);
curBoy=boy;
            }
        }
    }
//遍历当前环形链表publicvoidshowBoy(){
//判断链表是否为空if (first==null){
System.out.println("链表为空,没有任何小孩");
return;
        }
//因为first不能动,因此我们仍然使用一个辅助指针完成遍历BoycurBoy=first;
while (true){
System.out.printf("小孩的编号%d\n",curBoy.getNo());
if (curBoy.getNext()==first){//说明已经遍历完毕break;
            }
curBoy=curBoy.getNext();  //curBoy后移        }
    }
}
//创建一个Boy类,表示一个节点classBoy{
privateintno;//编号privateBoynext;//指向下一个节点,默认nullpublicBoy(intno) {
this.no=no;
    }
publicintgetNo() {
returnno;
    }
publicvoidsetNo(intno) {
this.no=no;
    }
publicBoygetNext() {
returnnext;
    }
publicvoidsetNext(Boynext) {
this.next=next;
    }
}
复制代码

3.4代码实现(出圈操作)

1.需求创建一个辅助指针(变量)helper,事先应该指向环形链表的最后这个节点 补充:小孩报数前,先让first和helper移动k-1次


2.当小孩报数时,让first和helper指针同时的移动m-1次


3.这时就可以将first指向的小孩节点出圈 first = first.next helper.next=first 原来fist指向的节点就没有任何引用,就会被回收

//根据用户的输入,计算小孩出圈的顺序/*** @param startNo  表示从第几个小孩开始数数* @param countNum 表示数几下* @param nums     表示最初有多少小孩在圈中*/publicvoidcountBoy(intstartNo, intcountNum, intnums) {
//先对数据进行校验if (first==null||startNo<1||startNo>nums) {
System.out.println("参数输入有误,请重新输入");
return;
        }
//创建辅助指针,帮助小孩 出圈Boyhelper=first;
//需求创建一个辅助指针(变量)helper,事先应该指向环形链表的最后这个节点while (true) {
if (helper.getNext() ==first) {//说明helper指向最后小孩节点break;
            }
helper=helper.getNext();
        }
//小孩报数前,先让first和helper移动k-1次for (inti=0; i<startNo-1; i++) {
first=first.getNext();
helper=helper.getNext();
        }
//当小孩报数时,让first和helper指针同时的移动m-1次,然后出圈//这里是一个循环操作,知道圈中只有一个节点while(true){
if (helper==first){//说明圈中只有一个节点break;
            }
//让first和helper指针同时移动countNum-1for (inti=0; i<countNum-1; i++) {
first=first.getNext();
helper=helper.getNext();
            }
//这时first指向的节点,就是小孩要出圈的节点System.out.printf("小孩%d出圈\n",first.getNo());
//这时将first指向的小孩节点出圈first=first.getNext();
helper.setNext(first);
        }
System.out.printf("最后留在圈中的小孩编号%d\n",first.getNo());
    }
}
复制代码

需求引入

计算式:[7*2*2-5+1-5+3-3]

请问:计算机底层是如何运算得到结果的?注意不是简单的把算式列出运算,因为我们看这个算式7*2*2-5,但是计算机怎么理解这个算式的对计算机而言,它接收到的就是一个字符串),我们讨论的是这个问题。=>栈

1.介绍

  • 栈的英文为(stack)
  • 栈是一个先入后出(FILO-First In LastOut))的有序列表。
  • 栈(stack)是限制线性表中元素的插入和删除只能在线性表的同一端进行的种特殊线性表。允许插入和删除的一端,为变化的一端,称为栈顶(Top),另端为固定的一端,称为栈底(Bottom)。
  • 根据栈的定义可知,最先放入栈中元素在栈底,最后放入的元素在栈顶,而删除元素刚好相反,最后放入的元素最先删除,最先放入的元素最后删除
  • 出栈和入栈的概念(如图所示)

网络异常,图片无法展示
|

2.应用场景

  • 子程序的调用:在跳往子程序前,会先将下个指令的地址存到堆栈中,直到子程序执行完后再将地址取出,以回到原来的程序中。
  • 处理递归调用:和子程序的调用类似,只是除了储存下一个指令的地址外,也将参数、区域变量等数据存入堆栈中。
  • 表达式的转换[中缀表达式转后缀表达式]与求值(实际解决)。
  • 二叉树的遍历。
  • 图形的深度优先(depth一first)搜索法:

3.思路分析

网络异常,图片无法展示
|

  • 使用数组来模拟栈
  • 定义一个top来表示栈顶,初始化为1
  • 入栈的操作,当有数据加入到栈时,top++;stack[top]=data;
  • 出栈的操作,int value=stack[top];top--,return value;

4.代码实现

publicclassArrayStackDemo {
publicstaticvoidmain(String[] args) {
//测试一下ArrayStack//先创建一个Arraystack对象->表示栈ArrayStackstack=newArrayStack(4);
Stringkey="";
booleanloop=true;//控制是否退出菜单Scannerscanner=newScanner(System.in);
while(loop){
System.out.println("show:表示显示栈");
System.out.println("exit:退出程序");
System.out.println("push:添加数据到栈(入栈)");
System.out.println("show:从栈取出数据(出栈)");
System.out.println("请输入你的选择");
key=scanner.next();
switch (key){
case"show":
stack.list();
break;
case"push":
System.out.println("请输入一个数字");
intval=scanner.nextInt();
stack.push(val);
break;
case"pop":
try{
intres=stack.pop();
System.out.printf("出栈的数据是%d\n",res);
                    }catch (Exceptione){
System.out.println(e.getMessage());
                    }
break;
case"exit":
scanner.close();
loop=false;
break;
default:
break;
            }
        }
System.out.println("程序退出了");
    }
}
//定义一个ArrayStack 表示栈classArrayStack{
privateintmaxSize;//栈的大小privateint[] stack;//数组.数组模拟栈.数据就放在该数组中privateinttop=-1;//top表示栈顶,初始化位-1publicArrayStack(intmaxSize) {
this.maxSize=maxSize;
stack=newint[this.maxSize];
    }
//栈满publicbooleanisFull(){
returntop==maxSize-1;
    }
//栈空publicbooleanisEmpty(){
returntop==-1;
    }
//入栈-pushpublicvoidpush(intvalue){
//先判断栈是都满if (isFull()){
System.out.println("栈满");
return;
        }
top++;
stack[top]=value;
    }
//出栈-pop,将栈顶的数据返回publicintpop(){
//先判断栈是否空if (isEmpty()){
//抛出异常thrownewRuntimeException("栈空,没有数据");
        }
intvalue=stack[top];
top--;
returnvalue;
    }
//遍历栈的情况 遍历时,需要从栈顶开始显示数据publicvoidlist(){
if (isEmpty()){
System.out.println("栈空,没有数据");
return;
        }
for (inti=top; i>=0 ; i--) {
System.out.printf("stack[%d]=%d\n",i,stack[i]);
        }
    }
}


目录
相关文章
|
9月前
|
存储 监控 安全
企业上网监控系统中红黑树数据结构的 Python 算法实现与应用研究
企业上网监控系统需高效处理海量数据,传统数据结构存在性能瓶颈。红黑树通过自平衡机制,确保查找、插入、删除操作的时间复杂度稳定在 O(log n),适用于网络记录存储、设备信息维护及安全事件排序等场景。本文分析红黑树的理论基础、应用场景及 Python 实现,并探讨其在企业监控系统中的实践价值,提升系统性能与稳定性。
555 1
|
9月前
|
存储 监控 算法
基于跳表数据结构的企业局域网监控异常连接实时检测 C++ 算法研究
跳表(Skip List)是一种基于概率的数据结构,适用于企业局域网监控中海量连接记录的高效处理。其通过多层索引机制实现快速查找、插入和删除操作,时间复杂度为 $O(\log n)$,优于链表和平衡树。跳表在异常连接识别、黑名单管理和历史记录溯源等场景中表现出色,具备实现简单、支持范围查询等优势,是企业网络监控中动态数据管理的理想选择。
242 0
|
10月前
|
编译器 C语言 C++
栈区的非法访问导致的死循环(x64)
这段内容主要分析了一段C语言代码在VS2022中形成死循环的原因,涉及栈区内存布局和数组越界问题。代码中`arr[15]`越界访问,修改了变量`i`的值,导致`for`循环条件始终为真,形成死循环。原因是VS2022栈区从低地址到高地址分配内存,`arr`数组与`i`相邻,`arr[15]`恰好覆盖`i`的地址。而在VS2019中,栈区先分配高地址再分配低地址,因此相同代码表现不同。这说明编译器对栈区内存分配顺序的实现差异会导致程序行为不一致,需避免数组越界以确保代码健壮性。
218 0
栈区的非法访问导致的死循环(x64)
|
存储 算法 Java
算法系列之数据结构-二叉树
树是一种重要的非线性数据结构,广泛应用于各种算法和应用中。本文介绍了树的基本概念、常见类型(如二叉树、满二叉树、完全二叉树、平衡二叉树、B树等)及其在Java中的实现。通过递归方法实现了二叉树的前序、中序、后序和层次遍历,并展示了具体的代码示例和运行结果。掌握树结构有助于提高编程能力,优化算法设计。
411 10
 算法系列之数据结构-二叉树
|
10月前
232.用栈实现队列,225. 用队列实现栈
在232题中,通过两个栈(`stIn`和`stOut`)模拟队列的先入先出(FIFO)行为。`push`操作将元素压入`stIn`,`pop`和`peek`操作则通过将`stIn`的元素转移到`stOut`来实现队列的顺序访问。 225题则是利用单个队列(`que`)模拟栈的后入先出(LIFO)特性。通过多次调整队列头部元素的位置,确保弹出顺序符合栈的要求。`top`操作直接返回队列尾部元素,`empty`判断队列是否为空。 两题均仅使用基础数据结构操作,展示了栈与队列之间的转换逻辑。
|
算法 Java
算法系列之数据结构-Huffman树
Huffman树(哈夫曼树)又称最优二叉树,是一种带权路径长度最短的二叉树,常用于信息传输、数据压缩等方面。它的构造基于字符出现的频率,通过将频率较低的字符组合在一起,最终形成一棵树。在Huffman树中,每个叶节点代表一个字符,而每个字符的编码则是从根节点到叶节点的路径所对应的二进制序列。
399 3
 算法系列之数据结构-Huffman树
|
算法 Java
算法系列之数据结构-二叉搜索树
二叉查找树(Binary Search Tree,简称BST)是一种常用的数据结构,它能够高效地进行查找、插入和删除操作。二叉查找树的特点是,对于树中的每个节点,其左子树中的所有节点都小于该节点,而右子树中的所有节点都大于该节点。
553 22
|
存储 机器学习/深度学习 算法
C 408—《数据结构》算法题基础篇—链表(下)
408考研——《数据结构》算法题基础篇之链表(下)。
511 30
|
算法 调度 C++
STL——栈和队列和优先队列
通过以上对栈、队列和优先队列的详细解释和示例,希望能帮助读者更好地理解和应用这些重要的数据结构。
336 11
☀☀☀☀☀☀☀有关栈和队列应用的oj题讲解☼☼☼☼☼☼☼
### 简介 本文介绍了三种数据结构的实现方法:用两个队列实现栈、用两个栈实现队列以及设计循环队列。具体思路如下: 1. **用两个队列实现栈**: - 插入元素时,选择非空队列进行插入。 - 移除栈顶元素时,将非空队列中的元素依次转移到另一个队列,直到只剩下一个元素,然后弹出该元素。 - 判空条件为两个队列均为空。 2. **用两个栈实现队列**: - 插入元素时,选择非空栈进行插入。 - 移除队首元素时,将非空栈中的元素依次转移到另一个栈,再将这些元素重新放回原栈以保持顺序。 - 判空条件为两个栈均为空。
下一篇
开通oss服务