《C系列-实例相关》C语言实例二

1.基于C语言的分支限界法

采用分支限界法解决集装箱问题:
问题:有n个集装箱要装上一艘载重量为W的轮船,其中集装箱i(1≤i≤n)的重量为wi。
在装载体积不受限制的情况下,将尽可能重的集装箱装上轮船,当总重量相同时要
求选取的集装箱个数尽量少。编写一个实验程序采用分枝限界法求解,设计合理的限
界函数,并采用队列式分支限界法求最优解。其中,n=5,W=10,w={5,2,6,4,3}
集装箱个数:n;
轮船可承载重量:W;
集装箱i的重量wi;
思路:
1.对于第i层的结点e,已装载的集装箱的总重量为e.w,剩余集装箱重量为r, 定义结点e的上届函数为e.w+r.
2.对于左孩子结点,当满足e.w+w[e.i+1]>W时会变成死结点,对于e结点的右孩子节点,其上界最优解的装载重量maxw,被剪枝
3.在队列基本运算中,函数对队列进行初始化判断,以及判空操作,结点的进队操作
4.在分支限界法操作过程中,实现记录分支结点的上界,计算并输出最优解。
5.队列式分支限界法,建立队列,并采用先进先出的原则,选择下一个结点作为拓展结点

#include<stdio.h>//主函数 
#define MAXN 20//最多集装箱数 
#define MAXQ 50//队列大小 
int maxw = 0;//全局变量,存放最大装载重量 
int maxx[MAXN] = {0};//全局变量,存放最优解  
int count = 1;//全局变量,累计节点数 
typedef struct
{
	int no;
	int i;
	int w;
	int x[MAXN];
	int ub;
}ElemType;//队列结点类型定义 
typedef struct
{
	ElemType data[MAXQ];
	int front,rear;
}QueueType;//队列类型 
void copyx(int x[],int y[],int i)//实现解向量复制功能 
{
	int j;
	for(j=0;j<=i;j++)
		y[j]=x[j];
}
void elemcopy(ElemType a,ElemType &b)//队列结点复制 
{
	b.no=a.no;b.i=a.i;
	b.ub=a.ub;b.w=a.w;
	copyx(a.x,b.x,a.i);//调用void copyx() 
}
void initQueue(QueueType &q)//队列初始化 
{
	q.front=q.rear=0;//头结点等于尾结点等于零 
}
int emptyQueue(QueueType q)//判空操作
{
	return q.front==q.rear;//头结点与尾结点在同一位置 
}
int enQueue(QueueType &q,ElemType e,int n)//进队操作 
{
	if((q.rear+1)%MAXQ==q.front)//判断队是否为满 
		return 0;
	else//可进队 
	{
		if(e.i==n)//可行叶子结点,不进队 
		{
			if(e.w>maxw||(e.w==maxw&&e.x[0]<maxx[0]))//比较找最优解 
			{maxw=e.w;
			copyx(e.x,maxx,n);
		}
		
		}
		else//其他结点进队 
		{
			q.rear=(q.rear+1)%MAXQ;
			elemcopy(e,q.data[q.rear]);
		}
		return 1;
	}
}
int deQueue(QueueType &q,ElemType &e)//结点e出队 
{
	if(emptyQueue(q))//调用判空函数 
		return 0;
	else
	{
		q.front=(q.front+1)%MAXQ;
		elemcopy(q.data[q.front],e);
		return 1;
	}
}
void bound(int w[],int W,int n,ElemType &e)//计算分支结点e的上界 
{
	int i=e.i+1;
	int r=0;//剩余集装箱重量 
	while(i<=n)
	{
		r+=w[i];
		i++;
	}
	e.ub=e.w+r;
	
}
void Loading(int w[],int W,int n)//采用队列式分支限界法求解装载问题的最优解 
{
	int j;
	QueueType q;//建立一个队列 
	initQueue(q);//队列初始化 
	ElemType e,e1,e2;//定义三个结点 
	e.i=0;
	e.w=0;
	e.no=count++;
	for(j=0;j<=n;j++)
		e.x[j]=0;
		bound(w,W,n,e);//求根结点的上界 
		enQueue(q,e,n);//根节点进队 
		while(!emptyQueue(q))//判空操作 
		{
			deQueue(q,e);
			if(e.w+w[e.i+1]<=W)
			{
				e1.no=count++;
				e1.i=e.i+1;//建立左孩子结点 
				e1.w=e.w+w[e1.i];
				copyx(e.x,e1.x,e.i);
				e1.x[0]++;//装入集装箱数增1 
				e1.x[e1.i]=1;
				bound(w,W,n,e1);//求左孩子结点的上界 
				enQueue(q,e1,n); 
			 } 
			 e2.no=count++;
			 e2.i=e.i+1;//建立右孩子结点 
			 e2.w=e.w;
			 copyx(e.x,e2.x,e.i);
			 e2.x[e2.i]=0;
			 bound(w,W,n,e2);//求右孩子结点的上界 
			 if(e2.ub>maxw)//若右孩子结点可行,则进队,否则被剪枝 
			 	enQueue(q,e2,n);
		}
 } 
 void dispasolution(int n)//输出最优解 
 {
 	int i;
 	printf("采用分支限界法求解装载问题:\n");
	 printf("共装入%d个集装箱\n",maxx[0]);
	 printf("X=[");
	 for(i=1;i<=n;i++)
	 	printf("%2d",maxx[i]);
	printf("]\n装载总重量为%d\n",maxw); 
 }
 int main()//主函数 
 {
 	int n=5,W=10;
 	int w[]={0,5,2,6,4,3};//各个集装箱的重量 
 	Loading(w,W,n);//调用分支限界法求装载问题 
 	dispasolution(n);//输出最优解 
 	printf("搜索的结点个数为%d\n",count);
 }

