常见算法,信号量总结

算法总结

考研

​ 1.已知2个有序表,A[0,…n-1],B[0,…m-1]尝试写一个算法将他们归并为有序表C[0,…m+n-1]

typedef struct{
    ElementType data[Maxsize];
    int length
}Sqlist

bool Merge(Sqlist A,Sqlist B,Sqlist &C){
   if(A.length+B.length>C.length)
    	return false;
   int i =0,j=0,k=0;
   while(i<A.length&&j<B.length){
   if(A.data[i]<B.data[j]){
   	C.data[k++]=A.data[i++]
    }else {
    C.data[k++]=B.data[j++]
    }
   }
   while(i<A.length)
   	C.data[k++]=A.data[i++];
   while(j<B.length)
   	C.data[k++]=B.data[j++];
   C.length=k;
   return true;
}

2.从顺序标中删除具有最小元素的(假设唯一)并由函数删除被删除的元素的值,空出的位置有最后一个元素填补,若顺序表为空则显示错误信息并推出

int Del_MIN(Sqlist &L){
    if(l.length==0){
        printf("空表")
    }
    int min =0 ,locate=0;
    min=L.data[0];
    for(int i=1;i<L.length;i++){
        if(min>L.data[i]){
            min=L.data[i];
            locate=i;
        }
    }
    L.data[locate]=L.data[L.length-1];
    return min;
}

3.将顺序表L的所有元素逆置,要求算法的空间复杂度为O(1)

void Reverse(Sqlist &L){
    int temp;
    for (int i=0;i<L.length/2;i++){
        temp=L.data[i];
     	L.data[i]=L.data[L.length-i-1];
        L.data[L.length-i-1]=temp;
    }
}

排序

1.插入排序

void insert(int A[],int n){
    int i,j;
    for(i=2;i<=n;i++){
        if(A[i]<A[i-1]){
            A[0]=A[i]
            for(j=i-1;A[0]<A[j];--j){
                    A[j+1]=A[j];
                }
            A[j+1]=A[0];
        }
    }
}

2.折半插入排序

void InsertSort(int A[],int n){
    int i,j,low,high,mid;
    for(i=2;i<=n;i++){
        if(A[i]<A[i-1]){
            low=1,high=i-1;
            while(low<=high){
                mid=(low+high)/2;
                if(A[mid]>A[0]){
                    high=mid-1;
                }else{
                    low=mid+1;
                }
            }
           for(j=i-1;j>=high+1;--j)
               A[j+1]=A[j]
            A[high+1]=A[0]   
        }
    }
}

希尔排序

public int[] shellSort(int A[],int n){
    int dk,i,j;
    for(dk=n/2;dk>=1;dk=dk/2){
        for(i=dk+1;i<=n;i++){
            if(A[i]<A[i-dk]){
                A[0]=A[i];
                for(j=i-dk;j>0&&A[j]>A[0];j=j-dk)
                    A[j+dk]=A[j];
                A[j+dk]=A[0];
            }
        }
    }
    return A;
}

冒泡排序

void BubbleSort(int A[],int n){
    for(i=0;i<n-1;i++){
        flag=false;
        for(j=n-1;j>i;j--){
            if(A[j-1]>A[j]){
                int temp=A[j-1];
                A[j-1]=A[j];
                A[j]=temp;
                flag=true;
            }
            if(flag==false)
                return;
        }
    }
}

快速排序

void QuickSort(int A[],int low,int high){
    if(low<high){
        int pivotpos=Partition(A,low,high);
        QuickSort(A,low,pivotpos-1);
        QuickSort(A,pivotpos+1,high);
    }
}
   public int Partition(int A[],int low,int high){
       int pivot=A[low];
       while (low<high){
           while (low <high && A[pivot]<A[high])
               high--;
           while (low<high && A[pivot]>A[low])
               low++;
       }
        A[low]=pivot;    
        return low;
    }

选择排序

void SelectSort(int A[],int n){
    for(int i=0;i<n-1;i++){
        min=i;
        for(int j=i+1;j<n;j++){
            if(A[j]<A[min]) 
          		min=j;
        }
        if(min!=i){
            int temp=A[min];
            A[min]=A[i];
            A[i]=temp;
        }
    }
}

堆排序


public void HeapSort(int A[],int len){
    BuildMaxHeap(A,len);
    for(int i=len;i>1;i--){
        int temp=A[1];
        A[1]=A[i];
        A[i]=temp;
        HeadAdjust(A,1,i-1);
    }
}

public void BuildMaxHeap(int A[],int len){
    for(int i=len/2;i>0;i--){
        HeadAdjust(A,i,len);
    }
}

public void HeadAdjust(int A[],int k,int len){
    //函数headAdjust将元素k为根的字数进行调整
    A[0]=A[k];
    for(int i=2*k;i<len;i*=2){
        if(i<len && A[i]<A[i+1]){
            i++;
        }
        if(A[0]>=A[i]) break;
        else {
            A[k]=A[i];
            k=i;
        }
    }
    A[k]=A[0];
}

归并排序

void Merge(int A[],int low,int mid,int high){
	int B[]=new int[A.length];
   	for(int k=low ;k<=high;k++)
        B[k]=A[k]
    for(int i=low,j=mid+1,k=i;i<mid&&j<high;k++){
        if(B[j]>=A[i]){
            A[k]=B[j++]//将较小的值复制到A中
        }else{
            A[k]=B[i++];
        }
    }
    while(i<=mid) A[k++]=B[i++];
    while(j<=high) A[k++]=B[j++];
}

