【信息论与编码】【北京航空航天大学】实验二、哈夫曼编码【C语言实现】(下)图像编码压缩

news2024/11/17 21:30:15

实验2 哈夫曼编码(下)(图像编码)

实验简介: 本次实验为实验1:哈夫曼编码的后续补充,实验1见博客:实验一、哈夫曼编码【C语言实现】(上)

说明: 实验代码仅作为学习使用,欢迎转载、改进,禁止用于任何商业用途。

一、实验内容

“不同格式的压缩”:

1、问题: 使用画图软件或者其他工具进行一些简单的艺术创作(推荐使用三四种颜色,不要太多,尽量使用较大的分辨率(例如3840 x 2160)),分别将图片保存为 bmpjpeg 格式,尝试使用你在必选模组实现的程序编码图片,对比地解释为什么文件体积会发生这种变化。类似地,尝试编码一个可执行文件(.exe格式),并尝试解释文件体积的变化

2、C语言代码实现

整个项目分为以下5个源代码文件:

(1)pq.h
文件说明:优先队列头文件。
文件内容:

//pq.h:优先队列
#ifndef _PRIORITY_QUEUE_H
#define _PRIORITY_QUEUE_H

// =============KeyValue Struct 结构体:键值对=============
typedef struct key_value_struct KeyValue;
struct key_value_struct
{
      int _key;
      void *_value;
};
KeyValue *key_value_new(int key, void *value);
void key_value_free(KeyValue *kv, void (*freevalue)(void *));

// =============PriorityQueue Struct 结构体:优先队列=============
#define PRIORITY_MAX 1
#define PRIORITY_MIN 2
typedef struct priority_queue_struct PriorityQueue;
struct priority_queue_struct
{
      KeyValue **_nodes;
      int _size;
      int _capacity;
      
      int _priority;
};


// Some Declarations 相关声明 
PriorityQueue *priority_queue_new(int priority);
void priority_queue_free(PriorityQueue *pq, void (*freevalue)(void *));
const KeyValue *priority_queue_top(PriorityQueue *pq);
KeyValue *priority_queue_dequeue(PriorityQueue *pq);
void priority_queue_enqueue(PriorityQueue *pq, KeyValue *kv);
int priority_queue_size(PriorityQueue *pq);
int priority_queue_empty(PriorityQueue *pq);
void priority_queue_print(PriorityQueue *pq);
#endif

(2)pq.c

文件说明:优先队列函数实现。
文件内容:

//pq.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "pq.h"


//Private Functions Declarations
static void priority_queue_realloc(PriorityQueue *pq);
static void priority_queue_adjust_head(PriorityQueue *pq);
static void priority_queue_adjust_tail(PriorityQueue *pq);
static int priority_queue_compare(PriorityQueue *pq, int pos1, int pos2);
static void priority_queue_swap(KeyValue **nodes, int pos1, int pos2);


//Functions of KeyValue Struct
// 键、值对结构之构造函数
KeyValue *key_value_new(int key, void *value)
{
      KeyValue *pkv = (KeyValue *)malloc(sizeof(KeyValue));
      pkv->_key = key;
      pkv->_value = value;
      return pkv;
}


// 释放键、值对结构之内存
void key_value_free(KeyValue *kv, void (*freevalue)(void *))
{
      if(kv)
      {
            if(freevalue)
            {
                  freevalue(kv->_value);
            }
            free(kv);
      }
}


//Functions of PriorityQueue Struct
// 优先队列之构造函数
PriorityQueue *priority_queue_new(int priority)
{
      PriorityQueue *pq = (PriorityQueue *)malloc(sizeof(PriorityQueue));
      pq->_capacity = 11; //default initial value
      pq->_size = 0;
      pq->_priority = priority;
      
      pq->_nodes = (KeyValue **)malloc(sizeof(KeyValue *) * pq->_capacity);
      return pq;
}


// 释放优先队列之内存
void priority_queue_free(PriorityQueue *pq, void (*freevalue)(void *))
{
      int i;
      if(pq)
      {
            for(i = 0; i < pq->_size; ++i)
                  key_value_free(pq->_nodes[i], freevalue);
            free(pq->_nodes);
            free(pq);
      }
}


