算法上机题目mergesort,priority queue,Quicksort,divide and conquer
1.Implement exercise 2.3-7.
2. Implement priority queue.
3. Implement Quicksort and answer the following questions. (1) How many comparisons will Quicksort do on a list of n elements that all have the same value? (2) What are the maximum and minimum number of comparisons will Quicksort do on a list of n elements, give an instance for maximum and minimum case respectively.
4. Give a divide and conquer algorithm for the following problem: you are given two sorted lists of size m and n, and are allowed unit time access to the ith element of each list. Give an O(lg m + lgn) time algorithm for computing the kth largest element in the union of the two lists. (For simplicity, you can assume that the elements of the two lists are distinct).
l 实验过程
1.先读懂题目,由于题目是英文的,所以读懂题目很重要。
2.根据题目回想自己课堂上所学的知识,进行初步思路构思。
3.在本子上写出伪代码,可以简练,自己懂就好。
4.检查伪代码,并上机运行,转换成实际C代码。
5.代码纠错和运行调试,并进行数据测试,数据测试尽可能全面。
l 具体代码
1.mergesort
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<malloc.h>
#define MAX 10000
void merge_sort(int a[],int p,int r); //定义函数
int main()
{
for(;;) //无限循环的函数,方便测试
{
int a[10],i;
int j=9;
int x;
srand((int)time(NULL)); //产生随机数
for(i=0;i<10;i++)
{
a[i]=rand()%100;
printf("%d\t",a[i]);
}
printf("请输入给定的和:\n");
scanf("%d",&x);
merge_sort(a,0,9);
i=0;
while(j>i)
{
if(a[i]+a[j]>x)
j--;
else if(a[i]+a[j]<x)
i++;
else
{
printf("a中存在两个数和等于x, 它们分别是%d\t%d\n",a[i],a[j]);
break;
}
}
if(i==j)
printf("a中不存在两个数和等于x\n");
}
system("pause");
return 0;
}
void merge(int a[],int p,int q,int r)
{
int n1,n2;
int i,j,k;
n1=q-p+1;
n2=r-q;
int* L=(int*)malloc(sizeof(int)*(n1+1));
int* R=(int*)malloc(sizeof(int)*(n2+1));
for(i=0;i<n1;i++)
L[i]=a[p+i];
for(j=0;j<n2;j++)
R[j]=a[q+j+1];
L[n1]=MAX;
R[n2]=MAX;
i=0;
j=0;
for(k=p;k<=r;k++)
{
if(L[i]<=R[j])
{
a[k]=L[i];
i++;
}
else
{
a[k]=R[j];
j++;
}
}
free(L);
free(R);
}
void merge_sort(int a[],int p,int r)
{
int q;
if(p<r)
{
q=(p+r)/2;
merge_sort(a,p,q);
merge_sort(a,q+1,r);
merge(a,p,q,r);
}
}
2.priority queue
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<malloc.h>
void build_max_heap(int a[]);
int heap_maximum(int a[]);
int heap_extract_max(int a[]);
void heap_increase_key(int a[],int i,int key);
void max_heap_insert(int a[],int key);
static int heapsize=0;
static int length=0;
int main()
{
printf("请输入数组的大小:");
scanf("%d",&heapsize);
int m;
int* a=(int *)malloc(sizeof(int)*heapsize);
int i;
srand((int)time(NULL));
for(i=0;i<heapsize;i++)
{
a[i]=rand()%100;
printf("%d\t",a[i]);
}
printf("\n");
build_max_heap(a);
for(i=0;i<heapsize;i++)
{
printf("%d\t",a[i]);
}
printf("\n");
printf("MAXIMUM(S):返回S中具有最大关键字的元素:");
printf("%d\n",heap_maximum(a));
m=heap_maximum(a);
printf("EXTRACT_MAX(S):返回S中具有最大关键字的元素并删除之:");
printf("%d\n",heap_extract_max(a));
printf("MAXIMUM(S):返回新的S中具有最大关键字的元素:");
printf("%d\n",heap_maximum(a));
heapsize++;
a[heapsize-1]=m;
build_max_heap(a);
heap_increase_key(a,1,100);
printf("INCREASE_KEY(S,1,100):将数组下标为1的元素改变为100后的数组:");
for(i=0;i<heapsize;i++)
{
printf("%d\t",a[i]);
}
printf("\n");
max_heap_insert(a,10);
printf("INSORT(S,10):插入元素10后的数组:");
for(i=0;i<heapsize;i++)
{
printf("%d\t",a[i]);
}
printf("\n");
free(a);
system("pause");
return 0;
}
int parent(int i)
{
return (i-1)/2;
}
int left(int i)
{
return 2*i+1;
}
int right(int i)
{
return 2*i+2;
}
void max_heapify(int a[],int i)
{
int l,r,largest;
l=left(i);
r=right(i);
if((l<=heapsize-1)&&a[l]>a[i])
largest=l;
else
largest=i;
if((r<=heapsize-1)&&a[r]>a[largest])
largest=r;
if(largest!=i)
{
int temp=a[i];
a[i]=a[largest];
a[largest]=temp;
max_heapify(a,largest);
}
}
//建立大顶堆过程
void build_max_heap(int a[])
{
length=heapsize;
int i;
for(i=(length-1)/2;i>=0;i--)
max_heapify(a,i);
}
int heap_maximum(int a[])
{
return a[0];
}
int heap_extract_max(int a[])
{
int max;
if(heapsize<1)
{
printf("heap underflow\n");
return -1;
}
else
{
max=a[0];
a[0]=a[heapsize-1];
heapsize=heapsize-1;
max_heapify(a,0);
return max;
}
}
void heap_increase_key(int a[],int i,int key)
{
if(key<a[i]||i>heapsize-1)
printf("new key is smaller than current key\n");
else
{
a[i]=key;
while(i>0&&a[parent(i)]<a[i])
{
int temp=a[i];
a[i]=a[parent(i)];
a[parent(i)]=temp;
i=parent(i);
}
}
}
void max_heap_insert(int a[],int key)
{
heapsize++;
realloc(a,sizeof(int)*heapsize);
a[heapsize-1]=-1;
heap_increase_key(a,heapsize-1,key);
}
3.Quicksort
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
int partition(int a[],int p,int r);
void quicksort(int a[],int p,int r);
void main()
{
int i,a[10];
srand((int)time(NULL));
for(i=0;i<10;i++)
{
a[i]=rand()%100;
printf("%d\t",a[i]);
}
quicksort(a,0,9);
for(i=0;i<10;i++)
{
printf("%d\t",a[i]);
}
}
void quicksort(int a[],int p,int r)
{
int q;
if(p<r)
{
q=partition(a,p,r);
quicksort(a,p,q-1);
quicksort(a,q+1,r);
}
}
int partition(int a[],int p,int r)
{
int x,i,j,temp;
x=a[r];
i=p-1;
for(j=p;j<r;j++)
{
if(a[j]<=x)
{
i++;
temp=a[i];
a[i]=a[j];
a[j]=temp;
}
}
temp=a[i+1];
a[i+1]=a[r];
a[r]=temp;
return i+1;
}
4.divide and conquer
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<malloc.h>
int partition(int a[],int p,int r);
void quicksort(int a[],int p,int r);
int findi(int a[],int i);
int FindTheKth(int a[],int b[],int aLeft, int aRight, int bLeft, int bRight, int k) ;
void main()
{
int n,m,i;
srand((int)time(NULL));
printf("请输入两个数组的大小:\n");
printf("n:");
scanf("%d",&n);
printf("m:");
scanf("%d",&m);
int* a=(int*)malloc(sizeof(int)*n);
int* b=(int*)malloc(sizeof(int)*m);
printf("a数组:\n");
for(i=0;i<n;i++)
{
a[i]=rand()%100;
printf("%d\t",a[i]);
}
printf("\nb数组:\n");
for(i=0;i<m;i++)
{
b[i]=rand()%100;
printf("%d\t",b[i]);
}
quicksort(a,0,n-1);
quicksort(b,0,m-1);
printf("\n排序后的a数组:\n");
for(i=0;i<n;i++)
{
printf("%d\t",a[i]);
}
printf("\n排序后的b数组:\n");
for(i=0;i<m;i++)
{
printf("%d\t",b[i]);
}
printf("\n");
printf("数组a的第4个元素:%d\n",findi(a,4));
printf("数组b的第4个元素:%d\n",findi(b,4));
printf("%d\n",FindTheKth(a,b,0, n-1, 0, m-1, 7));
free(a);
free(b);
}
void quicksort(int a[],int p,int r)
{
int q;
if(p<r)
{
q=partition(a,p,r);
quicksort(a,p,q-1);
quicksort(a,q+1,r);
}
}
int partition(int a[],int p,int r)
{
int x,i,j,temp;
x=a[r];
i=p-1;
for(j=p;j<r;j++)
{
if(a[j]<=x)
{
i++;
temp=a[i];
a[i]=a[j];
a[j]=temp;
}
}
temp=a[i+1];
a[i+1]=a[r];
a[r]=temp;
return i+1;
}
int findi(int a[],int i)
{
int size=0;
for(;;)
if(a[size]>=0&&a[size]<=100)
size++;
else
break;
if(i>size||i<1)
{
return -1;
}
else
return a[i-1];
}
int FindTheKth(int a[],int b[],int aLeft, int aRight, int bLeft, int bRight, int k)
{
int aMid = (aLeft + aRight) / 2, bMid = (bLeft + bRight) / 2;
if (aLeft > aRight) return b[bLeft+k-1];
if (bLeft > bRight) return a[aLeft+k-1];
if (a[aMid] <= b[bMid])
{
if (k <= (aMid - aLeft) + (bMid - bLeft) + 1)
{
return FindTheKth(a,b,aLeft, aRight, bLeft, bMid-1, k);
}
else
{
return FindTheKth(a,b,aMid+1, aRight, bLeft, bRight, k-(aMid-aLeft)-1);
}
}
else
{
if (k <= (aMid - aLeft) + (bMid - bLeft) + 1)
{
return FindTheKth(a,b,aLeft, aMid-1, bLeft, bRight, k);
}
else
{
return FindTheKth(a,b,aLeft, aRight, bMid+1, bRight, k-(bMid-bLeft)-1);
}
}
return -1;
}
l 实验结果
mergesort结果
通过实验我们知道:归并排序是一个典型的分治合并算法,对一个大小的记录序列排序,可以把记录划分成2个记录序列,如果这两个子序列还是不能直接排序,则一真划分,直到序列剩下2个素或者1个元素。分治完毕后再依次两两,直至合并成一个有序表。
如果问题规模为T(n),则分治过程中分成了两个子问题每个子问题的规模是1/2 * T(n/2)
合并排序的运行时间可以分解为:
分解:就是算出中间位置
解决:递归解决两个子问题,时间为1/2 * T(n/2)
合并:我们注意到,在一个含有n个元素的子数组上,Merge过程的运行时间为O(n),由于O(n)是线性关系,不妨设O(n)
= cn;每一层的总规模是cn,一共有logn + 1层,那么复杂度为cn*logn,所以得出O(nlogn)。
priority queue结果
优先队列最基本的功能就是出队时不是按照先进先出的规则,而是按照队列中优先级顺序出队。
1、一般存放实型类型,可比较大小
2、默认情况下底层以Vector实现
3、默认情况下是大顶堆,也就是大者优先级高,后面可以自定义优先级比较规则
堆分为大根堆和小根堆,是完全二叉树。大根堆的要求是每个节点的值都不大于其父节点的值,即A[PARENT[i]] >= A[i]。在数组的非降序排序中,需要使用的就是大根堆,因为根据大根堆的要求可知,最大的值一定在堆顶。
堆排序法利用二叉树最大堆实现对数字的排序。其排序的时间为O(nlgn)
divide and conquer结果及分析
原问题是规模为 n 的问题,在树的第一层,把问题分为规模为n/2的两个子问题,如果解决了这两个子问题,把它们合并就能得到原问题的解。现在来看其中的一个子问题,为了解决他们,又把它分为两个规模更小的问题n/4。解决了规模为n/4的问题,合并之就能得到规模 n/2 的问题的解。按照上面的思想,把原问题递归的分解为规模小的问题,然后合并之就能得到原问题的解。
Quicksort结果及分析
本例产生随机数,并将其排序。
快速排序采用的“大事化小,小事化了”的思想,用递归的方法,将原问题分解成若干规模较小但与原问题相似的子问题进行求解。快速算法的平均时间复杂度为O(nlogn) ,平均而言,快速排序是基于关键字比较的内部排序算法中速度最快者;但是由于快速排序采用的是递归的方法,因此当序列的长度比较大时,对系统栈占用会比较多。快速算法尤其适用于随机序列的排序。
l 实验总结
这次实验总的来说还是蛮顺利的,由于课本上的基础知识提前都看了,而且关于实验的内容提前在课下做了很多,所以还是蛮轻松的,不过,有一点就是,如何将所学习的知识应用于真正的实践中,比如说这次的实验,将伪代码转换称自己的思想是要经消化的,再通过自己的语言表达出来,或者用C,或者C++,或者Java都可以。关于上机,自己也更体会到了算法这门课的奥妙,通过上机,我们才真正怎么将复杂的算法简化,然后减轻计算机的负担,优化程序的执行时间,这在我们以后的编程之中是很有用的。
还有就是课本上的伪代码便于理解,但是如果直接转换成可以运行的代码则又会有一些问题,比如有关数组的下标问题,有关部分循环结构的问题。
总的来说,受益匪浅,辅导老师也解决了我的几个问题。谢谢老师。
算法上机题目mergesort,priority queue,Quicksort,divide and conquer的更多相关文章
- 算法学习笔记之——priority queue、heapsort、symbol table、binary search trees
Priority Queue 类似一个Queue,但是按照priority的大小顺序来出队 一般存在两种方式来实施 排序法(ordered),在元素入队时即进行排序,这样插入操作为O(N),但出队为O ...
- 算法与数据结构基础 - 堆(Heap)和优先级队列(Priority queue)
堆基础 堆(Heap)是具有这样性质的数据结构:1/完全二叉树 2/所有节点的值大于等于(或小于等于)子节点的值: 图片来源:这里 堆可以用数组存储,插入.删除会触发节点shift_down.shif ...
- find-median-from-data-stream & multiset priority queue 堆
https://leetcode.com/problems/find-median-from-data-stream/ 这道题目实在是不错,所以单独拎出来. https://discuss.leetc ...
- 《Algorithms 4th Edition》读书笔记——2.4 优先队列(priority queue)-Ⅴ
命题Q.对于一个含有N个元素的基于堆叠优先队列,插入元素操作只需要不超过(lgN + 1)次比较,删除最大元素的操作需要不超过2lgN次比较. 证明.由命题P可知,两种操作都需要在根节点和堆底之间移动 ...
- 《Algorithms 4th Edition》读书笔记——2.4 优先队列(priority queue)-Ⅳ
2.4.4 堆的算法 我们用长度为 N + 1的私有数组pq[]来表示一个大小为N的堆,我们不会使用pq[0],堆元素放在pq[1]至pq[N]中.在排序算法中,我们只能通过私有辅助函数less()和 ...
- 《Algorithms 4th Edition》读书笔记——2.4 优先队列(priority queue)-Ⅰ
许多应用程序都需要处理有序的元素,但不一定要求他们全部有序,或者是不一定要以此就将他们排序.很多情况下我们会手机一些元素,处理当前键值最大的元素,然后再收集更多的元素,再处理当前键值最大的元素.如此这 ...
- 什么是优先级队列(priority queue)?
有时候我们需要在某个元素集合中找到最小值和最大值 .优先级队列抽象数据(Priority Queue ADT)模型是我们能够使用的方法之一,这是一种支持插入和删除最小值(DeleteMin)或者最大值 ...
- STL之heap与优先级队列Priority Queue详解
一.heap heap并不属于STL容器组件,它分为 max heap 和min heap,在缺省情况下,max-heap是优先队列(priority queue)的底层实现机制.而这个实现机制中的m ...
- Priority Queue
优先队列 集合性质的数据类型离不开插入删除这两操作,主要区别就在于删除的时候删哪个,像栈删最晚插入的,队列删最早插入的,随机队列就随便删,而优先队列删除当前集合里最大(或最小)的元素.优先队列有很多应 ...
随机推荐
- TOMACT 各个版本集合
http://archive.apache.org/dist/tomcat/ 再点击 bin 目录,找到想下载的即可
- NLP预训练模型-百度ERNIE2.0的效果到底有多好【附用户点评】
ERNIE是百度自研的持续学习语义理解框架,该框架支持增量引入词汇(lexical).语法 (syntactic) .语义(semantic)等3个层次的自定义预训练任务,能够全面捕捉训练语料中的词法 ...
- 关于JQUery.parseJSON()函数的知识札记
JSON数据也许大家都很陌生,而对我来讲属于半成品,由于项目问题,做web虽然用的是JSON数据格式传输,但是关于解析这一块还真不知道该注意什么,更不知道它是如何解析的,由于最近要把串口通信协议与此一 ...
- USDT跑分系统开发
USDT跑分系统开发找[林生:178-7666-2415微/电],USDT跑分系统开发,USDT跑分系统解决方案,USDT跑分系统定制,小程序开发.APP.公众号等软件开发. 数字资产结算通道的特点: ...
- MinIO 搭建
MinIO 搭建 MinIO 是一个基于 Apache License v2.0 开源协议的对象存储服务.它兼容亚马逊 S3 云存储服务接口,非常适合于存储大容量非结构化的数据,例如图片.视频.日志文 ...
- st表复习笔记
st表,一种高效的区间最值查询(RMQ)算法.本质其实是一个动态规划. 其实吧,对于看过线性dp的人来说应该不难理解,只是处理有些麻烦.但是本土狗因为-1的问题居然改了许久... 用两个2^i的区间把 ...
- UiPath之基础知识(一)
各位小伙伴,大家好.在10月份小U的微信订阅号做了一个投票,主题是UiPath目前已经掌握的程度. 从投票的结果来看,有一半以上的人还是刚刚起步,为了帮助刚刚起步的小伙伴,准备陆续发布一些基础性的内容 ...
- jquey写进度条问题
jquey写进度条问题可以直接按照 总时间和进度条宽度之比来做 不管他是不是y=kx 反正时间到0 进度肯定是0了
- php nginx反向代理获取真实ip的教程
php nginx反向代理获取真实ip的教程 <pre> location /getip { proxy_pass http://newmiracle.cn/ip.php; } proxy ...
- mongodb定时删除数据(索引删除)
一 简介:本文介绍创建自动删除数据的TTL索引 二 目的 定时删除数据三 创建方法 db.collection.createIndex(keys, options) options: ex ...