栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

数据结构C十二

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

数据结构C十二

1.1N皇后问题求解

N皇后问题是一个经典的问题,作为回溯的经典案例,在一个N*N的棋盘上放置N个皇后,每行一个并使其不能互相攻击(同一行、同一列、同一斜线上的皇后都会自动攻击),有多少摆法。有递归和非递归两种实现方式,现在用递归方法。

这里用一个N*N的矩阵来存储棋盘:a)算法开始, 清空棋盘,设当前行为第一行,当前列设为第一列; b)在当前行,当前列的位置上判断是否满足条件(即保证经过这一点的行,列与斜线上都没有两个皇后),若不满足,跳到第d步;c )在当前位置上满足条件的情形:在当前位置放一个皇后,若当前行是最后一行,则记录下来;若当前行不是最后一行,当前行设为下一行, 当前列设为当前行的第一个大测位置;若当前行是最后一行,当前列不是最后一列,当前列设为下一列;若当前行是最后一行,当前列是最后一列,回溯,清空当前行及以下各行的棋盘,然后,当前行设为上一行,当前列设为当前行的下一个待测位置;以上返回到第b步;d)在当前位置上不满足条件的情形:若当前列不是最后一列,当前列设为下一列,返回到第b步;若当前列是最后一列了,回溯,即,若当前行已经是第一行了,算法退出,否则,清空当前行及以下各行的棋盘,然后,当前行设为上一行,当前列设为当前行的下一个待测位置,返回到第b步;

具体实现

1.2判断能否放置

bool place(int* paraSolution, int paraT){
	
    for (int j = 1; j < paraT; j ++)
	{
        if ((abs(paraT - j) == abs(paraSolution[j] - paraSolution[paraT])) || (paraSolution[j] == paraSolution[paraT]))		
		{  
		   	return false;
		}
    }//Of for
    return true;
}//Of place

1.3回溯操作

void backtracking(int* paraSolution, int paraN, int paraT){
	int i;
    if (paraT > paraN)
	{
        for (i = 1; i <= paraN; i ++)
		{
        	printf("%d ", paraSolution[i]);
		}            
		printf("rn");
    }else{
        for (i = 1; i <= paraN; i ++)
		{
            paraSolution[paraT] = i;
            if (place(paraSolution, paraT))
			{
            	backtracking(paraSolution, paraN, paraT + 1);
			}
               
        }//Of for i
    }//Of if
}//Of backtracking

1.4完整代码

#include 
#include 
#include 


//Place it there, applicable?

bool place(int* paraSolution, int paraT){
	
    for (int j = 1; j < paraT; j ++)
	{
        if ((abs(paraT - j) == abs(paraSolution[j] - paraSolution[paraT])) || (paraSolution[j] == paraSolution[paraT]))		
		{  
		   	return false;
		}
    }//Of for
    return true;
}//Of place

//Backtracking.

void backtracking(int* paraSolution, int paraN, int paraT){
	int i;
    if (paraT > paraN)
	{
        for (i = 1; i <= paraN; i ++)
		{
        	printf("%d ", paraSolution[i]);
		}            
		printf("rn");
    }else{
        for (i = 1; i <= paraN; i ++)
		{
            paraSolution[paraT] = i;
            if (place(paraSolution, paraT))
			{
            	backtracking(paraSolution, paraN, paraT + 1);
			}
               
        }//Of for i
    }//Of if
}//Of backtracking

//Title: n queens.
void nQueen(int paraN){ int i; int* solution = (int*)malloc((paraN + 1) * sizeof(int)); for (i = 0; i <= paraN; i ++) solution[i] = 0; backtracking(solution, paraN, 1); }//Of nQueen //The entrance. int main(){ nQueen(4); return 1; }//Of main

1.5运行结果

1 3 5 2 4
1 4 2 5 3
2 4 1 3 5
2 5 3 1 4
3 1 4 2 5
3 5 2 4 1
4 1 3 5 2
4 2 5 3 1
5 2 4 1 3
5 3 1 4 2

--------------------------------
Process exited after 0.1284 seconds with return value 1
请按任意键继续. . .

改变数据为四

2 4 1 3
3 1 4 2

--------------------------------

2.1哈夫曼树

给定n个权值作为n个叶子结点,构造一棵二叉树,若该树的带权路径长度达到最小,则称该二叉树为哈夫曼树,也被称为最优哈夫曼树。树的带权路径长度规定为所有叶子结点的带权路径长度之和,记为WPL。权值就是定义的路径上面的值。可以这样理解为结点间的距离。二叉树的一种特殊情况。学长代码理解临摹。

实现:输入字符喘后统计每个字符出现次数,构造哈夫曼树,选择权重最小的两个节点,创建哈夫曼编码01,将读入的文件编码,写到txt文件 ,读入编码文件,解码 ,同样规则原样输出。

2.2具体实现

2.2.1结构体定义与初始化

typedef struct NODE
{
    char c;
    //结点权重
    int weight;
    //记录结点表示的二进制,左0右1
    int binary;
    //是否已经创建该结点,1为创建,0为未创建
    int flag;//判断 

    struct NODE *lchild, *rchild, *parent;

} NODE, *PNODE;

typedef struct
{
    int valuse[MAXSIZE];
    int top;
} STACK;

 //栈的相关操作

void initStack(STACK &stack)
{
    stack.top = 0;
}

void push(STACK &stack, int value)
{
    stack.valuse[stack.top++] = value;
}

int pop(STACK &stack)
{
    if (stack.top == 0)
        return -1;
    stack.top--;
    return stack.valuse[stack.top];
}

//初始化树结点
void initNode(PNODE node)
{
    node->lchild = NULL;
    node->parent = NULL;
    node->rchild = NULL;
    node->flag = 0;
    node->weight = 0;
    node->c = -1;
    node->binary = 0;
}