// 取优先队列的队顶元素
const KeyValue *priority_queue_top(PriorityQueue *pq)
{
      if(pq->_size > 0)
            return pq->_nodes[0];
      return NULL;
}


// 出个队
KeyValue *priority_queue_dequeue(PriorityQueue *pq)
{
      KeyValue *pkv = NULL;
      if(pq->_size > 0)
      {
            pkv = pq->_nodes[0];
            priority_queue_adjust_head(pq);
      }
      return pkv;
}


// 入个队
void priority_queue_enqueue(PriorityQueue *pq, KeyValue *kv)
{
      printf("add key:%d\n", kv->_key);
      pq->_nodes[pq->_size] = kv;
      priority_queue_adjust_tail(pq);
      if(pq->_size >= pq->_capacity)
            priority_queue_realloc(pq);
}


// 多大的队?
int priority_queue_size(PriorityQueue *pq)
{
      return pq->_size;
}


// 空不空?
int priority_queue_empty(PriorityQueue *pq)
{
      return pq->_size <= 0;
}


// 输出一下
void priority_queue_print(PriorityQueue *pq)
{
      int i;
      KeyValue *kv;
      printf("data in the pq->_nodes\n");
      for(i = 0; i < pq->_size; ++i)
            printf("%d ", pq->_nodes[i]->_key);
      printf("\n");
      
      printf("dequeue all data\n");
      while(!priority_queue_empty(pq))
      {
            kv = priority_queue_dequeue(pq);
            printf("%d ", kv->_key);
      }
      printf("\n");
}


// 重新分配内存
static void priority_queue_realloc(PriorityQueue *pq)
{
      pq->_capacity = pq->_capacity * 2;
      pq->_nodes = realloc(pq->_nodes, sizeof(KeyValue *) * pq->_capacity);
}


// 头部略作调整
static void priority_queue_adjust_head(PriorityQueue *pq)
{
      int i, j, parent, left, right;
      
      i = 0, j = 0;
      parent = left = right = 0;
      priority_queue_swap(pq->_nodes, 0, pq->_size - 1);
      pq->_size--;
      while(i < (pq->_size - 1) / 2)
      {
            parent = i;
            
            left = i * 2 + 1;
            right = left + 1;
            j = left;
            if(priority_queue_compare(pq, left, right) > 0)
                  j++;
            if(priority_queue_compare(pq, parent, j) > 0)
            {
                  priority_queue_swap(pq->_nodes, i, j);
                  i = j;
            }
            else
                  break;
            
      }
      
}


// 尾部略作调整
static void priority_queue_adjust_tail(PriorityQueue *pq)
{
      int i, parent, child;
      
      i = pq->_size - 1;
      pq->_size++;
      while(i > 0)
      {
            child = i;
            parent = (child - 1) / 2;
            
            if(priority_queue_compare(pq, parent, child) > 0)
            {
                  priority_queue_swap(pq->_nodes, child, parent);
                  i = parent;
            }
            else
                  break;
            
      }
}


// 比个大小
static int priority_queue_compare(PriorityQueue *pq, int pos1, int pos2)
{
      int adjust = -1;
      int r = pq->_nodes[pos1]->_key - pq->_nodes[pos2]->_key;
      if(pq->_priority == PRIORITY_MAX)
            r *= adjust;
      return r;
}


// 交换2个优先队列
static void priority_queue_swap(KeyValue **nodes, int pos1, int pos2)
{
      KeyValue *temp = nodes[pos1];
      nodes[pos1] = nodes[pos2];
      nodes[pos2] = temp;
}

(3)compress.h

文件说明:压缩函数相关头文件。
文件内容:

//compress.h
#ifndef _FILE_COMPRESSION_H
#define _FILE_COMPRESSION_H


//Huffman Tree Node 哈夫曼树结点结构
typedef struct HaffumanTreeNode HTN;
struct HaffumanTreeNode
{
      char _ch;   //character
      int _count; //frequency
      struct HaffumanTreeNode *_left; //left child
      struct HaffumanTreeNode *_right;//right child
};


