首页 > 其他分享 >链表/栈/队列/KMP

链表/栈/队列/KMP

时间:2023-07-28 18:55:59浏览次数:46  
标签:head 下标 idx 队列 ne 链表 int KMP 节点

  • 链表

    • 用数组模拟,不同于结构体加指针
    • 调用new关键字开上万级别的节点非常慢,基本会超时
    • 单链表

      • 来构造邻接表
      • 用于存图与树
      • 基本结构:
        • head 表示头结点的下标
        • e[i] 表示节点i的值
        • ne[i] 表示节点i的下一个节点的下标
        • idx 存储当前已经用到了哪个节点,表示新节点
      • 基本操作:
        • 向链表头插入一个节点
        • 在节点k后面插入一个节点
        • 删除节点k后面的一个节点
      • 模板:
        int head;//头指针,指向头结点
        int e[N];//e[i]表示节点i的值
        int ne[N],//en[i]表示节点i的下一个节点 
        int idx;//存储新节点的下标
        
        //初始化
        void init(){
            head = 0; //0代表空节点
            idx = 1;//第一个插入的节点的下标为1
        }
        
        //头插法
        void add_to_head(int x){
            e[idx] = x; //存值
            ne[idx] = head; //连接
            head = idx; //转移连接
            idx ++ ; //
        }
        
        //在下标为k的节点后面插入一个数
        void add(int k, int x){
            e[idx] = x;
            ne[idx] = ne[k];
            ne[k] = idx;
            idx ++ ;
        }
        
        //删除下标为k的节点的后面的数
        void del(int k){
            ne[k] = ne[ne[k]];
        }
        
        //头删法,删除头结点
        void del_the_head(){
            head = ne[head];
        }
        
        //遍历输出所有节点
        for(int i = head; i; i = ne[i]) cout << e[i]; 
        
    • 双链表

      • 用于优化某些问题
      • 基本结构:
        • l[i] 存储下标为i的节点的右边的节点
        • r[i] 存储下标为i的节点的左边的节点
        • e[i] 存储下标为i的节点的值
        • idx 存储新节点的下标
        • 默认0表示空的头结点,1 表示空的尾节点,所有节点在0与1之间插入
      • 模板:
        const int N = 1e5 + 10;
        int l[N], r[N], e[N], idx;
        
        //初始化
        void init(){
        	//0表示空头节点,1表示空尾节点
            r[0] = 1; 
            l[1] = 0;
            idx = 2; //1,0已经被使用,初始化为2,表示第一个插入的节点的下标为2
        }
        
        //在下标为k的节点后面插入节点
        void add(int k, int x){
            e[idx] = x; //赋值
            l[idx] = k; //连接左
            r[idx] = r[k]; //连接右
            l[r[idx]] = idx; //转移连接
            r[l[idx]] = idx; //转移连接
            idx ++ ; //更新下标
        }
        
        //删除下标为k的节点
        void del(int k){
            r[l[k]] = r[k];
            l[r[k]] = l[k];
        }
        
        //遍历输出节点,注意起点与终点
        for(int i = r[0]; i != 1; i = r[i]) cout << e[i];
        
        //以下是统一插入个数与下标的代码
        //初始化
        void init(){
        	//0表示空头结点,N - 1表示空尾节点
        	r[0] = N - 1;
        	l[N - 1] = 0;
        	idx = 1; //0,N - 1被使用,下标从1开始,表示第一个插入的节点下标就是1
        }
        //add函数不变
        //遍历输出,注意起点和终点
        for(int i = r[0]; i != N - 1; i = r[i]) cout << e[i];
        
  • 邻接表

    • 一堆单链表,单链表数组
    • 先进后出
    • 模板:
      int stk[N], tt;//声明栈和栈顶下标
      stk[ ++ tt] = x; //x入栈
      tt --; //出栈
      stk[tt]; //取栈顶元素
      if(tt > 0) not empty //判断是否为空
      else empty
      
    • 单调栈:
      • 应用:在一段序列中求距离某数最近的最大值/最小值
  • 队列

    • 先进先出
    • 模板:
      int q[N], hh, tt = -1; //声明队列,队首下标,队尾下标
      q[ ++ tt] = x; //入队只能从队尾
      hh --; //出队只能从队首
      q[hh];//取队首
      q[tt];//取队尾
      if(hh <= tt)not empty //判断是否为空
      else empty
      
    • 单调队列(单调双端队列):
      • 引用:求固定大小的滑动窗口的最大值/最小值
  • KMP

    • 模式串匹配算法
    • 模板:
      int s[N], p[M];//主串和模式串,下标从1开始
      
      //求next数组
      void get_next(){
      	for(int i = 2, j = 0; i <= m; ++ i){
      		while(j && p[i] != p[j + 1]) j = ne[j];//j可以回跳并且匹配不成功时, j回跳
      		if(p[i] == p[j + 1]) j ++ ; //匹配成功
      		ne[i] = j; //存i可以回跳的位置
      	}
      }
      
      //KMP
      for(int i = 1, j = 0; i <= n; ++ i){
      	while(j && s[i] != p[j + 1]) j = ne[j]; //同上
      	if(s[i] == p[j + 1]) j ++ ;
      	if(j == n){ //当j等于模式串的长度时匹配成功
      		j = ne[j]; //继续进行下一次匹配
      		cout << i - n << endl; //输出匹配的起点下标
      	}
      }
      //j = ne[j] ,j往前跳,相当于字串往后移
      