2.2.2创建结点,param 新节点的权重

PNODE createNode(int weight)
{
    PNODE node = (PNODE)malloc(sizeof(NODE));
    if (node)
    {
        initNode(node);
        node->weight = weight;
    }
    return node;
}

2.2.3进行字符,字符串的编码

对一棵具有n个叶子结点的哈夫曼树,若对树中的每个左分支赋0,右分支赋1(或左1右0),则从根到每个叶子的通路上,各个分支的赋值分别构成一个二进制串,哈夫曼编码为最优前缀编码,能使各种报文对应的二进制串的平均长度最短。param c 欲编码的字符 param childrenNodes 叶子结点的集合param lenOfNodes 叶子结点的个数return 返回保存该叶子结点路径的栈,param str 欲编码的字符串 ,param childrenNodes 哈夫曼树的叶子节点的集合,param lenOfNodes 叶子结点的个数, return 返回编码后的二进制字符串
 

STACK charEncode(char c, PNODE childrenNodes, int lenOfNodes)
{
    STACK stack;
    initStack(stack);
    
    for (int i = 0; i < lenOfNodes; i++)
    {
        if (c == childrenNodes[i].c)
        {
            PNODE tmp = &childrenNodes[i];
            while (tmp->parent != NULL)
            {
                push(stack, tmp->binary);
                tmp = tmp->parent;
            }
            break;
        }
    }
    return stack;
}


char *strEncode(char *str, PNODE childrenNodes, int lenOfNodes)
{
    char *result = (char *)malloc(sizeof(char) * MAXSIZE * lenOfNodes);
    int len = 0;
    
    while (*str != '')
    {
        STACK stack = charEncode(*str, childrenNodes, lenOfNodes);
        while (stack.top > 0)
        {
            result[len++] = pop(stack) + '0';
        }
        str++;
    }
    result[len] = '';
    return result;
}

2.2.4获取权重最小节点

PNODE getMinWeightNode(PNODE nodes, int lenOfNodes)
{
    PNODE node;
    int min = 0, i;
    //对已创建过的结点进行过滤
    while (min < lenOfNodes)
    {
        if (nodes[min].flag == 0)
        {
            break;
        }
        min++;
    }
    if (min == lenOfNodes)
    {
        return NULL;
    }
//查找未创建的结点中权重最小的结点
    for (i = min + 1; i < lenOfNodes; i++)
    {
        if (nodes[i].flag == 0 && nodes[i].weight < nodes[min].weight)
        {
            min = i;
            continue;
        }
    }
    nodes[min].flag = 1;
    return &nodes[min];
}

2.2.5进行创建通过叶子结点数创建哈夫曼树

PNODE createHuffmanTree(PNODE nodes, int lenOfNodes, PNODE childNode)
{
    PNODE minWeightNode, parentNode;

    minWeightNode = getMinWeightNode(nodes, lenOfNodes);

    if (!minWeightNode)
        return childNode;

    if (!childNode)
    {
        parentNode = minWeightNode;
    }
    else
    {
        parentNode = createNode(childNode->weight + minWeightNode->weight);

        if (childNode->weight < minWeightNode->weight)
        {
            parentNode->lchild = childNode;
            parentNode->rchild = minWeightNode;
        }
        else
        {
            parentNode->rchild = childNode;
            parentNode->lchild = minWeightNode;
        }
        parentNode->lchild->binary = 0;
        parentNode->rchild->binary = 1;

        childNode->parent = minWeightNode->parent = parentNode;
    }

    createHuffmanTree(nodes, lenOfNodes, parentNode);
}

2.2.6据字符出现频率创建哈夫曼树

PNODE readFromSource(const char *filePath, char *buff, PNODE childrenNodes, int &lenOfNodes)
{

    //记录字符串长度
    int lenOfStr = 0, i;

    //记录当前读取的字符
    char c;

    FILE *file = fopen(filePath, "rb");

    if (file == NULL)
    {
        puts("Can't find source file!");
        exit(0);
    }

    //一个字符一个字符读入本地文本
    c = fgetc(file);
    while (!feof(file))
    {
        c = charTolowercase(c);
        //初始化结点
        initNode(&childrenNodes[lenOfNodes]);

        buff[lenOfStr++] = c;
        for (i = 0; i < lenOfNodes; i++)
        {
            if (childrenNodes[i].c == c)
            {
                childrenNodes[i].weight++;
                break;
            }
        }
        if (i == lenOfNodes)
        {
            childrenNodes[lenOfNodes].c = c;
            childrenNodes[lenOfNodes++].weight++;
        }
        c = fgetc(file);
    }
    buff[lenOfStr] = '';

    fclose(file);
    return createHuffmanTree(childrenNodes, lenOfNodes, NULL);
}

2.2.7编码后的存入文件

void writeResult(const char *filePath, char *result)
{
    FILE *fp = fopen(filePath, "sc");
    if (fputs(result, fp) >= 0)
    {
        printf("生成结果成功rn");
    }
    fclose(fp);
}

2.2.8解压

char *strDecode(const char *str, PNODE TreeRoot)
{
    const char *tmp = str;
    char *result = (char *)malloc(sizeof(char) * MAXSIZE);
    //用来记录结果字符串的长度
    int len = 0;
    while (*tmp != '')
    {
        PNODE tmpNode = TreeRoot;
        while (tmpNode->lchild && tmpNode->rchild)
        {
            tmpNode = *tmp == '0' ? tmpNode->lchild : tmpNode->rchild;
            tmp++;
        }
        result[len++] = tmpNode->c;
    }
    result[len] = '';
    return result;
}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/935763.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号