//FileCompress Struct 文件压缩结构
#define BITS_PER_CHAR 8     //the number of bits in a char
#define MAX_CHARS 256            //the max number of chars
#define FILE_BUF_SIZE 8192  //the size of Buffer for FILE I/O

typedef struct FileCompressStruct FCS;

struct FileCompressStruct
{
      HTN *_haffuman;        //A pointer to the root of hafumman tree
      unsigned int _charsCount; //To store the number of chars
      unsigned int _total; //Total bytes in a file.
      char *_dictionary[MAX_CHARS]; //to store the encoding of each character
      int _statistic[MAX_CHARS]; //To store the number of each character
};

// Function Prototypes 函数原型
FCS *fcs_new();
void fcs_compress(FCS *fcs, const char *inFileName, const char *outFileName);
void fcs_decompress(FCS *fcs, const char *inFileName, const char *outFileName);
void fcs_free(FCS *fcs);

#endif

(4)compress.c

文件说明:压缩相关的函数实现。
文件内容:

//compress.c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "compress.h"
#include "pq.h"


// 掩码
static const unsigned char mask[8] = 
{ 
      0x80, /* 10000000 */
      0x40, /* 01000000 */
      0x20, /* 00100000 */
      0x10, /* 00010000 */
      0x08, /* 00001000 */
      0x04, /* 00000100 */
      0x02, /* 00000010 */
      0x01  /* 00000001 */                        
};


//static functions of HTN 哈夫曼树结点相关函数
// 构造函数
static HTN *htn_new(char ch, int count)
{
      HTN *htn = (HTN *)malloc(sizeof(HTN));
      htn->_left = NULL;
      htn->_right = NULL;
      htn->_ch = ch;
      htn->_count = count;
      return htn;
}


// 递归打印函数
static void htn_print_recursive(HTN *htn, int depth)
{
      int i;
      if(htn)
      {
            for(i = 0; i < depth; ++i)
                  printf("  ");
            printf("%d:%d\n", htn->_ch, htn->_count);
            htn_print_recursive(htn->_left, depth + 1);
            htn_print_recursive(htn->_right, depth + 1);
      }
}


// 遍历整棵树
static void htn_print(HTN *htn)
{ 
      htn_print_recursive(htn, 0);
}


// 释放树的内存
static void htn_free(HTN *htn)
{
      if(htn)
      {
            htn_free(htn->_left);
            htn_free(htn->_right);
            free(htn);
      }
}
 

//static functions of FCS 文件压缩相关函数
static void fcs_generate_statistic(FCS *fcs, const char *inFileName)
{
      int ret, i;
      unsigned char buf[FILE_BUF_SIZE];
      FILE *pf = fopen(inFileName, "rb");
      if(!pf)
      {
            fprintf(stderr, "can't open file:%s\n", inFileName);
            return;
      }
      while((ret = fread(buf, 1, FILE_BUF_SIZE, pf)) > 0)
      {
            fcs->_total += ret;
            for(i = 0; i < ret; ++i)
            {
                  if(fcs->_statistic[buf[i]] == 0)
                        fcs->_charsCount++;
                  fcs->_statistic[buf[i]]++;
            }
      }
      fclose(pf);
}



static void fcs_create_haffuman_tree(FCS *fcs)
{
      int i, count;
      HTN *htn, *parent, *left, *right;
      KeyValue *kv, *kv1, *kv2;
      PriorityQueue *pq;
      pq = priority_queue_new(PRIORITY_MIN);
      for(i = 0; i < MAX_CHARS; ++i)
      {
            if(fcs->_statistic[i])
            {
                  htn = htn_new((char)i, fcs->_statistic[i]);
                  kv = key_value_new(fcs->_statistic[i], htn);
                  priority_queue_enqueue(pq, kv);
            }
      }
      //fprintf(stdout, "the number of haffuman leaf is %d\n", priority_queue_size(pq));
      
      while(!priority_queue_empty(pq))
      {
            //fprintf(stdout, "priority queue size:%d\n", priority_queue_size(pq));
            kv1 = priority_queue_dequeue(pq);
            kv2 = priority_queue_dequeue(pq);
            if(kv2 == NULL)
            {
                  fcs->_haffuman = kv1->_value;
                  key_value_free(kv1, NULL);
            }
            else
            {
                  left = (HTN *)kv1->_value;
                  right = (HTN *)kv2->_value;
                  count = left->_count + right->_count;
                  key_value_free(kv1, NULL);
                  key_value_free(kv2, NULL);
                  parent = htn_new(0, count);
                  parent->_left = left;
                  parent->_right = right;
                  kv = key_value_new(count, parent);
                  priority_queue_enqueue(pq, kv);
            }
      }
      priority_queue_free(pq, NULL);
      //htn_print(fcs->_haffuman);
}



