• 线段树做大数据排序


    const fs=require('fs');
    //比较字符基类大小 相同返回0,str1>str2 返回1,str1<str2 返回-1,
    function str_compare(str1,str2){
    let index=0;
    let dis=0;
    while (dis===0&&index<str1.length){
    if(str1.charCodeAt(index)>str2.charCodeAt(index)){
    dis=1
    }else if(str1.charCodeAt(index)<str2.charCodeAt(index)){
    dis=-1
    }else{
    index++;
    if(index>str2.length){
    dis=1;
    }
    }
    }
    if(dis===0&&index<str2.length){
    dis=-1
    }
    return dis;
    }
    //用二分法查找最近的字符位置
    function str_find(str,hasSortArr,callback) {
    let l=0,r=hasSortArr.length;
    let index=-1;
    if(hasSortArr.length>0){
    const ri=callback(str,hasSortArr[r-1]);
    if(ri===1){
    return [r,-1]
    }else if(ri===0){
    return [r-1,r-1]
    }else{
    r=r-1;
    }
    const li=callback(str,hasSortArr[0]);
    if(li===-1){
    return [0,-1]
    }else if(li===0){
    return [0,0]
    }else{
    l=l+1;
    }
    while(r-l>0){
    const m=(l+r)>>1;
    //比较下坐标大小
    const order=callback(str,hasSortArr[m])
    if(order===1){
    l=Math.max(l+1,m)
    }else if(order===-1){
    r=Math.min(r-1,m)
    }else{
    l=r=m;
    index=m;
    }
    }
    }
    return [(l+r)>>1,index]
    }
    //线段树做大数据排序
    const tree={
    getData(i){
    const arr=JSON.parse(fs.readFileSync(this.dir+i+'.json'))
    return arr;
    },
    setData(i,obj){
    fs.writeFileSync(this.dir+i+'.json',JSON.stringify(obj))
    },
    init(){
    this.dir=__dirname+ '/treeData/';
    this.pageSize=1;
    this.rangeArr=[];
    //分页排序
    this.sort1();
    //排序合并
    this.sort2()
    console.log(this.rangeArr)
    },
    //分段排序
    sort1(){
    const rangeArr=this.rangeArr;
    let index=0;
    let narr=[]
    const pageSize=this.pageSize;
    const list=fs.readdirSync(this.dir).filter(function (name) {
    return /^d+.json/.test(name)
    });
    const temp=[]
    for(let j=0;j<list.length;j++){
    const name=j+'.json';
    const obj=JSON.parse(fs.readFileSync(this.dir+name));

    if(narr.length===0&&obj.data.length===pageSize&&index===j){
    rangeArr[index]=[obj.data[0].key,obj.data[obj.data.length-1].key]
    index++;
    }else{
    fs.unlinkSync(this.dir+name)
    for(let i=0;i<obj.data.length;i++){
    const [n,d]=str_find(obj.data[i],narr,function (obj1,obj2) {
    return str_compare(obj1.key,obj2.key);
    });
    if(d===-1){
    narr.splice(n,0,obj.data[i])
    if(narr.length===pageSize){
    if(index>j){
    temp.push(index)
    fs.writeFileSync(this.dir+'t_'+index+'.json',JSON.stringify({
    data:narr,
    }))
    }else{
    fs.writeFileSync(this.dir+index+'.json',JSON.stringify({
    data:narr,
    }))
    }
    rangeArr[index]=[narr[0].key,narr[narr.length-1].key]
    index++;
    narr=[]
    }
    }
    }
    }
    }
    if(narr.length>0){
    rangeArr[index]=[narr[0].key,narr[narr.length-1].key]
    fs.writeFileSync(this.dir+index+'.json',JSON.stringify({
    data:narr,
    }))
    index++;
    }
    if(temp.length>0){
    for(let i=0;i<temp.length;i++){
    fs.renameSync(this.dir+'t_'+temp[i]+'.json',this.dir+temp[i]+'.json',)
    }
    }
    },
    //排序合并
    sort2(){
    const rangeArr=this.rangeArr;

    for(let j=0;j<rangeArr.length-1;j++){
    const obj1=this.getData(j)
    const arr1=obj1.data;
    const range1=rangeArr[j];
    for(let i=j+1;i<rangeArr.length;i++){
    const range2=rangeArr[i];
    //排序不对,需要交换
    if(str_compare(range1[1],range2[0])===1){
    //第一个的最大值和第二个的最小值做交换,
    const obj2=this.getData(i)
    const arr2=obj2.data;
    do{
    const str1=arr1.pop();
    const str2=arr2.shift();
    const [n1,index1]=str_find(str2,arr1,function (item1,item2) {
    return str_compare(item1.key,item2.key)
    });
    if(index1===-1){
    if(n1===arr1.length){
    range1[1]=str2;
    }else if(n1===0){
    range1[0]=str2;
    }
    arr1.splice(n1,0,str2)
    }
    const [n2,index2]=str_find(str1,arr2,function (item1,item2) {
    return str_compare(item1.key,item2.key)
    });
    if(index2===-1){
    if(n2===arr2.length){
    range2[1]=str1;
    }else if(n2===0){
    range2[0]=str1;
    }
    arr2.splice(n2,0,str1)
    }

    }while (str_compare(arr1[arr1.length-1].key,arr2[0].key)===1)

    this.setData(i,obj2)
    }
    }
    this.setData(j,obj1)
    }
    },
    //key的增删改查
    setItem(key,val){
    const rangeArr=this.rangeArr;
    const [n1,index1]=str_find(key,rangeArr,function (str1,range) {
    if(str_compare(str1,range[0])===-1){
    return -1
    }else if(str_compare(str1,range[1])===1){
    return 1
    }else{
    return 0
    }
    });
    if(n1<rangeArr.length){
    const obj1=this.getData(n1)
    const [n2,index2]=str_find(key,obj1.data,function (str1,item) {
    return str_compare(str1,item.key);
    });
    if(index2!==-1){
    if(val===null){
    obj1.data.splice(n2,1)
    }else{
    obj1.data[n2]={key,val}
    }
    }else{
    obj1.data.splice(n2,0,{key,val})
    rangeArr[n1][0]=obj1.data[0].key
    rangeArr[n1][1]=obj1.data[obj1.data.length-1].key
    }
    if(obj1.data.length===0&&n1===rangeArr.length-1){
    rangeArr.pop()
    fs.unlinkSync(this.dir+n1+'.json')
    }else{
    this.setData(n1,obj1)
    }

    return [n1,n2]
    }else if(val!==null){
    const obj1={
    data:[{key,val}]
    }
    rangeArr[n1]=[]
    rangeArr[n1][0]=key
    rangeArr[n1][1]=key
    this.setData(n1,obj1)
    return [n1,0]
    }
    return [n1,index1]
    }

    }
    tree.init();
    console.log(tree.setItem('222',null))
    console.log(tree.setItem('222',21))
  • 相关阅读:
    Javascript模块化开发2——Gruntfile.js详解
    Javascript模块化开发1——package.json详解
    数据库性能优化策略
    HTTP协议学习笔记
    Redis五种基本数据类型底层实现
    浅谈单元测试
    Lambda 表达式有何用处?如何使用?
    快捷键和常用的命令
    Homebrew安装和Mac使用
    为什么String要设计成不可变的?
  • 原文地址:https://www.cnblogs.com/caoke/p/13228016.html
Copyright © 2020-2023  润新知