在一段连续空间里面,维护N个stack 的回帖
程序2个优化 函数一个有问题 一个还要重写。。排序的函数 不知道哪里出了错误 当全部出栈了时候 再压栈的时候当时没有问题。但测试函数去测试的时候会崩溃。
找了好就没有找出来。算了, 大概程序的思路 开始我就有了。可能是那地方的细节没有处理好吧。。
因为各种原因,我就没有在那张帖子回帖
问题:在一段连续的内存空间里面,维护N个stack, 并且每个stack可以独立push 和pop,只要整个空间还有空余,都可以做push, 当然被维护的stack空了,是不可以pop的.
我的程序只有了一个栈测试,但是没有影响一样的是可以测试。
思路:2个链表。 一个是空闲表 和一个是占用表。
空闲表: 保存那块内存可以用的内存。
占用块: 保存占用内存块的地址和大小信息(这样就可以不需要在那块内存里面保存一些不必要的信息)
_malloc 函数: 给栈分配内存的函数(是那块固定的内存)
_free 函数; 给栈释放内存 主要是修改空闲表 占用表的信息 再调用SortMem是空闲表从小到大排序。在用merge()函数合并能够掐前后在一起的内存块。
由于排序 我的有BUG 所以 合并函数 我要重写。
所以这2个函数都有问题。我就把他们注释掉了。
但这样也可以满足要求,但这样内存碎片就会很多。 所以这样的程序,效率就不高了。由于找了好久错误,没有找出来。
加上这个程序 我思路基本都有了。所以不想浪费继续找出错了。 如果你能指点一下,那我非常感谢你。
思路 来之以前写的malloc 和free() 函数模拟来的。。。。。。
manage.h
程序代码:#ifndef MANAGE_H_INCLUDED
#define MANAGE_H_INCLUDED
#include "stack.h"
#define Stack_N 2
#define MINI_SIZE 8 // 相差最下的范围 8字节
extern const int valume;//1000个字节大小
extern char room[]; //内存最小单位是一个字节 可以把这块内存分成valume块
typedef struct tagMem_block
{
int size; //内存空闲块的大小
void *addr; //放的地址
struct tagMem_block *next;
struct tagMem_block *pre;
}mem_block;
typedef struct tagun_block
{
int size;
void *addr;
struct tagun_block* next;
}un_block;
extern un_block *un_head;//放已经分配的信息
//un_head->next = NULL;
typedef struct tagManage
{
mem_block head;
mem_block *tail;
int availible; //剩下可以利用的内存大小 单位字节
}Manage;
extern Manage ma;
extern int isInit;
void Init();
void SortMem();//把空闲块的大小排序从小到大排序
void* _malloc(int size);
void _free(void* p);
void merge();//优化函数
int GetInfo(void* p); //获得释放指针的大小信息
void UnListAdd(void* p,int size); //占用表的处理
void MemListAdd(void* p, int size); //空闲表的处理
/*****************************测试函数************************************/
void TraUnBlock();
void TraMemBlock();
#endif // MANAGE_H_INCLUDED
stasck.h
程序代码:#ifndef STACK_H_INCLUDED
#define STACK_H_INCLUDED
#include <stdio.h>
#include <stdlib.h>
#define datetype int
typedef struct tagStackNode
{
datetype date;
struct tagStackNode* next;
}StackNode;
typedef struct tagStack
{
StackNode* head;
StackNode* tail;
int num;
}Stack;
//创建栈
void CreateStack(Stack* s);
//进栈
void Push(Stack* s,datetype date);
//出栈
datetype Pop(Stack* s);
#endif // STACK_H_INCLUDED
manage.cpp
程序代码:#include "manage.h"
un_block *un_head = NULL ;
Manage ma;
int isInit = 0;
const int valume = 64*sizeof(char);
char room[valume];
void Init()
{
ma.availible = valume;
ma.head.addr = room;
ma.head.next = NULL;
ma.head.size = valume;
ma.tail = &ma.head;
ma.tail->next = NULL;
}
//次函数功能 分配对应的内存。
//把这块内存的信息添加到占用表中
//然后求剩下的空闲表
void *_malloc(int size)
{
if(0 == isInit)
{
Init();
isInit = 1;
}
if(ma.availible < size)
{
return NULL; //分配内存失败
}
//printf("ma 的信息 size %d",ma.head.size);
mem_block *p; //指向空闲内存块的指针
//un_block* pt; //指向占用块内存的指针
//这里还要处理ma.head 中的东西啊
//开始的时候空闲块就是我们提供的那块全部的内存块
for(p = &ma.head;p;p=p->next)
{
if(p->size - size <0)
{
puts("内存不足");
continue;//当当前结点不满足需要的内存,如是寻找下一个结点
}
if(p->size - (size)>0)//我的空闲块的顺序是按大小排序的
{ //当前,内存块大小满足时候
p->size -= size; //但要判断是否正好相等与
ma.availible -= size;
//printf("内存减少到%d",ma.availible);
void *tp = p->addr;
void* pp=(char*)(p->addr)+size; //移动size个字节
p->addr = pp;
//puts("这里分配的内存1");
UnListAdd(tp,size); //占用表的处理
return tp; //因为相等和不想等处理方式是一样的
} //但当空闲块大小大于需要的内存块的时候
else //只要把这个空闲块的大小改掉就可以了
if(p->size - size ==0)
{
//当空闲块大小相等于的时候,我需要把这个
//保存空闲块的链表的结点释放掉。
//当这里就有一个特殊情况了,正好整个空闲块的大小变为
//0的时候,空闲块的指针要怎么表示的问题,
//ma.head 赋值为空。
if(NULL!=p->next) //当前结点不是最后一个结点的时候
{
puts("这里分配的内存2");
if(p!=&ma.head)
{
UnListAdd(p->addr,size); //占用表的处理
p->pre->next = p->next; //当不是最后一个空闲块的时候
p->next->pre = p->pre;
void *pp = p->addr;
free(p); // 释放掉结点
ma.availible -= size;
//printf("内存减少到%d",ma.availible);
return pp;
}
else
{
//添加到占用表里面
// puts("这里分配的内存3");
UnListAdd(p->addr,size);
//把空闲表的头指针后移动下一个结点
ma.head = *ma.head.next; //
free(ma.head.next);
ma.availible -= size;
// printf("内存减少到%d",ma.availible);
return p->addr;
}}
else
{
//当是最后一个结点的时候
UnListAdd(p->addr,size);
//是为尾结点的但不是剩下的最后一个空闲块的时候
if(p!=&ma.head)
{
// puts("这里分配的内存4");
ma.tail->pre->next = NULL;
void* pp = ma.tail;
ma.tail = ma.tail->pre;
ma.availible -= size;
//printf("内存减少到%d",ma.availible);
free(pp);
}
else
{
//剩下最后一个空闲块的时候
// puts("这里的分配的内存5");
//puts("是这里出了问题吗");
void* pp = ma.head.addr;
ma.tail = NULL;
ma.availible = 0;
ma.head.addr =NULL;
ma.head.size = 0;
//printf("内存减少到%d",ma.availible);
return pp;
}
}
//这里要处理相等于的特殊情况
//当是第一个空闲块的时候是一个特殊情况
}
}
return NULL;
}
//必须判断是否为占用表的地址 不是的做出assert 处理
void _free(void* p) //p 是地址
{
int size = GetInfo(p);
//添加到链表的最后
//printf("获得size %d\n",size);
MemListAdd(p,size);
//SortMem(); //空闲表排序
//merge();//合并
//下面对占用表做出相应的处理
un_block *pre;
un_block *cur;
cur = un_head;
pre = NULL;
while(cur)
{
if(cur->addr == p)
{
if(cur!=un_head)
{
pre->next = cur->next; //释放该结点
ma.availible+=size;
free(cur);
return;
}
else
{
if(cur->next== NULL) //当为最后一个占用的结点的时候
{
free(un_head);
ma.availible+=size;
un_head = NULL;
return;
}
else
{
void *t = cur;
cur = cur->next;
un_head = cur; //一定要修改这全局变量
ma.availible+=size;
free(t);
return; //不要掉了reutrn; 不然下面还要运算 导致非法指针 我调试了好久啊
}
}
}
pre = cur;
cur = cur->next;
}
}
//释放地址的时候,把这个地址与空闲表中的地址进行对比进行优化
void merge()
{
mem_block* ptr,*pre;
char* addr;
for(ptr = &ma.head;pre = ptr,ptr = ptr->next;)
{
addr = (char*)ptr->addr;
addr += ptr->size;
if(addr == ptr->addr)
{
if(ptr->next)
{
pre = ptr->next;
ptr->next->pre = pre;
pre->size+= ptr->size;
free(ptr);
}
else
{
pre->size+=ptr->size;
pre->next = NULL;
free(ptr);
}
}
}
}
void SortMem()
{
mem_block* p;
mem_block* p1;
mem_block* min,*t1;
int i,j;
void* addr;
void* t;
int k =1;
for(p = &ma.head; p; p = p->next)
{
i = p->size;
addr = p->addr;
for(p1 = p; p1; p1 = p1->next)
{
if(i > (p1->size))
{
j = i;
i = p1->size;
p1->size = j;
t = addr;
addr = p1->addr;
p1->addr = t;
}
}
p->size = i;
p->addr = addr;
}
/* for(p = &ma.head;p;p=p->next)
{
i = p->size;
//puts("在排序");
addr = (void*)(p->addr);
for(p1 = p; p1; p1=p1->next)
{
if(i>(p1->size))
{
//puts("交换中");
j = i;
i = p1->size;
p1->size = j;
t = addr;
addr = (void*)p1->addr;
p1->addr = t;
}
}
p->size = i;
p->addr = addr;
//printf("交换%d次 size %d , 地址 %d",k++,i, addr);
}*/
}
int GetInfo(void* p)
{
un_block * ptr;
for(ptr = un_head;ptr;ptr = ptr->next)
{
if(ptr->addr == p)
{
return ptr->size;
}
}
return 0;
}
void TraUnBlock()
{
un_block* p;
for(p = un_head; p; p = p->next)
{
printf("当前的结点的大小 %d\t",p->size);
printf("当前的地址是%d\t",p->addr);
printf("我保存的数据%d\n",*(int*)p->addr); //我因为定义的是整形
}
}
void TraMemBlock()
{
mem_block* p;
if(ma.head.addr==0)
{
puts("空闲表为空");
return;
}
printf("总共空闲块的大小:%d \n",ma.availible);
printf("空闲链表的第一个块的地址 %d\n",ma.head.addr);
for(p = &ma.head; p; p = p->next)
{
printf("pp %d",p);
printf("空闲块的大小:%d\n",p->size);
printf("空闲块的地址:%d\n",p->addr);
}
}
void UnListAdd(void* p,int size)
{
if(NULL == un_head) //当链表头还没有分配空间的时候
{
un_head =(un_block*)malloc(sizeof(un_block));
if(NULL == un_head)
{
puts("占用表的内存申请失败1");
return;
}
un_head->addr = p;//保存当前的内存块的地址
un_head->size = size; //保存内存块大小的信息
un_head->next = NULL;
}
else //当占用块的链表的头已经处理的时候
{
un_block* pt;
pt = (un_block*)malloc(sizeof(un_block));
if(NULL == pt)
{
puts("占用表的内存申请失败2");
return;
}
//保存占用块的信息
pt->size = size;
pt->addr = p;
//头部添加的方法
pt->next = un_head;
un_head = pt;
}
}
void MemListAdd(void* p, int size)
{
if(ma.head.addr == NULL) //我在结构中给head 是定义不是指针;
{
ma.head.addr = p;
ma.head.next =NULL;
//ma.availible = size; //当空闲链表没有空闲的时候
ma.tail = &ma.head;
ma.tail->next = NULL;
ma.head.size = size;
return;
}
else
{
mem_block* ptr;
ptr = (mem_block*)malloc(sizeof(mem_block));
if(ptr == NULL)
{
puts("MemListAdd 内存申请失败");
return;
}
ptr->addr = p;
ptr->size = size;
ptr->next = NULL;
ptr->pre = ma.tail;
ma.tail->next = ptr;
ma.tail = ptr; //指向最后一个结点
//ma.availible+= size;
}
}
stack.cpp
程序代码:#include "stack.h"
#include "manage.h"
void CreateStack(Stack* s)
{
s->head = NULL;
s->tail = NULL;
s->num = 0;
}
void Push(Stack* s,datetype da)
{
//StackNode* Ptr = (StackNode*)malloc(sizeof(StackNode));
StackNode* Ptr = (StackNode*)_malloc(sizeof(StackNode)); //_malloc 返回的是自己给他的内存块地址
//printf("malloc 后的地址 un_head %d",un_head);
if(NULL == Ptr)
{
puts("内存申请失败");
return;
}
//puts("内存申请成功一个");
//getchar();
Ptr->date = da;
Ptr->next = NULL;
if(NULL == s->head)
{
s->head = Ptr;
s->tail = Ptr;
s->num++;
s->head->next = NULL;
s->tail->next = NULL;
}
else
{
Ptr->next = s->head;
s->head = Ptr;
s->num++;
}
}
datetype Pop(Stack* s)
{
void *p;
if(0 == s->num)
{
puts("栈已经全部为空");
return -1;
}
else
{
//printf("\nu_head add %d\n",un_head);
datetype da;
da = s->head->date;
p = (void*)s->head;
//printf("pp pp %d",p);
//getchar();
s->head= s->head->next;
s->num--;
//printf("s->head %d\n",s->head);
//printf("\n head is %d\n",p);
//printf("\n head is %d\n",p);
//printf("\nu_head add %d\n",un_head);
//free(p); //鎴戣繕娌″摕鍐欏ソ_free()锛?
_free(p);
return da;
}
}
main.cpp
程序代码:#include <iostream>
#include "stack.h"
#include "manage.h"
using namespace std;
int main()
{
Stack s;
CreateStack(&s);
printf("room %d\n",room);
//Init();
// for(int i = 0; i < 5; i++)
// {
// Push(&s,i);
// }
// Push(&s,23);
// Push(&s,34);
// Push(&s,231);
// puts("11111111");
// TraMemBlock();
// Pop(&s);
// puts("22222222");
// TraMemBlock();
// Push(&s,1314);
//
// TraUnBlock();
// TraMemBlock();
Push(&s,1);
Push(&s,2);
Pop(&s);
Push(&s,12);
Push(&s,1246);
Pop(&s);
TraMemBlock();
Push(&s,345);
TraMemBlock();
TraUnBlock();
// Push(&s,3434);
// TraUnBlock();
// int k = Pop(&s);
// printf("hh k %d\n",k);
//TraUnBlock();
// TraUnBlock();
// while(s.num)
// {
// datetype k;
// k = Pop(&s);
// cout<<k<<endl;
// }
//
// TraMemBlock();
// TraUnBlock();
return 0;
}
[ 本帖最后由 小鱼儿c 于 2012-3-19 18:09 编辑 ]










