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))