static void fcs_generate_dictionary_recursively(HTN *htn, char *dictionary[], char path[], int depth)
{
      char *code = NULL;
      if(htn)
      {
            if(htn->_left == NULL && htn->_right == NULL)
            {
                  code = (char *)malloc(sizeof(char) * (depth + 1));
                  memset(code, 0, sizeof(char) * (depth + 1));
                  memcpy(code, path, depth);
                  dictionary[(unsigned char)htn->_ch] = code;
            }
            if(htn->_left)
            {
                  path[depth] = '0';
                  fcs_generate_dictionary_recursively(htn->_left, dictionary, path, depth + 1);
            }
            if(htn->_right)
            {
                  path[depth] = '1';
                  fcs_generate_dictionary_recursively(htn->_right, dictionary, path, depth + 1);
            }
      }
}



static void fcs_generate_dictionary(FCS *fcs)
{
      char path[32];
      fcs_generate_dictionary_recursively(fcs->_haffuman, fcs->_dictionary, path, 0);
      //fcs_print_dictionary(fcs);
}



static void fcs_print_dictionary(FCS *fcs)
{
      int i;
      for(i = 0; i < MAX_CHARS; ++i)
            if(fcs->_dictionary[i] != NULL)
                  fprintf(stdout, "%d:%s\n", i, fcs->_dictionary[i]);
}



static void fcs_write_statistic(FCS *fcs, FILE *pf)
{
      int i;
      fprintf(pf, "%d\n", fcs->_charsCount);
      for(i = 0; i < MAX_CHARS; ++i)
            if(fcs->_statistic[i] != 0)
                  fprintf(pf, "%d %d\n", i, fcs->_statistic[i]); 
}


// 文件压缩
static void fcs_do_compress(FCS *fcs, const char *inFileName, const char* outFileName)
{
      int i, j, ret;
      
      char *dictEntry, len;
      unsigned int bytes;
      char bitBuf;
      int bitPos;
      
      unsigned char inBuf[FILE_BUF_SIZE];
      FILE *pfIn, *pfOut;
      pfIn = fopen(inFileName, "rb");
      if(!pfIn)
      {
            fprintf(stderr, "can't open file:%s\n", inFileName);
            return;
      }
      pfOut = fopen(outFileName, "wb");
      if(!pfOut)
      {
            fclose(pfIn);
            fprintf(stderr, "can't open file:%s\n", outFileName);
            return;
      }
      fcs_write_statistic(fcs, pfOut);
      bitBuf = 0x00;
      bitPos = 0;
      bytes = 0;
      while((ret = fread(inBuf, 1, FILE_BUF_SIZE, pfIn)) > 0)
      {
            for(i = 0; i < ret; ++i)
            {
                  len = strlen(fcs->_dictionary[inBuf[i]]);
                  dictEntry = fcs->_dictionary[inBuf[i]];
                  //printf("%s\n", dictEntry);
                  for(j = 0; j < len; ++j)
                  {
                        if(dictEntry[j] == '1')
                        {
                              bitBuf |= mask[bitPos++];
                        }
                        else
                        {
                              bitPos++;
                        }
                        
                        if(bitPos == BITS_PER_CHAR)
                        {
                              fwrite(&bitBuf, 1, sizeof(bitBuf), pfOut);
                              bitBuf = 0x00;
                              bitPos = 0;
                              bytes++;
                        }
                  }
            }
      }
      if(bitPos != 0)
      {
            fwrite(&bitBuf, 1, sizeof(bitBuf), pfOut);
            bytes++;
      }
      fclose(pfIn);
      fclose(pfOut);
      printf("The compression ratio is:%f%%\n",
            (fcs->_total - bytes) * 100.0 / fcs->_total);
}



