Как построить динамическую таблицу QTableWidget используя алгоритм Хаффмана

Как при открытии текстового файла, в котором есть неопределённое количество символов, построить таблицу (QTableWidget) вероятностей для этих символов по алгоритму Хаффмана.

test.py:

from PySide2.QtCore import (QCoreApplication, QMetaObject, QObject, QPoint,
    QRect, QSize, QUrl, Qt)
from PySide2.QtGui import (QBrush, QColor, QConicalGradient, QCursor, QFont,
    QFontDatabase, QIcon, QLinearGradient, QPalette, QPainter, QPixmap,
    QRadialGradient)
from PySide2.QtWidgets import *


class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        if MainWindow.objectName():
            MainWindow.setObjectName(u"MainWindow")
        MainWindow.resize(800, 600)
        self.centralwidget = QWidget(MainWindow)
        self.centralwidget.setObjectName(u"centralwidget")
        self.verticalLayout = QVBoxLayout(self.centralwidget)
        self.verticalLayout.setSpacing(0)
        self.verticalLayout.setObjectName(u"verticalLayout")
        self.verticalLayout.setContentsMargins(0, 0, 0, 0)
        self.frame = QFrame(self.centralwidget)
        self.frame.setObjectName(u"frame")
        self.frame.setMinimumSize(QSize(0, 0))
        self.frame.setMaximumSize(QSize(16777215, 30))
        self.frame.setFrameShape(QFrame.NoFrame)
        self.frame.setFrameShadow(QFrame.Raised)
        self.horizontalLayout = QHBoxLayout(self.frame)
        self.horizontalLayout.setSpacing(0)
        self.horizontalLayout.setObjectName(u"horizontalLayout")
        self.horizontalLayout.setContentsMargins(0, 0, 0, 0)
        self.pushButton = QPushButton(self.frame)
        self.pushButton.setObjectName(u"pushButton")

        self.horizontalLayout.addWidget(self.pushButton, 0, Qt.AlignLeft)


        self.verticalLayout.addWidget(self.frame)

        self.frame_2 = QFrame(self.centralwidget)
        self.frame_2.setObjectName(u"frame_2")
        self.frame_2.setFrameShape(QFrame.NoFrame)
        self.frame_2.setFrameShadow(QFrame.Raised)
        self.verticalLayout_2 = QVBoxLayout(self.frame_2)
        self.verticalLayout_2.setSpacing(0)
        self.verticalLayout_2.setObjectName(u"verticalLayout_2")
        self.verticalLayout_2.setContentsMargins(0, 0, 0, 0)
        self.tableWidget = QTableWidget(self.frame_2)
        self.tableWidget.setObjectName(u"tableWidget")

        self.verticalLayout_2.addWidget(self.tableWidget)


        self.verticalLayout.addWidget(self.frame_2)

        MainWindow.setCentralWidget(self.centralwidget)
        self.statusbar = QStatusBar(MainWindow)
        self.statusbar.setObjectName(u"statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)

        QMetaObject.connectSlotsByName(MainWindow)
    # setupUi

    def retranslateUi(self, MainWindow):
        MainWindow.setWindowTitle(QCoreApplication.translate("MainWindow", u"MainWindow", None))
        self.pushButton.setText(QCoreApplication.translate("MainWindow", u"\u041e\u0442\u043a\u0440\u044b\u0442\u044c", None))`

main.py:

import sys
from PySide2 import QtCore, QtGui, QtWidgets
from PySide2.QtCore import (QCoreApplication, QPropertyAnimation, QDate, QDateTime, QMetaObject, QObject, QPoint, QRect, QSize, QTime, QUrl, Qt, QEvent)
from PySide2.QtGui import (QBrush, QColor, QConicalGradient, QCursor, QFont, QFontDatabase, QIcon, QKeySequence, QLinearGradient, QPalette, QPainter, QPixmap, QRadialGradient)
from PySide2.QtWidgets import *
from test import Ui_MainWindow# импорт нашего сгенерированного файла
class mywindow(QMainWindow):
    def __init__(self):
        super(mywindow, self).__init__()
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        self.ui.pushButton.clicked.connect(self.open)
        self.show()
    def open(self):
        res = QFileDialog.getOpenFileName(self , 'Открыть файл')
if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = mywindow()
    sys.exit(app.exec_())

Пример таблицы:

Таблица вероятностей


Ответы (1 шт):

Автор решения: S. Nick

Я не знаком с алгоритмом Хаффмана и вы не предоставили алгоритм Хаффмана.
Я взял предложенный Google "Жадный алгоритм код Хаффмана..." и построил для вас таблицу в QTableWidget.

Текстовый файл huffman.txt прилагается.

Поменяйте импорты для PySide2 и попробуйте.

main.py

import sys
'''
from PySide2 import QtCore, QtGui, QtWidgets
from PySide2.QtCore import (QCoreApplication, QPropertyAnimation, QDate, QDateTime, QMetaObject, QObject, QPoint, QRect, QSize, QTime, QUrl, Qt, QEvent)
from PySide2.QtGui import (QBrush, QColor, QConicalGradient, QCursor, QFont, QFontDatabase, QIcon, QKeySequence, QLinearGradient, QPalette, QPainter, QPixmap, QRadialGradient)
from PySide2.QtWidgets import *
'''

from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.Qt import *

#from test import Ui_MainWindow          # импорт нашего сгенерированного файла
class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        if MainWindow.objectName():
            MainWindow.setObjectName(u"MainWindow")
        MainWindow.resize(800, 600)
        self.centralwidget = QWidget(MainWindow)
        self.centralwidget.setObjectName(u"centralwidget")
        self.verticalLayout = QVBoxLayout(self.centralwidget)
        self.verticalLayout.setSpacing(0)
        self.verticalLayout.setObjectName(u"verticalLayout")
        self.verticalLayout.setContentsMargins(0, 0, 0, 0)
        
        self.frame = QFrame(self.centralwidget)
        self.frame.setObjectName(u"frame")
        self.frame.setMinimumSize(QSize(0, 0))
        self.frame.setMaximumSize(QSize(16777215, 30))
        self.frame.setFrameShape(QFrame.NoFrame)
        self.frame.setFrameShadow(QFrame.Raised)
        self.horizontalLayout = QHBoxLayout(self.frame)
        self.horizontalLayout.setSpacing(0)
        self.horizontalLayout.setObjectName(u"horizontalLayout")
        self.horizontalLayout.setContentsMargins(0, 0, 0, 0)
        
        self.pushButton = QPushButton(self.frame)
        self.pushButton.setObjectName(u"pushButton")
        self.horizontalLayout.addWidget(self.pushButton, 0, Qt.AlignLeft)

        self.verticalLayout.addWidget(self.frame)
        self.frame_2 = QFrame(self.centralwidget)
        self.frame_2.setObjectName(u"frame_2")
        self.frame_2.setFrameShape(QFrame.NoFrame)
        self.frame_2.setFrameShadow(QFrame.Raised)
        self.verticalLayout_2 = QVBoxLayout(self.frame_2)
        self.verticalLayout_2.setSpacing(0)
        self.verticalLayout_2.setObjectName(u"verticalLayout_2")
        self.verticalLayout_2.setContentsMargins(0, 0, 0, 0)
        self.tableWidget = QTableWidget(self.frame_2)
        self.tableWidget.setObjectName(u"tableWidget")
        self.verticalLayout_2.addWidget(self.tableWidget)
        self.verticalLayout.addWidget(self.frame_2)

        MainWindow.setCentralWidget(self.centralwidget)
        self.statusbar = QStatusBar(MainWindow)
        self.statusbar.setObjectName(u"statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        MainWindow.setWindowTitle(QCoreApplication.translate("MainWindow", "MainWindow"))
        self.pushButton.setText(QCoreApplication.translate("MainWindow", "Открыть"))


# Создать класс узла
class Node(object):
    def __init__(self, name=None, value=None):
        self.name = name
        self.value = value
        self.lchild = None
        self.rchild = None
        
        
# Создать дерево Хаффмана
class HuffmanTree(object):
    # По идее дерева Хаффмана: 
    # на основе узла построить дерево Хаффмана в обратном порядке
    def __init__(self, char_Weights):
        
        self.char_Weights = char_Weights
        
        self.Leaf = [Node(k,v) for k, v in char_Weights.items()]
        while len(self.Leaf) != 1:
            self.Leaf.sort(key=lambda node:node.value, reverse=True)
            n = Node(value=(self.Leaf[-1].value + self.Leaf[-2].value))
            n.lchild = self.Leaf.pop(-1)
            n.rchild = self.Leaf.pop(-1)
            self.Leaf.append(n)
        self.root = self.Leaf[0]
        self.Buffer = list(range(10))

    # Создавать коды с рекурсивным мышлением
    def Hu_generate(self, tree, length):
        node = tree
        if (not node):
            return
        elif node.name:
            buffer = []
            #print(f'{node.name} Кодировка Хаффмана: ', end='')
            for i in range(length):
                #print(self.Buffer[i], end='')
                buffer.append(self.Buffer[i])
     
            self.char_Weights[node.name] = [
                str(self.char_Weights[node.name]), 
                ''.join(map(str, buffer))
            ]
            #print('')
            return
            
        self.Buffer[length] = 0
        self.Hu_generate(node.lchild, length + 1)
        self.Buffer[length] = 1
        self.Hu_generate(node.rchild, length + 1)

    #Output кодировка Хаффмана
    def get_code(self):
        self.Hu_generate(self.root, 0)
        

class MyWindow(QMainWindow, Ui_MainWindow):
    def __init__(self):
        super(MyWindow, self).__init__()
        self.setupUi(self)
        
        self.pushButton.clicked.connect(self.open_file)
                
    def open_file(self):
        path_file, _ = QFileDialog.getOpenFileName(
            self, 
            'Открыть файл',
            '.',
            'Text Files(*.txt)'                               # huffman.txt
        )

        if not path_file:
            return        
        
        self.result = self.findTheCharFrequency(path_file)
        
        tree = HuffmanTree(self.result)
        tree.get_code()
        
        self.tableWidget.clear()
        self.tableWidget.setRowCount(0)
        self.tableWidget.setColumnCount(3)
        self.tableWidget.setHorizontalHeaderLabels(
            ['Символ', 'Вероятностей каждого символа', 'Кодировка Хаффмана'])
        self.tableWidget.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeToContents)
        self.tableWidget.verticalHeader().hide()

        list_keys = list(tree.char_Weights.keys())
        list_keys.sort()
        for i in list_keys:
            v, k = tree.char_Weights[i]
            rowPosition = self.tableWidget.rowCount()
            self.tableWidget.insertRow(rowPosition)   
            
            self.tableWidget.setItem(rowPosition, 0, QtWidgets.QTableWidgetItem(i))
            self.tableWidget.setItem(rowPosition, 1, QtWidgets.QTableWidgetItem(v))
            self.tableWidget.setItem(rowPosition, 2, QtWidgets.QTableWidgetItem(k))

    # Подготовить таблицу вероятностей каждого символа           
    def findTheCharFrequency(self, text):                       
        # частота каждого символа дается в виде словаря
        result = dict()                                               
        with open(text, 'r', encoding='utf-8') as f:                                     
            for line in f.readlines():                                
                line = line.lower()                                   
                for i in line:                                        
                    if i.isalpha():     # Определить, является ли символ буквой                  
                        if i in result:                               
                            result[i] += 1                            
                        else:                                         
                            result.update({i:1})                      
        return result  

        
if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MyWindow()
    window.show()
    sys.exit(app.exec_())

huffman.txt

ХаффманаКак построить динамическую таблицу в QTableWidget используя алгоритм Хаффмана
Хаффмана Как при открытии текстового файла, в котором есть неопределённое количество символов.
Хаффмана построить таблицу вероятностей для этих символов по алгоритму Хаффмана.

введите сюда описание изображения

→ Ссылка