void MergeSort(int A[],int low,int high){
    if(low<high){
        int low=(low+high)/2;
        MergeSort(A,low,mid);
        MergeSort(A,mid+1,high);
        Merge(A,low,mid,high)
    }
}

信号量

生产者消费者

semaphore mutex=1; 	//临界区互斥信号量
semaphore empty=n; 	//空闲缓存区
semaphore full=0;	//缓冲区初始化为空
producer(){
    while(1){
        P(empty);
       	P(mutex);
        add next to buffer;
        V(mutex);
        V(full);
    }
}
consumer(){
    while(1){
        P(full);
        P(mutex);
        remove an item from buffer;
        V(mutex);
        V(empty);
    }
}

爸妈儿女问题

问题描述:桌子上有一个盘子,每次只能向其中放入一个水果。爸爸专向盘子中放苹果,妈妈转向盘子中放橘子,儿子专门等着盘子里面中的橘子,女儿专门吃盘子里面的苹果,只有盘子为空时,爸爸或者妈妈才可以向盘子中放入一个水果,仅当盘子中有自己需要的水果时,儿子或者女儿可以从盘中取出。

问题分析:爸爸和妈妈时互斥关系。爸爸和女儿时同步,妈妈和儿子时同步,而且这两对关系必须练起来。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-utlTBwWX-1618061161406)(img/爸妈女儿.png)]

semaphore plate=1;//互斥信号量,代表盘子
semaphore apple=0,orange=0;//同步信号量
dad(){
    while(1){
        P(plate);
        put the apple on the plate;
        V(apple);
    }
}
mom(){
    while(1){
        P(plate);
        put the orange on the plate;
        V(apple);
    }
}
son(){
    while(1){
        P(orange);
        take an orange from the plate;
        V(plate);
    }
}
daughter(){
    while(1){
        P(apple);
        take apple from the plate;
        V(plate);
    }
}

读者-写者问题

问题描述:有读者和写着两组并发进程,共享一个文件,当两个或者以上的读进程同时访问共享数据时不会产生副作用,但是若某个写进程或者其他进程(读进程或者写进程)同时访问两个共享数据时则可能导致数据不一致错误。因此要求:1.允许多个读者同时对文件执行读操作。2.只允许一个写者往文件中写信息。3.任意写着在完成写操作完成之前不允许其他读者或者写着工作。4.写着执行写操作前,应让已有读者和写着全部退出。

问题分析:读者和写着是互斥的,写着和写着也是互斥的,而读者和读者不存在互斥问题

int count=0; //代表读者数量
semaphore mutex=1;	//互斥信号量,保护更新count变量时的互斥
semaphore rw=1;	//互斥信号量,读者和写着互斥
writer(){
    while(1){
        P(rw);
        writing;
        V(rw);
    }
}
reader(){
    while(1){
        P(mutex);
        if(count==0){
            P(rw);
        }
        count++;
        V(mutex);
        reading;
        P(mutex);
        count--;
        if(count==0){
            V(rw);
        }
        V(mutex);
    }
}

哲学家进餐问题

semaphore chopstick[5]={1,1,1,1,1};//初始化信号量
semaphore mutex=1;//设置去筷子的信号量;
pi(){
    do(){
        P(mutex);
        P(chopstick[i]);
        P(chopstick[(i+1)%5]);//一共有5根筷子
        V(mutex)
        eat;
        V(chopstick[i]);
       	V(chopstick[(i+1)%5]);
    }while(1)
}

吸烟者问题

问题描述:假设一个系统有三个抽烟者进程和一个供应者进程。每个抽烟者不停的卷烟并抽调,但是卷起并抽调一支烟,抽烟者需要三种材料:烟草,纸和胶水。三个抽烟者中,第一个拥有烟草,第二个拥有纸,第三个拥有胶水。供应者进程无限的提供三种材料,供应者每次将两种材料放在桌子上,拥有剩下那种材料的抽烟者卷一根烟并抽调它,并给供应者一个信号告诉已完成,此时供应者就会把剩下另外两种材料放到桌子上,入此重复(让三个抽烟者轮流的抽烟)

问题分析:供应者与三个抽烟者分别时同步关系,由于供应者无法同时满足两个及其以上的抽烟者,三个抽烟者对抽烟这个动作时互斥的关系;

int random;//存储随机数
semaphore offer1=0;//定义信号量对应烟草和纸的组合
semaphore offer2=0;//定义信号量对应烟草和胶水的组合
semaphore offer3=0;//定义信号量对应胶水和纸的组合
semaphore finish=0;//代表抽烟是否完成
process p1(){//供应者
	while(1){
	random=任意一个正数
	random=random%3;
	if(random==0){
		V(offer1);
	}else if(random==1){
		V(offer2);
	}else if(random==2){
		V(offer3);
	}
	任意两种材料方才桌子上;
	P(finish);
	}
}
process P2(){
	while(1){
	P(offer1)
	抽烟;
	V(finish)
	}
}
process P3(){
	while(1){
	P(offer2)
	抽烟;
	V(finish)
	}
}
process P3(){
	while(1){
	P(offer3)
	抽烟;
	V(finish)
	}
}

e finish=0;//代表抽烟是否完成
process p1(){//供应者
while(1){
random=任意一个正数
random=random%3;
if(random0){
V(offer1);
}else if(random
1){
V(offer2);
}else if(random==2){
V(offer3);
}
任意两种材料方才桌子上;
P(finish);
}
}
process P2(){
while(1){
P(offer1)
抽烟;
V(finish)
}
}
process P3(){
while(1){
P(offer2)
抽烟;
V(finish)
}
}
process P3(){
while(1){
P(offer3)
抽烟;
V(finish)
}
}


  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值