C语言编写可以实现malloc() & free()功能的函数(空间/时间复杂度低)

#include <stdio.h>

typedef struct _BLOCK   //定义一个结构体,用于记录所有可用区块的大小及位置
{
    unsigned int size;
    struct _BLOCK xdata* pLink;

}BLOCK,xdata* PBLOCK;

PBLOCK xdata pHead = NULL;

// 
// Initialize 
//    Init the Block  
// 
// Formal Parameters: 
//    memory = the address of memory
//    len = the size of the memory   
// 
// Global Input Parameters: 
//    None
// 
// Global Output Parameters: 
//    None 
// 
// Return Value: 
//    None 
//
void 
MemInitializePool(
    void* memory,
    unsigned len
    )
{
    pHead = (PBLOCK)memory;   //头结点指向自定义用于分配内存的空间
    pHead->pLink = NULL;
    pHead->size = len;
}

// 
// MyMalloc 
//    malloc the space  
// 
// Formal Parameters: 
//    needSize = size of the Block we need    
// 
// Global Input Parameters: 
//    None
// 
// Global Output Parameters: 
//    None 
// 
// Return Value: 
//    result = the location of the Block 
//
void* 
MemAlloc(
    unsigned int needSize
    )
{
    PBLOCK pPrior,pNext,pNewNode;
    void* result;
    pNext  = pHead;
    pPrior = pHead;
    do
    {
        if ( pNext->size >= needSize )     //寻找到合适大小的空白区块
        {
            pNext->size    = pNext->size - needSize - sizeof(BLOCK);  //分配空间出去
            pNewNode       = (PBLOCK)((void*)pNext + pNext->size + sizeof(BLOCK));//得到存储信息的空间的地址
            pNewNode->size = needSize; //可使用的空间大小
                        
            if(pNext->size < sizeof(BLOCK))
            {
                pPrior->pLink = pNext->pLink;
            }

            result = (void*)(++pNewNode);//返回分配出去的空间地址
            return result;
        }

        pPrior = pNext;
        pNext  = pNext->pLink;
    
    }while ( pNext != NULL );
    if(pNext == NULL)                //over
    {
        return NULL;
    }    
}


// 
// merge 
//    merge the Block we needn't use  
// 
// Formal Parameters: 
//    pPrior = the node of the Link
//    pNext = the pLink node of the Link    
// 
// Global Input Parameters: 
//    None
// 
// Global Output Parameters: 
//    None 
// 
// Return Value: 
//    None 
//
void 
Merge(
    PBLOCK pPrior,
    PBLOCK pNext
    )
{
    if ( pNext == (PBLOCK)((void*)pPrior + pPrior->size + sizeof(PBLOCK)) ) //如果两个空白区块连续,合并空间
    {
        pPrior->size += (pNext->size) + sizeof(BLOCK);
        pPrior->pLink = pNext->pLink;
    }
}