2.基于C语言的银行家算法

实验题目:银行家算法

一、 实验目的
利用银行家算法避免死锁,银行家算法原本是为银行系统设计的,用来保证在发放现金贷款的时候,不会发生不能满足客户需要的情况,在OS中常用银行家算法来避免死锁。
二、 设备与环境

  1. 设备:PC机
  2. 环境:C语言编程环境
    三、 实验内容
    为实现银行家算法,每一个进程在进入系统的时候,他必须申明在运行的过程中,可能需要每种资源类型的最大单元数目,其数目不应超过系统所拥有的资源总量。
    四、 实验结果及分析
  3. 实验设计说明
    为了实现银行家算法,在系统中可以设置下面六个数据结构,分别用力啊描述系统中的
    (1) Allocation可以存放各个进程以及资源已有的资源数
    (2) Max各个进程和各类资源的总需求量
    (3) maxres用来存放系统为各类资源提供的最大限度
    (4) work表示各类资源已有的资源总量。Work[j] += Allocation[i][j];
    (5) need表示还需要的各类资源的数量。Need[i] = maxres[i] - Work[i];
    (6) running用来设置标志位
  4. 实验代码
    主函数:
void bank()
{
	while (count != 0) //只有存在进程progress,count!=0就成立 
	{
		safe = 0;//设置标志位 
		for (i = 0; i < progress; i++) 
		{
		    if (running[i]) //存在进程progress,running[i]=1,则if条件成立 
			{
		        mark = 1;//标志位 
		        for (j = 0; j < variety; j++) 
				{
		            if (Max[i][j] - Allocation[i][j] > Need[j]) 
					{//用于判断 需要的资源数是否大于可提供的资源 
		                mark = 0;//满足情况,置0 
		                break;
		            }
		        }
		        if (mark) 
				{
		            printf("\n进程%d安全\n", i);//进程从0开始,(i = 0; i < progress; i++) 
		            running[i] = 0;
		            count--;//控制while(count != 0 ),当count减到0后,跳出while循环 
		            safe = 1;
		
		            for (j = 0; j < variety; j++) 
					{
		                Need[j] += Allocation[i][j];//已有的资源+释放的资源 
		            }
		
		            break;
		        }
		    }
		}
		if (!safe)//经过上述作用,safe值变为1,取反后if条件不成立 
		{//如果经过一系列判断后,进程都不满足安全状态 
		    printf("\n进程陷入了不安全状态\n");
		    break;
		}
		else 
		{
		    printf("\n进程是安全的");
		    printf("\n各类资源的资源总量 :");
		
		    for (i = 0; i < variety; i++) 
			{
		        printf("\t%d", Need[i]);//输出资源总量 
		    }
		
		    printf("\n");
		}
    }	
 }
  1. 实验结果
    请输入进程数目:5

请输入资源种类数目: 3

请输入系统为各类资源提供的最大限度 :10 5 7

请输入各个进程和各类资源已有库存 :
0 1 0
2 0 0
3 0 2
2 1 1
0 0 2

请输入各个进程和各类资源的总需求量 :
7 5 3
3 2 2
9 0 2
2 2 2
4 3 3

系统为各类资源提供的最大限度 : 10 5 7
各个进程和各类资源已有库存 :
0 1 0
2 0 0
3 0 2
2 1 1
0 0 2

各个进程和各类资源的总需求量:
7 5 3
3 2 2
9 0 2
2 2 2
4 3 3

目前各类资源已有的资源总量 : 7 2 5
各类资源仍需的资源总量 : 3 3 2

进程1安全

进程是安全的
各类资源的资源总量 : 5 3 2

进程3安全

进程是安全的
各类资源的资源总量 : 7 4 3

进程0安全

进程是安全的
各类资源的资源总量 : 7 5 3

进程2安全

进程是安全的
各类资源的资源总量 : 10 5 5

进程4安全

进程是安全的
各类资源的资源总量 : 10 5 7
4. 实验结果分析
通过键盘输入进程的数目、资源种类数目、各类资源提供的最大限度、个进程和各类资源已有库存、个进程和各类资源的总需求量。然后通过bank()函数来计算各类资源仍需的资源总量,以及判断当前进程是否安全并输出当前各类资源的总量。
五、 实验心得
通过学习和设计银行家算法,了解银行家算法避免死锁的处理原理。死锁问题的出现容易导致进程进入不安全状态,银行家算法的使用,当进程请求一组资源的时候,系统必须确认是否具有足够的资源,以及给他分配资源后,自身进程是否 会陷入不安全状态。

  • 3
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

DATA数据猿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值