练习45

/**************************************************************************************

  45. (数列的最小代价) 给定一个正整数序列,例如:4,1,2,3, 不改变数的位置把
 它们相加, 并且由括号来标记每一次加法所得到的和。例如:((4+1)+(2+3))=
 ((5)+(5))=10. 除去原数4、1、2、3之外,其余都为中间结果,如:5,5,10, 将中
 间结果相加,得到:5+5+10=20, 数 20 称为此数列的一个代价。对于另一种算法:
 (4+((1+2)+3))=(4+((3+3))=(4+(6))=10, 得到数列的另一个代价为:3+6+10=19.
 若给出 N 个数的数列,求出此数列的最小代价。

  贪心算法求解

  *************************************************************************************/

#include <stdio.h> 
#include <malloc.h> 

typedef struct tagTreeNode
{
    int data;
    tagTreeNode *left;
    tagTreeNode *right;
} TreeNode;

typedef struct tagLinkNode
{
    TreeNode *pTreeNode;
    tagLinkNode *pNext;
} LinkNode;

LinkNode *head = NULL;
LinkNode *tail = NULL;
TreeNode *root = NULL;

//创建一个链表,保存数列 
void CreateLink(int n)
{
    int i;
    int data;
    TreeNode *tempTreeNode;
    LinkNode *tempLinkNode;

    for(i=0; i<n; i++)
    {
        scanf("%d",&data);
        tempTreeNode = (TreeNode*)malloc(sizeof(TreeNode));
        tempTreeNode->data = data;
        tempTreeNode->left = NULL;
        tempTreeNode->right = NULL;
        tempLinkNode = (LinkNode*)malloc(sizeof(LinkNode));
        tempLinkNode->pTreeNode = tempTreeNode;
        tempLinkNode->pNext = NULL;
        if(!head)
            head = tail = tempLinkNode;
        else 
        {
            tail->pNext = tempLinkNode;
            tail = tail->pNext;
        }
    }
}

//插入元素 
LinkNode* InsertAfter(LinkNode *pLinkNode,int data)
{
    TreeNode *tempTreeNode;
    LinkNode *tempLinkNode = NULL;

    if(pLinkNode)
    {
        tempTreeNode = (TreeNode*)malloc(sizeof(TreeNode));
        tempTreeNode->data = data;
        tempTreeNode->left = NULL;
        tempTreeNode->right = NULL;
        tempLinkNode = (LinkNode*)malloc(sizeof(LinkNode));
        tempLinkNode->pTreeNode = tempTreeNode;
        tempLinkNode->pNext = NULL;
        
        tempLinkNode->pNext = pLinkNode->pNext;
        pLinkNode->pNext = tempLinkNode;
        if(pLinkNode == tail)
            tail = tempLinkNode;
    }

    return tempLinkNode;
}

//删除元素 
void DeleteLinkNode(LinkNode *pLinkNode)
{
    LinkNode *p,*q;
    if(pLinkNode == head)
    {
        head = head->pNext;
        if(head == NULL)
            tail = NULL;
        free(pLinkNode);
    }
    else 
    {
        p = NULL;
        q = head;
        while(q)
        {
            p = q;
            q = q->pNext;
            if(q == pLinkNode)
            {
                p->pNext = q->pNext;
                free(pLinkNode);
                break;
            }
        }
    }
}

//计算 
int Calc()
{
    int sum = 0;
    int min_sum;
    LinkNode *p,*q,*min,*pnew;

    while(head != tail)
    {
        p = NULL;
        q = head;
        min = q;
        min_sum = min->pTreeNode->data + min->pNext->pTreeNode->data;
        while(q)
        {
            p = q;
            q = q->pNext;
            
            if(q)
            {
                if(q->pTreeNode->data + p->pTreeNode->data < 
                    min_sum)
                {
                    min = p;
                    min_sum = min->pTreeNode->data + min->pNext->pTreeNode->data;
                }
            }
        }
        sum += min_sum;
        pnew = InsertAfter(min->pNext,min_sum);
        pnew->pTreeNode->left = min->pTreeNode;
        pnew->pTreeNode->right = min->pNext->pTreeNode;
        DeleteLinkNode(min->pNext);
        DeleteLinkNode(min);
    }
    root = head->pTreeNode;
    DeleteLinkNode(head);
    
    return sum;
}

//打印结果 
void PrintTree(TreeNode *ptree)
{
    if((!ptree->left) && (!ptree->right))
    {
        printf("%d",ptree->data);
    }
    else
    {
        printf("(");
        PrintTree(ptree->left);
        printf("+");
        PrintTree(ptree->right);
        printf(")");
    }
}

void main()
{
    int n,sum;

    printf("请输入数列元素的个数N: ");
    scanf("%d",&n);
    CreateLink(n);
    sum = Calc();
    printf("min = %d /n", sum);
    PrintTree(root);
}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值