基于trie树的具有联想功能的文本编辑器
之前的软件设计与开发实践课程中,自己构思的大作业题目。做的具有核心功能,但是还欠缺边边角角的小功能和持久化数据结构,先放出来,有机会一点点改。github:https://github.com/chuxiuhong/smarteditor
数据结构,使用过程截图以及源代码如下:
#数据结构
**trie树**
trie树相应的介绍点击链接 https://en.wikipedia.org/wiki/Trie
trie树在python文件中的类型定义
Node定义
#GUI设计界面
首先,用较大的文本文件进行训练,完成trie的树的训练。本文件夹下提供了一个big2.txt文件作为示例。
在之后的输入会弹出提示框
- #!/usr/bin/python
- # -*- coding: utf-8 -*-
- import PyQt4
- from PyQt4.QtCore import *
- from PyQt4.QtGui import *
- import PyQt4.QtCore
- import sys
- import pickle
- print '===================start======================='
- class Node:
- def __init__(self):
- self.value = None
- self.children = {} # children is of type {char, Node}
- self.fre = 0
- self.father = None
- def CMP(a, b):
- return b.fre - a.fre
- class Trie:
- def __init__(self):
- self.root = Node()
- self.choose = []
- self.__OpenCorrect__ = 0
- def insert(self, key): # key is of type string
- # key should be a low-case string, this must be checked here!
- node = self.root
- for char in key:
- if char not in node.children:
- child = Node()
- node.children[char] = child
- child.value = char
- child.father = node
- node = child
- else:
- node = node.children[char]
- # node.value = key
- node.fre += 1
- def search(self, key):
- node = self.root
- for char in key:
- if char not in node.children:
- return None
- else:
- node = node.children[char]
- return node.value
- def display_node(self, node):
- if (node.value != None):
- print node.value
- for char in 'abcdefghijklmnopqrstuvwxyz':
- if char in node.children:
- self.display_node(node.children[char])
- return
- def fallback(self, node):
- f_char = ''
- while node != self.root:
- f_char = node.value + f_char
- node = node.father
- # print f_char
- return f_char
- def display(self):
- self.display_node(self.root)
- def find_node(self, string):
- res_node = self.root
- for i in string:
- res_node = res_node.children[i]
- return res_node
- def association(self, node):
- # 调用此函数前应该先将self.choose恢复成空列表
- if (node.value != None):
- if node.fre > 0:
- self.choose.append(node)
- for char in 'abcdefghijklmnopqrstuvwxyz':
- if char in node.children:
- self.association(node.children[char])
- def output_association(self, char):
- char = str(char).lower()
- self.choose = []
- result_list = []
- self.association(self.find_node(char))
- self.choose.sort(cmp=CMP)
- if len(self.choose) > 0:
- for i in self.choose:
- result_list.append(self.fallback(i))
- if self.__OpenCorrect__ == 0:
- result_list.insert(1, self.correct(char))
- # print 'result_list',result_list
- return result_list
- def correct(self, string):
- self.choose = []
- p = self.find_node(string[:-1])
- self.association(p)
- self.choose.sort(cmp=CMP)
- if len(self.choose) > 1:
- return self.fallback(self.choose[0])
- def train(trie, path):
- # f = open(r'big2.txt')
- f = open(path)
- word = f.read()
- f.close()
- word = word.split(' ')
- for i in word:
- trie.insert(i)
- trie = Trie()
- trie.__OpenCorrect__ = 0
- def save_model(T):
- f1 = open("trie.pkl", 'wb')
- pickle.dump(T, f1)
- f1.close()
- def load_model(path):
- f2 = open(path, 'rb')
- trie = pickle.load(f2)
- f2.close()
- print '================= END ====================='
- class UI(QDialog):
- def __init__(self, parent=None):
- super(UI, self).__init__(parent)
- QSList = QStringList()
- # default
- # QSList<<'One'<<'Tow'<<'Three'<<'Four'<<'Five'
- # instance of Completer class
- cmp = Completer(QSList)
- global edit
- edit = TextEdit()
- edit.setFontPointSize(80)
- edit.setCompleter(cmp)
- self.setWindowTitle(u"智能文本编辑器")
- button1 = QPushButton(u"训练模型")
- button2 = QPushButton(u"保存文本文件")
- button3 = QPushButton(u"打开文本文件")
- '''
- buttons = QushButton()
- '''
- '''
- 定义按钮,()内为按钮名称
- '''
- self.connect(button1, SIGNAL("clicked()"), self.get_file)
- self.connect(button2, SIGNAL("clicked()"), self.func2)
- self.connect(button3, SIGNAL("clicked()"), self.func3)
- '''
- 关联按钮与函数格式同上,触发为clicked()单击,最后一个参数为
- 类内函数
- '''
- layout = QGridLayout()
- layout.addWidget(edit, 0, 1, 1, 5)
- layout.addWidget(button1, 2, 1)
- layout.addWidget(button2, 2, 3)
- layout.addWidget(button3, 2, 5)
- '''
- 按钮布局
- '''
- self.setLayout(layout)
- self.center()
- def center(self):
- screen = QDesktopWidget().screenGeometry()
- size = self.geometry()
- self.move((screen.width() - size.width()) / 2, (screen.height() - size.height()) / 2)
- def get_file(self):
- s = QFileDialog.getOpenFileName(self, "Open file dialog", "/", "TXT Files(*.txt)")
- train(trie, s)
- def func2(self):
- s = QFileDialog.getSaveFileName(self, "文件保存", "C:/", "All Files (*);Text Files (*.txt)")
- f = open(s, 'w')
- f.write(edit.toPlainText())
- f.close()
- def func3(self):
- s = QFileDialog.getOpenFileName(self, "Open file dialog", "/", "TXT Files(*.txt)")
- f = open(s)
- edit.setText(PyQt4.QtCore.QString(f.read()))
- f.close()
- class TextEdit(QTextEdit):
- def __init__(self, parent=None):
- super(TextEdit, self).__init__(parent)
- self.cmp = None
- self.p = ''
- self.count = 0
- def setCompleter(self, completer):
- if self.cmp:
- self.disconnect(self.cmp, 0, 0)
- self.cmp = completer
- if (not self.cmp):
- return
- self.cmp.setWidget(self)
- self.cmp.setCompletionMode(QCompleter.PopupCompletion)
- self.cmp.setCaseSensitivity(Qt.CaseInsensitive)
- self.connect(self.cmp, SIGNAL('activated(QString)'), self.insertCompletion)
- def completer(self):
- return self.cmp
- def insertCompletion(self, string):
- # get cursor position
- tc = self.textCursor()
- # selectd ranges
- tc.movePosition(QTextCursor.StartOfWord, QTextCursor.KeepAnchor)
- # replace selected ranges
- tc.insertText(string)
- self.p += str(string)
- # set cursor pos back to original pos
- self.setTextCursor(tc)
- def textUnderCursor(self):
- tc = self.textCursor()
- tc.select(QTextCursor.WordUnderCursor)
- return tc.selectedText()
- def keyPressEvent(self, e):
- '''
- if e.key() != Qt.Key_Backspace:
- self.p = self.p + e.text()
- self.count+=1
- print 'yes'
- else:
- self.p = self.p[:-1]
- self.count-=1
- '''
- print 'p ', self.p
- print 'pressed >> ', e.text()
- if (self.cmp and self.cmp.popup().isVisible()):
- if e.key() in (Qt.Key_Enter, Qt.Key_Return, Qt.Key_Escape, Qt.Key_Tab, Qt.Key_Backtab):
- e.ignore()
- return
- isShortcut = ((e.modifiers() & Qt.ControlModifier) and e.key() == Qt.Key_E)
- if (not self.cmp or not isShortcut):
- super(TextEdit, self).keyPressEvent(e)
- ctrlOrShift = e.modifiers() & (Qt.ControlModifier | Qt.ShiftModifier)
- if (not self.cmp or (ctrlOrShift and e.text().isEmpty())):
- return
- eow = QString("~!@#$%^&*()_+{}|:\"<>?,./;'[]\\-=")
- hasModifier = (e.modifiers() != Qt.NoModifier) and not ctrlOrShift
- completionPrefix = self.textUnderCursor()
- # hide popup while matching invalid cases
- if (not isShortcut and (hasModifier or e.text().isEmpty() or completionPrefix.length() < 1
- or eow.contains(e.text().right(1)))):
- self.cmp.popup().hide()
- return
- self.cmp.update(completionPrefix)
- self.cmp.popup().setCurrentIndex(self.cmp.completionModel().index(0, 0))
- cr = self.cursorRect()
- cr.setWidth(self.cmp.popup().sizeHintForColumn(0)
- + self.cmp.popup().verticalScrollBar().sizeHint().width())
- word = self.p.split(' ')[:-1]
- self.p = ''
- for k in xrange(len(word)):
- self.p += word[k]
- print 'self.p=', self.p
- self.cmp.complete(cr)
- class Completer(QCompleter):
- def __init__(self, stringlist, parent=None):
- super(Completer, self).__init__(parent)
- self.stringlist = stringlist
- self.setModel(QStringListModel())
- # update function will trigger while the text has been modified
- def update(self, completionText):
- # generate a new QStringList instance
- qsList = QStringList()
- # generate hint lists which returns by customatic definitions
- newList = genMyStrList(completionText)
- for item in newList:
- qsList.append(item)
- self.stringlist = qsList
- # filteredList = self.stringlist.filter(completionText, Qt.CaseInsensitive)
- self.model().setStringList(self.stringlist)
- self.popup().setCurrentIndex(self.model().index(0, 0))
- # the function below defined a way to generate a string list
- def genMyStrList(key):
- my_str_list = trie.output_association(key)
- return my_str_list
- def main():
- app = QApplication(sys.argv)
- app.processEvents()
- form = UI()
- form.show()
- # splash.finish(form)
- app.exec_()
- window = QMainWindow()
- window.statusBar().showMessage('Yuan Ziqi')
- menubar = window.menuBar
- window.setWindowTitle('Auto Complete Demo')
- window.resize(400, 200)
- window.move(400, 100)
- edit = TextEdit()
- edit.setFontPointSize(40)
- edit.setCompleter(cmp)
- # bt = addbutton()
- # window.addDockWidget(bt)
- window.setCentralWidget(edit)
- window.show()
- sys.exit(app.exec_())
- if __name__ == '__main__':
- print 'app is running successfully'
- main()
基于trie树的具有联想功能的文本编辑器的更多相关文章
- 基于trie树做一个ac自动机
基于trie树做一个ac自动机 #!/usr/bin/python # -*- coding: utf-8 -*- class Node: def __init__(self): self.value ...
- 用trie树实现输入提示功能,输入php函数名,提示php函数
参照刘汝佳的trie树 结构体 #include "stdio.h" #include "stdlib.h" #include "string.h&q ...
- [转] Trie树详解及其应用
一.知识简介 最近在看字符串算法了,其中字典树.AC自动机和后缀树的应用是最广泛的了,下面将会重点介绍下这几个算法的应用. 字典树(Trie)可以保存一些字符串->值 ...
- Trie树详解及其应用
一.知识简介 最近在看字符串算法了,其中字典树.AC自动机和后缀树的应用是最广泛的了,下面将会重点介绍下这几个算法的应用. 字典树(Trie)可以保存一些字符串->值的对 ...
- Trie树也称字典树
Trie树 Trie树也称字典树,因为其效率很高,所以在在字符串查找.前缀匹配等中应用很广泛,其高效率是以空间为代价的. 一.Trie树的原理 利用串构建一个字典树,这个字典树保存了串的公共前缀信息, ...
- LeetCode Implement Trie (Prefix Tree) (实现trie树3个函数:插入,查找,前缀)
题意:实现trie树的3个功能,只含小写字母的串. 思路:老实做即可! class TrieNode { public: TrieNode* chd[]; bool flag; // Initiali ...
- Trie 树(转)
看了很多 Trie 树的介绍, 这篇讲的最好,简单易懂(特别是代码部分),直接转载:http://www.cnblogs.com/dolphin0520/archive/2011/10/11/2207 ...
- 【动画】看动画轻松理解「Trie树」
Trie树 Trie这个名字取自“retrieval”,检索,因为Trie可以只用一个前缀便可以在一部字典中找到想要的单词. 虽然发音与「Tree」一致,但为了将这种 字典树 与 普通二叉树 以示区别 ...
- Trie树(Prefix Tree)介绍
本文用尽量简洁的语言介绍一种树形数据结构 -- Trie树. 一.什么是Trie树 Trie树,又叫字典树.前缀树(Prefix Tree).单词查找树 或 键树,是一种多叉树结构.如下图: 上图是一 ...
随机推荐
- Java 字符串格式化详解
Java 字符串格式化详解 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 文中如有纰漏,欢迎大家留言指出. 在 Java 的 String 类中,可以使用 format() 方法 ...
- ASP.NET Core project.json imports 是什么意思?
示例代码: "frameworks": { "netcoreapp1.0.0": { "imports" : "portable- ...
- Mybatis XML配置
Mybatis常用带有禁用缓存的XML配置 <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE ...
- UVA-146 ID Codes
It is 2084 and the year of Big Brother has finally arrived, albeit a century late. In order to exerc ...
- 简单分析JavaScript中的面向对象
初学JavaScript的时候有人会认为JavaScript不是一门面向对象的语言,因为JS是没有类的概念的,但是这并不代表JavaScript没有对象的存在,而且JavaScript也提供了其它的方 ...
- 【干货分享】流程DEMO-采购预算编制
流程名: 采购预算编制 业务描述: 在月初由计财部进行预算编辑,提交审批后预算生效 流程相关文件: 流程包.xml WebService业务服务.xml WebService.asmx WebSe ...
- IOS之Objective-C学习 ARC下的单例模式
单例模式是我常用的一种设计模式,最常见的用途就是用来保存数据并且传递数据.这都归功于单例模式的特性,首先就让我为大家简单介绍一下单例模式的特性. 单例模式的三大特性: 1.某个类只能有一个实例: 2. ...
- Java企业实训 - 01 - Java前奏
前言: 虽然个人专攻.NET方向,不过由于个人是干教育行业的,方方面面的东西,不能说都必须精通,但肯定多少都会涉及到. 一个菜鸟学员,从啥都不会,经过一步步学习,最后到企业上手掌管一个模块甚至一个项目 ...
- MySQL加密
MySQL字段加密和解密 1.加密:aes_encrypt('admin','key') 解密:aes_decrypt(password,'key') 2.双向加密 通过密钥去加密,解密的时候的只有知 ...
- join Linq
List<Publisher> Publishers = new List<Publisher>(); Publisher publish1 = new Publisher() ...