go语言[3]-数据结构-递归树构建17亿数据的内存模型

栏目: Go · 发布时间: 5年前

内容简介:用递归的方式实现了一颗树状的结构,该模型可以处理上亿qq数据。内存中查询10次既可以找到结果,速度非常快。虽然将数据全部放置在了内存中,但是内存的消耗应该是降低到了最低的。相较于C语言,这段代码明显就要难看了很多。因为Go语言是类型安全的语言,安全的的背后就是效率的损失。

递归树

用递归的方式实现了一颗树状的结构,该模型可以处理上亿qq数据。

内存中查询10次既可以找到结果,速度非常快。虽然将数据全部放置在了内存中,但是内存的消耗应该是降低到了最低的。

相较于C语言,这段代码明显就要难看了很多。因为 Go 语言是类型安全的语言,安全的的背后就是效率的损失。

/*
Copyright © 2018 jonson
功能:在上亿乱序的qq账号密码数据文件中构建递归树,能够在不到1秒的时间内查询出指定账号的密码。
代码基于泄漏的qq老密,加群获取文件
*/
package main

import (
	"bufio"
	"fmt"
	"log"
	"os"
	"strings"
	"unsafe"
)
var g_pp = make([]*[]*byte,10)
func main() {
	search()
}
//初始化构建内存模型
func init(){
	fmt.Println("初始化开始")
	file, err := os.Open("1E~001.txt")
	if err != nil {
		log.Fatal(err)
	}
	defer file.Close()
	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		str:= scanner.Text()

		if len(str) <50{//数据已经整理过,最多50位。
			qq:= getQQ(str)
			//fmt.Println(qq)
			if len(qq)==10  && isAllNum(qq){
				//递归树,将模型构建完毕。
				assign(&g_pp,11,qq,str)
			}
		}
	}

	if err := scanner.Err(); err != nil {
		log.Fatal(err)
	}

	fmt.Println("初始化结束")
}


/*
最重要的递归函数,pp指针。deep为深度,str为字符串,password为密码
*/
func assign(pp *[]*[]*byte, deep int, str string,password string) {

	//最后一级指针时,开辟内存,存储密码。
	if deep == 1 {

		buf:= make([]*byte,10)
		(*pp)[getnum(str[10-deep])] = &buf
		p:= (*string)(unsafe.Pointer((*pp)[getnum(str[10-deep])]))
		*p = password
		return
	}

	//刚开始传递11级指针的地址,deep=11递归下去,可以省略,改为传递11级指针,deep=10。
	if deep == 11 {
		assign((*[]*[]*byte)(unsafe.Pointer(pp)), deep - 1, str,password);
		return
	}
	//判断该指针是否为空。如1131052403,当deep=10时,取出第一个数字1.判断pp[1]是否为Nil,为Nil就说明从来没有出现过第10位为1的qq号。
	//这时就会为pp[1]开辟10个指针大小的内存,初始化为空。
	//如果已经存在就继续递归。
	if (*pp)[getnum(str[10-deep])]!=nil{
		assign((*[]*[]*byte)(unsafe.Pointer((*pp)[getnum(str[10-deep])])), deep - 1, str,password);
	}else {
		buf:= make([]*byte,10)
		(*pp)[getnum(str[10-deep])] = &buf
		assign((*[]*[]*byte)(unsafe.Pointer((*pp)[getnum(str[10-deep])])), deep - 1, str,password);
	}
}

//字符转换为数字
func getnum(u uint8) uint8{
	 return u - '0'
}

//qq补齐位数,判断是否为数字,字符转换为数字,数字不足补充0的算法
//获取QQ号 1131052403----qwerty
//截取数字10位,不足的补0,
//对于这个函数的改进,让我可以在查找qq函数时也可以用
func getQQ(s string) string{
	raw:= strings.Split(s,"----")[0]
	length := len(raw)
	if length < 10 {
		raw =  strings.Repeat("0",10-length) + raw
	}
	return raw
}

//判断qq全部为数字
func isAllNum(qq string ) bool{
	for _,ch := range qq{
		if ch < '0' || ch > '9'{
			return false
		}
	}
	return true
}



/*
根据初始化递归树的原理,我们可以明白判断是否存在的意义。
如果在某一位出现了一个数字,其所在的指针为NULL,就说明在该位从来没有出现过这个数字。
相反,如果存在该数字,就首先说明其每一位的指针都不为空。

*/
var flag = true
var findresult string = ""
func isExit(pp *[]*[]*byte, deep int, str string) {

	if deep == 1 {
		if (*pp)[getnum(str[10-deep])]!=nil{
			findresult = *(*string)(unsafe.Pointer((*pp)[getnum(str[10-deep])]))
		}
		return
	}

	if deep == 11 {
		isExit((*[]*[]*byte)(unsafe.Pointer(pp)), deep - 1, str);
		return
	}

	if flag && (*pp)[getnum(str[10-deep])]!=nil{
		isExit((*[]*[]*byte)(unsafe.Pointer((*pp)[getnum(str[10-deep])])), deep - 1, str);
	}else {

		flag = false
		return
	}
}

//查找qq号
func search(){
	input := bufio.NewScanner(os.Stdin)
	for input.Scan(){
			flag = true
			findresult=""

			qq:= input.Text()
		  qq= getQQ(qq)
		  fmt.Println("搜索qq号:",qq)
		isExit(&g_pp,11,qq)
			if isAllNum(qq) && findresult!=""{
					fmt.Printf("结果为:%s\n",findresult)
			}
	}
}

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

现代操作系统(原书第4版)

现代操作系统(原书第4版)

[荷] Andrew S. Tanenbaum、[荷] Herbert Bos / 陈向群、马洪兵 等 / 机械工业出版社 / 2017-7 / 89.00

Andrew S. Tanenbaum教授编写的教材《现代操作系统》现在已经是第4版了。第4版在保持原有特色的基础上,又增添了许多新的内容,反映了当代操作系统的发展与动向,并不断地与时俱进。 对比第3版,第4版有很多变化。一些是教材中多处可见的细微变化,一些是就某一功能或机制增加了对最新技术的介绍,如增加了futex同步原语、读–复制–更新(Read-Copy-Update)机制以及6级RA......一起来看看 《现代操作系统(原书第4版)》 这本书的介绍吧!

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具