static void fcs_read_statistic(FCS *fcs, FILE *pf)
{
      int i, charsCount = 0;
      int ch;
      int num;
      fscanf(pf, "%d\n", &charsCount);
      fcs->_charsCount = charsCount;
      for(i = 0; i < charsCount; ++i)
      {
            fscanf(pf, "%d %d\n", &ch, &num);
            fcs->_statistic[(unsigned int)ch] = num;
            fcs->_total += num;
      }
}


// 文件解压缩
static void fcs_do_decompress(FCS *fcs, FILE *pfIn, const char *outFileName)
{
      int i, j, ret;
      unsigned char ch;
      HTN *htn;
      unsigned char buf[FILE_BUF_SIZE];
      unsigned char bitCode;
      int bitPos;
      FILE *pfOut;
      pfOut = fopen(outFileName, "wb");
      if(!pfOut)
      {
            fprintf(stderr, "can't open file:%s\n", outFileName);
            return;
      }
      htn = fcs->_haffuman;
      bitCode = 0x00;
      bitPos = 0;
      while((ret = fread(buf, 1, FILE_BUF_SIZE, pfIn)) > 0)
      {
            for(i = 0; i < ret; ++i)
            {
                  ch = buf[i];
                  for(j = 0; j < BITS_PER_CHAR; ++j)
                  {
                        if(ch & mask[j])
                        {
                              htn = htn->_right;      
                        }
                        else
                        {
                              htn = htn->_left;
                        }
                        if(htn->_left == NULL && htn->_right == NULL) //leaf
                        {
                              if(fcs->_total > 0)
                              {
                                    fwrite(&htn->_ch, 1, sizeof(char), pfOut);
                                    fcs->_total--;
                              }
                              htn = fcs->_haffuman;
                        }
                  }
            }
      }
      fclose(pfOut);
}


//FCS functions
FCS *fcs_new()
{
      FCS *fcs = (FCS *)malloc(sizeof(FCS));
      fcs->_charsCount = 0;
      fcs->_total = 0;
      memset(fcs->_statistic, 0, sizeof(fcs->_statistic));
      memset(fcs->_dictionary, 0, sizeof(fcs->_dictionary));
      fcs->_haffuman = NULL;
      return fcs;
}



void fcs_free(FCS *fcs)
{
      int i;
      if(fcs)
      {
            if(fcs->_haffuman)
                  htn_free(fcs->_haffuman);
            for(i = 0; i < MAX_CHARS; ++i)
                  free(fcs->_dictionary[i]);
            free(fcs);
      }
}



void fcs_compress(FCS *fcs, const char *inFileName, const char *outFileName)
{
      fprintf(stdout, "To compress file: %s ...\n", inFileName); 
      fcs_generate_statistic(fcs, inFileName);
      fcs_create_haffuman_tree(fcs);
      fcs_generate_dictionary(fcs);
      fcs_do_compress(fcs, inFileName, outFileName);
      fprintf(stdout, "The compressed data of file: %s stored at %s!\n",
            inFileName, outFileName);
}



void fcs_decompress(FCS *fcs, const char *inFileName, const char *outFileName)
{
      FILE *pfIn;
      fprintf(stdout, "To decompress file: %s ...\n", inFileName);
      pfIn= fopen(inFileName, "rb");
      if(!pfIn)
      {
            fprintf(stderr, "can't open file: %s\n", inFileName);
            return ;
      }
      fcs_read_statistic(fcs, pfIn);
      fcs_create_haffuman_tree(fcs);
      fcs_generate_dictionary(fcs);
      fcs_do_decompress(fcs, pfIn, outFileName);
      fclose(pfIn);
      fprintf(stdout, "The decompressed data of file: %s stored at %s\n",
            inFileName, outFileName);
}