// 
// MemFree 
//    free the Block we used  
// 
// Formal Parameters: 
//    pBlock = the location of the Block we need to free  
// 
// Global Input Parameters: 
//    None
// 
// Global Output Parameters: 
//    None 
// 
// Return Value: 
//    None 
//
void 
MemFree(
    PBLOCK pBlock
    )
{
    PBLOCK pFree  = (--pBlock);
    PBLOCK pNext  = pHead;
    PBLOCK pPrior = pHead;

    do
    {
        pPrior = pNext;
        pNext  = pNext->pLink;

        if( pPrior <= pFree && pNext >= pFree)  //找到所需要释放的区块的位置
        {
            pFree->pLink = pNext;
            pPrior->pLink = pFree;
            break;
        }

    }while ( pNext != NULL );
    //合并空白区块
    Merge(
        pPrior,
        pFree
        );
    Merge(
        pFree,
        pNext
        );
}

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
生成哈夫曼树的算法有很多种,其中最常用的就是贪心算法。以下是用C语言实现时间复杂度为O(n)的生成哈夫曼树的代码,并计算带权路径的长度: ```c #include &lt;stdio.h&gt; #include &lt;stdlib.h&gt; #define MAX_SIZE 100 typedef struct { int weight; // 权值 int parent; // 父节点 int leftChild; // 左孩子 int rightChild; // 右孩子 } HTNode, *HuffmanTree; typedef char * *HuffmanCode; // 构建哈夫曼树 void CreateHuffmanTree(HuffmanTree *HT, int n) { if (n &lt;= 1) { return; } int m = 2 * n - 1; *HT = (HuffmanTree)malloc((m + 1) * sizeof(HTNode)); // 0号单元不用 // 初始化 for (int i = 1; i &lt;= m; i++) { (*HT)[i].parent = 0; (*HT)[i].leftChild = 0; (*HT)[i].rightChild = 0; } // 输入权值 printf(&quot;请输入%d个权值:\n&quot;, n); for (int i = 1; i &lt;= n; i++) { scanf(&quot;%d&quot;, &amp;((*HT)[i].weight)); } // 构建哈夫曼树 for (int i = n + 1; i &lt;= m; i++) { // 找出权值最小的两个节点 int min1 = 0, min2 = 0; for (int j = 1; j &lt; i; j++) { if ((*HT)[j].parent == 0) { if (min1 == 0 || (*HT)[j].weight &lt; (*HT)[min1].weight) { min2 = min1; min1 = j; } else if (min2 == 0 || (*HT)[j].weight &lt; (*HT)[min2].weight) { min2 = j; } } } // 合并节点 (*HT)[min1].parent = i; (*HT)[min2].parent = i; (*HT)[i].leftChild = min1; (*HT)[i].rightChild = min2; (*HT)[i].weight = (*HT)[min1].weight + (*HT)[min2].weight; } } // 构建哈夫曼编码 void CreateHuffmanCode(HuffmanTree HT, HuffmanCode *HC, int n) { *HC = (HuffmanCode)malloc((n + 1) * sizeof(char *)); char *cd = (char *)malloc(n * sizeof(char)); // 临时存放编码 cd[n - 1] = &#39;\0&#39;; for (int i = 1; i &lt;= n; i++) { int start = n - 1; for (int c = i, f = HT[i].parent; f != 0; c = f, f = HT[f].parent) { if (HT[f].leftChild == c) { cd[--start] = &#39;0&#39;; } else { cd[--start] = &#39;1&#39;; } } (*HC)[i] = (char *)malloc((n - start) * sizeof(char)); strcpy((*HC)[i], &amp;cd[start]); } free(cd); } // 计算带权路径长度 int WeightedPathLength(HuffmanTree HT, int n) { int wpl = 0; for (int i = 1; i &lt;= n; i++) { int c = i; int f = HT[i].parent; while (f != 0) { if (HT[f].leftChild == c) { wpl += HT[f].weight; } c = f; f = HT[f].parent; } } return wpl; } int main() { HuffmanTree HT; HuffmanCode HC; int n; printf(&quot;请输入叶子节点个数:\n&quot;); scanf(&quot;%d&quot;, &amp;n); CreateHuffmanTree(&amp;HT, n); CreateHuffmanCode(HT, &amp;HC, n); printf(&quot;哈夫曼编码如下:\n&quot;); for (int i = 1; i &lt;= n; i++) { printf(&quot;%d: %s\n&quot;, i, HC[i]); } int wpl = WeightedPathLength(HT, n); printf(&quot;带权路径长度为:%d\n&quot;, wpl); free(HT); free(HC); return 0; } ``` 上述代码中,CreateHuffmanTree函数用于构建哈夫曼树,CreateHuffmanCode函数用于构建哈夫曼编码,WeightedPathLength函数用于计算带权路径长度。在主函数中,先输入叶子节点个数,然后调用上述三个函数完成哈夫曼树的生成、编码的构建和带权路径长度的计算。 其中,CreateHuffmanTree函数中,先输入叶子节点的权值,然后采用贪心算法逐步合并节点,直到最后得到哈夫曼树。 CreateHuffmanCode函数中,先申请足够的内存空间,然后采用递归的方式,从叶子节点到根节点,逆序求得每个叶子节点的哈夫曼编码。 WeightedPathLength函数中,采用从叶子节点到根节点的逆序遍历方式,计算出每个叶子节点的带权路径长度,最后累加起来即可得到整棵树的带权路径长度。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值