块状链表实现BigString大字符串操作(golang)

news/2024/11/28 5:36:22/

前言

块状链表是介于链表和数组之间的数据结构,能够在 O ( n ) O(\sqrt{n}) O(n )时间内完成插入、删除、访问操作。

数据结构如图所示。假设最大容量为 n n n, 则它有一个长度为 s = n s=\sqrt{n} s=n 的链表。链表中每个结点是一个长度为 2 × n 2 \times \sqrt{n} 2×n 的数组。

参考:https://oi-wiki.org/ds/block-list/
在这里插入图片描述
实现时,有两个细节需要注意:

  • 初始时,只有一个链表结点。随着数据越来越多,当某个结点内数组装满后,将分裂成两个结点。

  • 删除数据后,如果数据所在结点为空,则需要删除结点(链表首元结点不用删除)。

本文以BigString为例进行实现。

实现

使用golang实现如下字符串功能:

  • Append(str) 向字符串尾部添加一个字符串
  • Size() 获取字符串长度
  • Insert(index, char) 向字符串某个位置插入一个字符
  • Erase(index) 删除某个位置的字符
  • At(index) 获了某个位置的字符
  • Set(index, char) 设置某个位置的字符
package mainimport ("fmt""math"
)type _Node struct {next *_Nodesize intdata []rune
}type BigString struct {head    *_Node // 没有哨兵,直接就是首元结点size    int    // 字符串大小bukSize int    // 分组大小maxSize int    // 最大字符大小
}func NewBigString(maxLen int) *BigString {if maxLen < 10 {maxLen = 10}// 计算分段长度s := int(math.Sqrt(float64(maxLen)))return &BigString{head:    &_Node{nil, 0, make([]rune, 2*s)},size:    0,bukSize: s,maxSize: maxLen,}
}func (this *BigString) String() string {var str stringfor node := this.head; node != nil; node = node.next {for i := 0; i < node.size; i++ {str += string(node.data[i])}}return str
}/*
*
在尾部插入字符
*/
func (this *BigString) Append(chars string) {for _, char := range chars {this.Insert(this.size, rune(char))}
}/*
*
在尾部插入字符
*/
func (this *BigString) Size() int {return this.size
}/*
*
在指定位置插入字符
*/
func (this *BigString) Insert(index int, char rune) {if this.size < this.maxSize && index >= 0 && index <= this.size {pos := -1for node := this.head; node != nil; node = node.next {if index <= node.size+pos+1 {insertPos := index - pos - 1 // 0 1 2 3 4 | 5 6 7   , index = 6,for j := node.size; j > insertPos; j-- {node.data[j] = node.data[j-1]}node.data[insertPos] = charnode.size++// 结点分裂开if node.size == len(node.data) {node2 := &_Node{node.next, this.bukSize, make([]rune, 2*this.bukSize)}for j := 0; j < this.bukSize; j++ {node2.data[j] = node.data[j+this.bukSize]}node.size -= this.bukSizenode.next = node2}break}pos += node.size}this.size++}
}/*
*
删除指定位置字符
*/
func (this *BigString) Erase(index int) {if index >= 0 && index < this.size {pos := -1var pre *_Node = nilfor node := this.head; node != nil; node = node.next {if index <= node.size+pos {deletePos := index - pos - 1for j := deletePos + 1; j < node.size; j++ {node.data[j-1] = node.data[j]}node.size--// 清理空结点if node.size == 0 {if node != this.head {pre.next = pre.next.next}}break}pos += node.sizepre = node}this.size--}
}/*
*
获取指定位置字符
*/
func (this *BigString) At(index int) rune {if index >= 0 && index < this.size {pos := -1for node := this.head; node != nil; node = node.next {if index <= node.size+pos {atPos := index - pos - 1return node.data[atPos]}pos += node.size}}return 0
}/*
*
设置指定位置字符
*/
func (this *BigString) Set(index int, char rune) {if index >= 0 && index < this.size {pos := -1for node := this.head; node != nil; node = node.next {if index <= node.size+pos {atPos := index - pos - 1node.data[atPos] = charbreak}pos += node.size}}
}

测试

测试结果与测试代码如下。结果表明实现是正确的。

在这里插入图片描述

str := NewBigString(225)// 测试 Append, Insert, Stringfmt.Println("【测试 Append, Insert, String】")str.Append("hello world! my name is cloudea. this is my first big string implementation!\n")str.Append("世界 你好! 我的我名字是克劳迪亚。这是我的第一个大字符串实现哦!\n")fmt.Println(str)str.Insert(0, '*')str.Insert(78, '#')fmt.Println(str)for i := 0; i < 40; i++ {str.Insert(100, '$')}fmt.Println(str)// 测试Erasefmt.Println("【测试 Erase】")for i := 0; i < 40; i++ {str.Erase(100)}fmt.Println(str)// 测试测试At 和 Setfmt.Println("【测试At 和 Set】")str.Set(99, '你')str.Set(100, '呀')str.Set(101, 'd')str.Set(102, '二')str.Set(103, '个')for i := 0; i < str.Size(); i++ {fmt.Print(string(str.At(i)))}fmt.Println()

http://www.ppmy.cn/news/62871.html

相关文章

配置本地Angular环境并使用VsCode调试Angular前端项目

配置本地Angular环境并使用VsCode调试Angular前端项目 配置本地Angular环境部署Node.Js本地环境配置一下环境变量 使用vscode调试Angular安装vscode 配置本地Angular环境 部署Node.Js本地环境 1 从官网下载node.js, 本文为(v16.13.0) 下载地址: https://nodejs.org/dist/v16.…

硬件设计 之 PCIe常用知识

以下是本人在自己在设计PCIe中常遇到的一些知识&#xff0c;对他们进行了简单整理一下&#xff0c;包括基本定义、传输速率、layout要求等。比如作为硬件工程师要了解芯片架构&#xff0c;哪些PCIe接口可以使用&#xff0c;使用这些PCIe要做什么&#xff0c;需要使用PCIe x1还是…

GRPC - JAVA笔记

GRPC - JAVA笔记 gRPC简介 由google开源的一个高性能的RPc框架&#xff0c;由google内部的Stubby框架演化而来。2015年正式开源。云原生时代的RPC标准&#xff0c;由Go语言开发 gRPC的核心设计思路 网络通信 ------> gRPC 自己封装了网络通信的部分&#xff0c;提供了多种…

为什么越来越多的 IT 人考软考?

近几年随着国家计算机与软件技术的发展&#xff0c;每年报名参加软考考试的人也越来越多。据工信部新闻发布会消息&#xff0c;计算机软件与通信专业技术人员职业资格考试累计报考人数超过485万&#xff0c;2022年报考人数129万人。 为什么越来越多的IT人考软考证书&#xff1…

代码随想录复习 707设计链表 翻转链表,两两交换节点

代码如下 type Node struct { //定义一个节点 &#xff0c;包含一个数据变量一个指针 Val int Next *Node } type MyLinkedList struct { //定义一个链表 &#xff0c;链表里面有一个虚拟头节点&#xff0c;和大小 Dummayhead *Node Size int } func Constructor(…

5月7日 2H55min|5月8日8H50min|时间轴复盘|14:00~14:30

5月8日 todo list list4 40min ✅ |实际上用了50+50 list6 40min ✅ |实际上用了30+60 阅读+听力连做 100min ✅ 口语 day01 ✅ 口语 day02 口语 day03

Vmware虚拟机问题解决方案

Vmware虚拟机问题解决方案 1. 运行虚拟机系统蓝屏 可能的原因有两个: 1). 虚拟机所在磁盘的空间不足 ; -------> 清理磁盘空间 。 2). 操作系统版本高, 需要适配新版本的Vmware ; ------> 卸载Vmware15版本, 安装Vmware16版本 。 2. 卸载Vmware步骤 1). 卸载已经安…

【Java】字符串模板拼接的方法

引 在Java中&#xff0c;构建字符串是非常常见的操作。在很多时候&#xff0c;我们都需要使用变量或输入来定制一个文本输出&#xff0c;例如打印日志、生成HTML代码或构建错误消息。而当需要进行字符串连接时&#xff0c;字符串模板是一种常用的方法。在本篇博客中&#xff0…