(5)main.c

文件说明: 自定义了压缩后的文件后缀名:.hfm(哈夫曼Huffman的简写)
文件内容:

//main.c
#include <stdlib.h>
#include "compress.h"

// 常量定义
const int DO_COMPRESS = 1;
const int DO_DECOMPRESS = 1;
const char *InFile = "tree.jpg"; //The file to compress 要压缩的文件
const char *CompressedFile = "tree.hfm"; //Compressed data of the file 压缩后的文件
const char *OutFile = "tree_decompressed.jpg"; //The decompressed file of the data 解压缩后的文件

// 主函数
int main(int argc, char **argv)
{
      //1. compress file 对文件进行压缩
      if(DO_COMPRESS)
      {
            FCS *fcs1;
            fcs1 = fcs_new();
            fcs_compress(fcs1, InFile, CompressedFile);
            fcs_free(fcs1);
      }
	  
      //2. decompress file 对压缩后的文件进行解压缩
      if(DO_DECOMPRESS)
      {
            FCS *fcs2;
            fcs2 = fcs_new();
            fcs_decompress(fcs2, CompressedFile, OutFile);
            fcs_free(fcs2);
      }
	  
      system("pause");
  
	  return 0;
}

3、图片压缩测试

(1)、测试文件1:tree.jpg
文件说明:手绘的简笔画,内容为一棵树,格式为 .jpg

main.c中输入的相关字段:

const char *InFile = "tree.jpg"; //The file to compress 要压缩的文件
const char *CompressedFile = "tree.hfm"; //Compressed data of the file 压缩后的文件
const char *OutFile = "tree_decompressed.jpg"; //The decompressed file of the data 解压缩后的文件

运行时截图:

在这里插入图片描述

压缩的文件大小:276,764字节
压缩的文件大小:242,500字节
压缩导致改变的百分比:约12.4%

(2)、测试文件2:plane.bmp

文件说明:手绘的简笔画,内容为一架飞机,格式为 .bmp

main.c中输入的相关字段:

const char *InFile = "plane.bmp"; //The file to compress 要压缩的文件
const char *CompressedFile = "plane.hfm"; //Compressed data of the file 压缩后的文件
const char *OutFile = "plane_decompressed.bmp"; //The decompressed file of the data 解压缩后的文件

运行时截图:

在这里插入图片描述

压缩的文件大小:24,883,254字节
压缩的文件大小:3,775,181字节
压缩导致改变的百分比:约84.8%

4、可执行文件压缩测试

(1)、测试文件1:test.exe
文件说明:某一C语言源程序编译生成的可执行文件,格式为 .exe

main.c中输入的相关字段:

const char *InFile = "test.exe"; //The file to compress 要压缩的文件
const char *CompressedFile = "test.hfm"; //Compressed data of the file 压缩后的文件
const char *OutFile = "test_decompressed.exe"; //The decompressed file of the data 解压缩后的文件

运行时截图:

在这里插入图片描述

压缩的文件大小:72,383字节
压缩的文件大小:49,895字节
压缩导致改变的百分比:约31.1%

(2)、测试文件2:bfv.exe
文件说明:主机游戏《战地风云5》的可执行文件,格式为 .exe

main.c中输入的相关字段:

const char *InFile = "bfv.exe"; //The file to compress 要压缩的文件
const char *CompressedFile = "bfv.hfm"; //Compressed data of the file 压缩后的文件
const char *OutFile = "bfv_decompressed.exe"; //The decompressed file of the data 解压缩后的文件

运行时截图:

在这里插入图片描述

压缩的文件大小:238,028,800字节
压缩的文件大小:45,326,336字节
压缩导致改变的百分比:约81.0%

问题: 在待压缩文件体积过大时,解压缩时可能会出现问题。具体原因仍在研究当中。
至此,本次实验结束。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1376268.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Redis系列-15.Redis的IO多路复用原理解析