标签:head,下标,idx,队列,ne,链表,int,KMP,节点
From: https://www.cnblogs.com/moilip/p/17588693.html

相关文章

  • 数据结构中队列的存储和应用
    队列:只有两个口进出数据,一个专门进入数据,另一个专门出数据,先进先出,FIFO表 一、顺序队列:存储元素的连续内存的首地址容量队头位置(出队)队尾位置(入队)[元素数量]运算:创建、销毁、清空、出队、入队、队空、队满、队头、队尾、元素数量#inclu......
  • 单链表查找与删除
    单链表是一种常见的数据结构,它由一系列的节点组成,每个节点包含一个数据元素和一个指向下一个节点的指针。在单链表中,查找和删除节点是常见的操作。1.单链表查找:要查找单链表中的一个节点,需要从链表的头节点开始,沿着指针依次遍历每个节点,直到找到目标节点或者到达链表的末尾(即指针......
  • 剑指 Offer 09. 用两个栈实现队列(简单)
    题目:classCQueue{public:stack<int>st1;stack<int>st2;CQueue(){}voidappendTail(intvalue){st1.push(value);}intdeleteHead(){if(st1.empty()&&st2.empty())return-1;......
  • Java 本地队列
    实现Java本地队列1.理解本地队列在开始实现Java本地队列之前,首先需要明确什么是队列。队列是一种先进先出(FIFO)的数据结构,类似于我们平常排队的场景。在编程中,队列常常被用来存储需要按照一定顺序处理的数据。Java提供了一个Queue接口,它是Collection接口的子接口,定义了......
  • 数据结构练习笔记——求解由单链表表示的一元多项式的值
    求解由单链表表示的一元多项式的值【问题描述】一个形如\[a_0x^0+a_1x^1+...+a_nx^n\]的一元多项式含有n+1项,每一项由系数和指数唯一确定,可表示成由系数项和指数项构成的一个二元组(系数,指数),一元多项式则可以表示成二元组的集合{(a0,0),(a1,1),(a2,2)...(an,n)},可看成是数据......
  • 问题--链表指针传参,修改next指针只传值
    1.问题--链表指针传参,修改next指针只传值Link_creat_head(&head,p_new);//将新节点加入链表在这当中head头指针传的是地址,而p_new传的是值,这二者有什么区别?#include<stdio.h>#include<stdlib,h>//定义结点结构体typedefstructstudent{//数据域intnum;......
  • 队列
    实现代码:importjava.util.Scanner;publicclassTest1{publicstaticvoidmain(String[]args){//测试ArrayQueuearrayQueue=newArrayQueue(3);charkey='';//接受用户输入Scannerscanner=newScanner(System.in);......
  • kmp算法的个人理解
    最长前后缀:假设有一段字符串:"aabaa"则这段字符串的前缀有:aaaaabaaba后缀:aaabaaabaa求最长公共前后缀的方法:找到前缀和后缀中相同的字符串:aaa其中最长的字符串为aa则"aabaa"这个字符串的最长公共前后缀为aaaa其长度为2按照以上的方式逐个计算"aabaa"中的每个子字符串得到......
  • 数据结构练习笔记——循环队列的基本操作
    循环队列的基本操作【问题描述】根据循环队列的类型定义,完成循环队列的基本操作。主函数中测试队列。【输入形式】一个整数m,表示入队的元素个数【输出形式】第一行:输出队头元素第二行:队列中元素依次出队以空格间隔【样例输入】5【样例输出】113579【样例输入】0【样......
  • Redis实现消息队列
    Redis基于内存,高性能并且提供多种数据结构供使用,那么对于Redis能不能作为消息队列?以及与专业的消息队列,如RocketMQ,Kafka等差距又在哪里?Redis提供多种方式实现消息队列,基于List,基于Pub/Sub等,如今基本广泛使用的是Redis5.0之后推出的Stream流格式,其具有支持持久化,支持消......