之前的软件设计与开发实践课程中,自己构思的大作业题目。做的具有核心功能,但是还欠缺边边角角的小功能和持久化数据结构,先放出来,有机会一点点改。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树的具有联想功能的文本编辑器的更多相关文章

  1. 基于trie树做一个ac自动机

    基于trie树做一个ac自动机 #!/usr/bin/python # -*- coding: utf-8 -*- class Node: def __init__(self): self.value ...

  2. 用trie树实现输入提示功能,输入php函数名,提示php函数

    参照刘汝佳的trie树 结构体 #include "stdio.h" #include "stdlib.h" #include "string.h&q ...

  3. [转] Trie树详解及其应用

    一.知识简介         最近在看字符串算法了,其中字典树.AC自动机和后缀树的应用是最广泛的了,下面将会重点介绍下这几个算法的应用.       字典树(Trie)可以保存一些字符串->值 ...

  4. Trie树详解及其应用

    一.知识简介        最近在看字符串算法了,其中字典树.AC自动机和后缀树的应用是最广泛的了,下面将会重点介绍下这几个算法的应用.      字典树(Trie)可以保存一些字符串->值的对 ...

  5. Trie树也称字典树

    Trie树 Trie树也称字典树,因为其效率很高,所以在在字符串查找.前缀匹配等中应用很广泛,其高效率是以空间为代价的. 一.Trie树的原理 利用串构建一个字典树,这个字典树保存了串的公共前缀信息, ...

  6. LeetCode Implement Trie (Prefix Tree) (实现trie树3个函数:插入,查找,前缀)

    题意:实现trie树的3个功能,只含小写字母的串. 思路:老实做即可! class TrieNode { public: TrieNode* chd[]; bool flag; // Initiali ...

  7. Trie 树(转)

    看了很多 Trie 树的介绍, 这篇讲的最好,简单易懂(特别是代码部分),直接转载:http://www.cnblogs.com/dolphin0520/archive/2011/10/11/2207 ...

  8. 【动画】看动画轻松理解「Trie树」

    Trie树 Trie这个名字取自“retrieval”,检索,因为Trie可以只用一个前缀便可以在一部字典中找到想要的单词. 虽然发音与「Tree」一致,但为了将这种 字典树 与 普通二叉树 以示区别 ...

  9. Trie树(Prefix Tree)介绍

    本文用尽量简洁的语言介绍一种树形数据结构 -- Trie树. 一.什么是Trie树 Trie树,又叫字典树.前缀树(Prefix Tree).单词查找树 或 键树,是一种多叉树结构.如下图: 上图是一 ...

随机推荐

  1. C#中如何给Excel添加水印

    我们知道Microsoft Excel并没有内置的功能直接给Excel表添加水印,但是其实我们可以用其他变通的方式来解决此问题,如通过添加页眉图片或艺术字的方法来模仿水印的外观.所以在这篇文章中,我将 ...

  2. .NET应用程序域

    在.NET平台下,可执行程序并没有直接承载在Windows进程中,而非托管程序是直接承载的..NET可执行程序承载在进程的一个逻辑分区中,称之为应用程序域(AppDomain).一个进程可以包含多个应 ...

  3. SAP CRM 用户界面对象类型和设计对象

    在CRM中的用户界面对象类型的帮助下,我们可以做这些工作: 进行不同的视图配置 创建动态导航 从设计层控制字段标签.值帮助 控制BOL对象的属性的可视性 从导航栏访问自定义组件 一个用户界面对象类型之 ...

  4. Android中点击事件的实现方式

    在之前博文中多次使用了点击事件的处理实现,有朋友就问了,发现了很多按钮的点击实现,但有很多博文中使用的实现方式有都不一样,到底是怎么回事.今天我们就汇总一下点击事件的实现方式. 点击事件的实现大致分为 ...

  5. 敏捷软件开发VS传统软件工程

    敏捷软件开发:又称敏捷开发,是一种从1990年代开始逐渐引起广泛关注的一些新兴软件开发方法,是一种应对快速变化的需求的一种软件开发能力. 与传统软件工程相比,它们的具体名称.理念.过程.术语都不尽相同 ...

  6. 记:MySQL 5.7.3.0 安装 全程截图

    前言: 下一个班快讲MySQL数据库了,正好把服务器里面的MySQL卸了重装了一下. 截个图,作为笔记.也正好留给需要的朋友们. 目录: 下载软件 运行安装程序 安装程序欢迎界面 许可协议 查找更新 ...

  7. liunx 磁盘管理命令记录

    Linux磁盘管理好坏管理直接关系到整个系统的性能问题. Linux磁盘管理常用三个命令为df.du和fdisk. df:列出文件系统的整体磁盘使用量 du:检查磁盘空间使用量 fdisk:用于磁盘分 ...

  8. s:form标签

    2017-01-07 17:43:18 基本的用法 <!-- Action类必须有一个无参的构造器,因为在执行action方法之前,拦截器已经创建了一个"空"的Action对 ...

  9. Lesson 14 Do you speak English?

    Text I had an amusing experience last year. After I had left a small village in the south of France. ...

  10. App开发的新趋势

    移动开发这些年,移动开发者人数越来越多,类似的培训公司发展也很快,不过伴随着的是移动应用的需求这几年发展更为旺盛.要开发好的App,纯原生开发肯定是最佳选择.但是这么多年发展,原生开发的难度并没有降低 ...