&#x1f44f;作者简介&#xff1a;大家好&#xff0c;我是爱吃芝士的土豆倪&#xff0c;24届校招生Java选手&#xff0c;很高兴认识大家&#x1f4d5;系列专栏&#xff1a;Spring源码、JUC源码、Kafka原理、分布式技术原理、数据库技术&#x1f525;如果感觉博主的文章还不错的…

【REST2SQL】05 GO 操作 达梦 数据库

【REST2SQL】01RDB关系型数据库REST初设计 【REST2SQL】02 GO连接Oracle数据库 【REST2SQL】03 GO读取JSON文件 【REST2SQL】04 REST2SQL第一版Oracle版实现 信创要求用国产数据库&#xff0c;刚好有项目用的达梦&#xff0c;研究一下go如何操作达梦数据库 1 准备工作 1.1 安…

查询速度提升15倍!银联商务基于 Apache Doris 的数据平台升级实践

本文导读&#xff1a; 在长期服务广大规模商户的过程中&#xff0c;银联商务已沉淀了庞大、真实、优质的数据资产数据&#xff0c;这些数据不仅是银联商务开启新增长曲线的基础&#xff0c;更是进一步服务好商户的关键支撑。为更好提供数据服务&#xff0c;银联商务实现了从 H…

关于高通Android 平台上qssi的介绍

1. QSSI 是 Qualcomm Single System Image 的缩写。 2. Android Q上开始支持QSSI。 3. QSSI 是用来编译system.img的 3.1 QSSI编译注意事项 lunch qssi ------ 编译system.img lunch target ------ 编译其余的image 3.2 有QSSI和没有QSSI的编译流程对比 没有QS…

3Dmax不能渲染怎么办?

使用3Dmax渲染异常的话&#xff0c;主要在于以下几点&#xff1a; 1.素材丢失导致渲染效果错误 max文件贴图丢失或对应路径不存在 2.相机位置 先要考虑是相机位置&#xff0c;不管用的普通相机还是物理相机。 看它的位置是不是放在了模型的里面或者是墙体的外面&#xff0c;…

如何构建Prompt,帮我生成QA,作为召回率检索的测试集?

最近在做搜索召回率的提升工作。粮草未动兵马先行&#xff01;在做之前应该先有一把尺子来衡量召回率的好坏。所以应该先构建测试数据集&#xff0c;然后去做标准化测试。 有了测试机集以后。再去做搜索优化&#xff0c;才能看出来效果。 当然可以选择一些开源的测试集。如果可…

“三指针法“合并两个有序数组(力扣每日一练)

我的第一想法确实是&#xff1a;先合并数组&#xff0c;再排序&#xff0c;搞完。 哈哈哈&#xff0c;想那么多干嘛&#xff0c;目的达成了就好了。 力扣官方题解是双指针&#xff1a; 还有糕手&#xff1a; Python&#xff1a; def merge(nums1, m, nums2, n):# 两个指针分别…

合并 K 个升序链表[困难]

一、题目 给你一个链表数组&#xff0c;每个链表都已经按升序排列。请你将所有链表合并到一个升序链表中&#xff0c;返回合并后的链表。 示例 1&#xff1a; 输入&#xff1a;lists [[1,4,5],[1,3,4],[2,6]] 输出&#xff1a;[1,1,2,3,4,4,5,6] 解释&#xff1a;链表数组如…

经管类CSSCI、北核期刊投稿指南数据(2023年更新)/经管类的期刊投稿指南

经管类CSSCI、北核期刊投稿指南&#xff08;2023年更新&#xff09; 1、内容包括&#xff1a;投稿指南-CSSCI版本、CSSCI扩展版本、北大核刊版本、建议期刊版本、所有期刊。 2、范围&#xff1a;CSSCI、CSSCI扩展、北大核刊 3、说明&#xff1a;包含经管类期刊的发表难度&am…

Spark六:Spark 底层执行原理SparkContext、DAG、TaskScheduler

Spark底层执行原理 学习Spark运行流程 学习链接&#xff1a;https://mp.weixin.qq.com/s/caCk3mM5iXy0FaXCLkDwYQ 一、Spark运行流程 流程&#xff1a; SparkContext向管理器注册并向资源管理器申请运行Executor资源管理器分配Executor&#xff0c;然后资源管理器启动Execut…

Day4Qt

1.头文件: #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QTime>//时间类 #include <QTimer>//时间事件类 #include <QTimerEvent>//定时器类 #include <QTextToSpeech> namespace Ui { class Widget; }class Widget : publi…

Leetcode2982. 找出出现至少三次的最长特殊子字符串 II

Every day a Leetcode 题目来源&#xff1a;2982. 找出出现至少三次的最长特殊子字符串 II 解法1&#xff1a;字符串分割 分类讨论 按照相同字母分组&#xff0c;每组统计相同字母连续出现的长度。例如 aaaabbbabb 把 a 分成一组&#xff0c;组内有长度 4 和长度 1&#x…

2022-ECCV-Explaining Deepfake Detection by Analysing Image Matching

一、研究背景 1.大量工作将深度伪造检测作为一个二分类任务并取得了良好的性能。 2.理解模型如何在二分类标签的监督下学习伪造相关特征仍难是个艰巨的任务。 3.视觉概念&#xff1a;具有语义的人脸区域&#xff0c;如嘴、鼻子、眼睛。 二、研究目标 1.验证假设&#xff0c;并…

centos8部署MySQL5.7故障集

转载说明&#xff1a;如果您喜欢这篇文章并打算转载它&#xff0c;请私信作者取得授权。感谢您喜爱本文&#xff0c;请文明转载&#xff0c;谢谢。 在centos8系统上安装MySQL&#xff0c;使用的是centos7上安装MySQL的脚本&#xff0c;出现了以下问题&#xff0c;以做记录&…

Spark原理——逻辑执行图

逻辑执行图 明确逻辑计划的边界 在 Action 调用之前&#xff0c;会生成一系列的RDD,这些RDD之间的关系&#xff0c;其实就是整个逻辑计划 val conf new SparkConf().setMaster("local[6]").setAppName("wordCount_source") val sc new SparkContext(conf)v…

多测师肖sir___ui自动化测试po框架讲解版

po框架 一、ui自动化po框架介绍 &#xff08;1&#xff09;PO是Page Object的缩写 &#xff08;2&#xff09;业务流程与页面元素操作分离的模式&#xff0c;可以简单理解为每个页面下面都有一个配置class&#xff0c; 配置class就用来维护页面元素或操作方法 &#xff08;3&am…

20240111在ubuntu20.04.6下解压缩RAR格式的压缩包

20240111在ubuntu20.04.6下解压缩RAR格式的压缩包 2024/1/11 18:25 百度搜搜&#xff1a;ubuntu rar文件怎么解压 rootrootrootroot-X99-Turbo:~/temp$ ll total 2916 drwx------ 3 rootroot rootroot 4096 1月 11 18:28 ./ drwxr-xr-x 25 rootroot rootroot 4096 1月…

【时事篇-02】20240110 365天存钱法(sum法)

背景需求 朋友圈里&#xff0c;一位保险推销员发布“存钱法广告”&#xff0c;我想用Python验算结果正确性 使用的是最近宫格数独里用到的”sum法” 代码展示 项目:存钱游戏计算 sum() 作者:阿夏 时间:2024年1月10日19:03 import random1、钻石版&#xff1a;从1元存到365元&a…

七星彩中奖号码模拟机器

七星彩号码抽取规则。 前区&#xff1a;抽取前区6个号码&#xff0c;每个号码是0~9之间选1个。 后区&#xff1a;抽取后区1个号码&#xff0c;每个号码是0~14之间选1个。 #七星彩模拟器&#xff0c;2024-01-12&#xff0c;by qs import random QianQu_6number [0,1,2,3,4,5,…

【C语言】linux内核set_task_stack_end_magic函数

一、函数定义 void set_task_stack_end_magic(struct task_struct *tsk) {unsigned long *stackend;stackend end_of_stack(tsk);*stackend STACK_END_MAGIC; /* for overflow detection */ } 内核版本6.4.3、6.7。 二、代码解读 解读1 这段代码是一个在Linux内核中定…