优先队列 - 1
优先队列升序写法

优先队列升序写法首先,优先队列是一种特殊的队列,其中每个元素都具有一个与之关联的优先级。
当出队时,优先级高的元素先出队,而优先级低的元素则稍后出队。
在升序优先队列中,优先级较高的元素是值越小的元素。
下面,我们将会用中文来讲述升序优先队列的实现方式。
首先,让我们来看看优先队列升序的实现思路:1. 用数组或链表等数据结构来存储元素。
2. 当元素入队时,按照优先级顺序插入到合适的位置。
3. 当元素出队时,取出优先级最高的元素,并删除它。
现在,让我们来详细看看优先队列升序的具体实现方法。
1. 数组实现在使用数组来实现优先队列时,我们需要在数组中存储元素及其优先级。
当元素入队时,我们需要遍历数组并找到第一个比当前元素优先级高的位置,然后将当前元素插入到该位置。
当元素出队时,我们只需要删除数组的最后一个元素即可。
2. 链表实现在使用链表来实现优先队列时,我们需要在链表中存储元素及其优先级。
当元素入队时,我们需要遍历链表并找到第一个比当前元素优先级高的位置,然后将当前元素插入到该位置。
当元素出队时,我们只需要删除链表的第一个元素即可。
3. 堆实现在使用堆来实现优先队列时,我们需要在堆中存储元素及其优先级。
当元素入队时,我们需要插入到堆的末尾,然后进行上浮操作,将元素插入到合适的位置。
当元素出队时,我们需要删除堆顶元素,然后进行下沉操作,将堆中的其他元素重新排列成堆的形式。
无论使用哪种实现方式,都需要注意以下几点:1. 在插入操作时,要确保元素始终按照优先级顺序排列。
2. 在删除操作时,要确保始终取出优先级最高的元素。
3. 在处理异常情况时,要确保代码的健壮性。
总之,在实现优先队列升序时,我们需要注意以下几点:1. 根据具体应用场景选择合适的实现方式。
2. 在插入和删除操作时,要确保始终遵循优先级规则。
3. 考虑到空间和时间复杂度,合理调整数据结构的大小。
以上是升序优先队列的实现方法,希望能对读者有所帮助。
C语言数据结构优先队列实现

一.优先队列的定义优先队列是0个或多个元素的集合,每个元素都有一个优先权或值,对优先队列执行的操作有1) 查找;2) 插入一个新元素;3) 删除。
本程序的实现二.实现本优先队列的初始化,查找,插入,删除操作,并且控制其查找,插入,删除操作的算法时间复杂度为O(logn)。
采用堆正好能实现该时间复杂度。
相关代码实现如下:#include<stdio.h>#include<stdlib.h>#include<malloc.h>#define LIST_INIT_SIZE 100#define LISTINCREMENT 10#define ElemType int#define Status int#define ERROR -1#define OK 1typedef struct Type{ElemType Elem; //元素值ElemType weigth;//元素权值}Type;typedef struct{Type *elem;int length;int listsize;}prqueue;Status INitqueue(prqueue &L)// 创建空顺序表,大小为LIST_INIT_SIZE{L.elem = (Type *)malloc(LIST_INIT_SIZE*sizeof(Type));if(!L.elem) return ERROR;L.length=0;L.listsize=LIST_INIT_SIZE;return OK;}Status Insertqueue(prqueue &L,ElemType e,ElemType f){Type *newbase;int i=L.length+1;if(i<1) return ERROR;if(L.length>=L.listsize) //当前储存空间已满,增加分配{newbase=(Type*)realloc(L.elem,(L.listsize+LISTINCREMENT)*sizeof(Type));if(!newbase) return ERROR; //存储分配失败L.elem=newbase; //新基址L.listsize+=LISTINCREMENT; //增加存储容量}L.elem[i].Elem=e;L.elem[i].weigth=f; //插入e,fL.length++;//表长加1return OK;}void SHeapAdjust(prqueue &H,int s,int m) //建小顶堆{int j;int rc1;rc1=H.elem[s].Elem;ElemType rc2 = H.elem[s].weigth;for(j=2*s;j<=m;j*=2) //沿weigth较小的孩子节点向下筛选{if(j<m&&H.elem[j].weigth>H.elem[j+1].weigth) j++;//j为weigth 较小的记录下标if(rc2<=H.elem[j].weigth) break; //rc应插在位置s上H.elem[s].weigth=H.elem[j].weigth;H.elem[s].Elem=H.elem[j].Elem;s=j;}H.elem[s].weigth=rc2;H.elem[s].Elem=rc1;}void SHeapSort(prqueue &H){Type t;int i;for(i=H.length/2;i>0;i--)//建成小顶堆SHeapAdjust(H,i,H.length);t=H.elem[1];H.elem[1]=H.elem[H.length];H.elem[H.length]=t; //将堆顶和最后一个元素交换}ElemType SSearchElem(prqueue &L)SHeapSort(L);return L.elem[L.length].Elem;}ElemType SSearchWeigth(prqueue &L){SHeapSort(L);return L.elem[L.length].weigth;}Status SDelete(prqueue &L){SHeapSort(L);L.length--;//删除最后一个元素,也就是权值最小的元素if(L.length>=0) return OK;else return ERROR;}void HeapAdjust(prqueue &H,int s,int m) //建大顶堆int j;int rc1;rc1=H.elem[s].Elem;ElemType rc2 = H.elem[s].weigth;for(j=2*s;j<=m;j*=2) //沿weigth较大的孩子节点向下筛选{if(j<m&&H.elem[j].weigth<H.elem[j+1].weigth) j++;//j为weigth 较大的记录下标if(rc2>=H.elem[j].weigth) break; //rc应插在位置s上H.elem[s].weigth=H.elem[j].weigth;H.elem[s].Elem=H.elem[j].Elem;s=j;}H.elem[s].weigth=rc2;H.elem[s].Elem=rc1;}void HeapSort(prqueue &H){Type t;int i;for(i=H.length/2;i>0;i--)//建成大顶堆HeapAdjust(H,i,H.length);t=H.elem[1];H.elem[1]=H.elem[H.length];H.elem[H.length]=t; //将堆顶和最后一个元素交换}ElemType SearchElem(prqueue &L){HeapSort(L);return L.elem[L.length].Elem;}ElemType SearchWeigth(prqueue &L){HeapSort(L);return L.elem[L.length].weigth;}Status Delete(prqueue &L){HeapSort(L);L.length--;//删除最后一个元素,也就是权值最大的元素if(L.length>=0) return OK;else return ERROR;}int Load_Sq(prqueue &L){int i;if(L.length==0)printf("The List is empty!");else{HeapSort(L);printf("还剩下的元素是:");for(i=L.length;i>0;i--)printf("% d",L.elem[i].Elem);printf("\n");printf("其权值是");for(i=L.length;i>0;i--)printf("% d",L.elem[i].weigth);}printf("\n");return OK;}int SLoad_Sq(prqueue &L){int i;SHeapSort(L);if(L.length==0)printf("The List is empty!");else{printf("还剩下的元素是:");for(i=L.length;i>0;i--)printf("% d",L.elem[i].Elem);printf("\n");printf("其权值是");for(i=L.length;i>0;i--)printf("% d",L.elem[i].weigth);}printf("\n");return OK;}int main(){prqueue T;int a;int b;int c;int e,i;ElemType x;if(INitqueue(T)){printf("欢迎\n");}while(1){printf("最大优先队列操作\n1:插入元素及其权值\n2:删除最大权值元素\n3:查找最大权值元素\n&&&&&&&&&&&&&&&&&&&&&&&&&&\n最小优先队列操作\n5:插入元素及其权值\n6:删除最小权值元素\n7:查找最小权值元素\n0:返回主菜单\n请选择(0-7):\n");scanf("%d",&a);switch(a){case 1: printf("请输入待插入元素个数:");scanf("%d",&b);for(c=0;c<b;c++){printf("请输入第%d个待插入元素:",c+1);scanf("%d",&i); printf("请输入第%d个待插入元素的权值:",c+1);scanf("%d",&x);if(!Insertqueue(T,i,x))printf("Insert Error!\n");elseprintf("第%d个元素%d 成功插入!其权值为%d \n",c+1,i,x);printf("请按回车进行下一个操作\n");getchar();getchar();system("cls");}break;case 2:if(!Delete(T))printf("Delete Error!\n");elseprintf("权值最大元素成功删除!\n");Load_Sq(T);printf("请按回车进行下一个操作\n");getchar();getchar();system("cls");break;case 3: SearchWeigth(T);SearchElem(T);printf("权值最大元素是%d 并且权值是%d \n",T.elem[T.length].Elem,T.elem[T.length].weigth);printf("请按回车进行下一个操作\n");getchar();getchar();system("cls");break;case 5: printf("请输入待插入元素:");scanf("%d",&i);printf("请输入待插入元素的权值:");scanf("%d",&x);if(!Insertqueue(T,i,x))printf("Insert Error!\n");elseprintf("元素%d 成功插入!其权值为%d \n",i,x);system("cls");break;case 6:if(!SDelete(T))printf("Delete Error!\n");elseprintf("权值最小元素成功删除!\n");SLoad_Sq(T);printf("请按回车进行下一个操作\n");getchar();getchar();system("cls");break;case 7: SSearchWeigth(T);SSearchElem(T);printf("权值最小元素是%d 并且权值是%d \n",T.elem[T.length].Elem,T.elem[T.length].weigth);printf("请按回车进行下一个操作\n");getchar();getchar();system("cls");break;case 0: return 1;}}}。
优先队列式分支限界法求解0-1背包问题

算法分析与设计实验报告第7 次实验}1、测试自己输入的小规模数据2、测试随机生成1003、随机生成1000数据4、随机生成1000数据附录:完整代码#include <iostream>#include<time.h>#include<algorithm>#include<fstream>using namespace std;ifstream in("input.txt");ofstream out("output.txt");typedef int Typew;typedef int Typep;//物品类class Object{friend Typep Knapsack(Typew *, Typep *, Typew, int, int *); public:int operator <= (Object a) const{return (d >= a.d);}private:int ID; //物品编号float d; //单位重量价值};//树结点类class bbnode{friend class Knap;friend Typep Knapsack(Typew *, Typep *, Typew, int, int *); private:bbnode *parent; //指向父节点的指针int LChild;};//堆结点类class HeapNode{friend class Knap;friend class MaxHeap;public:operator Typep()const{return uprofit;};private:Typep uprofit, //结点的价值上界profit; //结点所相应的价值Typew weight; //结点所相应的重量int level; //活结点在子集树中所处的层序号bbnode *elemPtr; //指向该活结点在子集树中相应结点的指针};//最大堆类class MaxHeap{public:MaxHeap(int maxElem){HeapElem = new HeapNode* [maxElem+1]; //下标为0的保留capacity = maxElem;size = 0;}void InsertMax(HeapNode *newNode);HeapNode DeleteMax(HeapNode* &N);private:int capacity;int size;HeapNode **HeapElem;};//0-1背包问题的主类class Knap{friend Typep Knapsack(Typew *, Typep *, Typew, int, int *); public:Typep MaxKnapsack();private:MaxHeap *H;Typep Bound(int i);void AddLiveNode(Typep up, Typep cp, Typew cw, int ch, int level);bbnode *E; //指向扩展结点的指针Typew c; //背包容量int n; //物品总数Typew *w; //物品重量数组(以单位重量价值降序)Typep *p; //物品价值数组(以单位重量价值降序)Typew cw; //当前装包重量Typep cp; //当前装包价值int *bestx; //最优解};void MaxHeap::InsertMax(HeapNode *newNode){int i = 1;for (i = ++size; i/2 > 0 && HeapElem[i/2]->uprofit < newNode->uprofit; i /= 2){HeapElem[i] = HeapElem[i/2];}HeapElem[i] = newNode;}HeapNode MaxHeap::DeleteMax(HeapNode *&N){if(size >0 ){N = HeapElem[1];int i = 1;while(i < size){if(((i*2 +1) <= size) && HeapElem[i*2]->uprofit > HeapElem[i*2 +1]->uprofit){HeapElem[i] = HeapElem[i*2];i = i*2;}else{if(i*2 <= size){HeapElem[i] = HeapElem[i*2];i = i*2;}elsebreak;}}if(i < size)HeapElem[i] = HeapElem[size];}size--;return *N;}Typep Knap::MaxKnapsack(){H = new MaxHeap(10000);bestx = new int [n+1];int i = 1;E = 0;cw = 0;cp = 0;Typep bestp = 0;Typep up = Bound(1);while (i != n+1){Typew wt = cw + w[i];if(wt <= c) {if(cp + p[i] > bestp)bestp = cp + p[i];AddLiveNode(up, cp + p[i], cw + w[i], 1, i);}up = Bound(i + 1);if(up >= bestp)AddLiveNode(up, cp, cw, 0, i);HeapNode* N;H->DeleteMax(N);E = N->elemPtr;cw = N->weight;cp = N->profit;up = N->uprofit;i = N->level + 1;}for (int i = n; i > 0; i--){bestx[i] = E->LChild;E = E->parent;}return cp;}Typep Knap::Bound(int i){Typew cleft = c - cw;Typep b = cp;while (i<=n && w[i] <= cleft){cleft -= w[i];b += p[i];i++;}if(i<=n) b += p[i]/w[i] * cleft;return b;}void Knap::AddLiveNode(Typep up, Typep cp, Typew cw, int ch, int level) {bbnode *b=new bbnode;b->parent=E;b->LChild=ch;HeapNode *N = new HeapNode;N->uprofit=up;N->profit=cp;N->weight=cw;N->level=level;N->elemPtr=b;H->InsertMax(N);}//Knapsack返回最大价值,最优值保存在bestxTypep Knapsack(Typew *w, Typep *p, Typew c, int n, int *bestx){Typew W = 0;Typep P = 0;Object *Q = new Object[n];for(int i =1; i<=n; i++){Q[i-1].ID = i;Q[i-1].d = 1.0*p[i]/w[i];P += p[i];W += w[i];}if (W <= c){for(int i =1; i<=n; i++){bestx[i] = p[i];}return P;}for(int i = 1; i<n; i++)for(int j = 1; j<= n-i; j++){if(Q[j-1].d < Q[j].d){Object temp = Q[j-1];Q[j-1] = Q[j];Q[j] = temp;}}Knap K;K.p = new Typep [n+1];K.w = new Typew [n+1];for(int i = 1; i<=n; i++){K.p[i] = p[Q[i-1].ID];K.w[i] = w[Q[i-1].ID];}K.cp = 0;K.cw = 0;K.c = c;K.n = n;Typep bestp = K.MaxKnapsack();for(int i = 1; i<=n; i++){bestx[Q[i-1].ID] = K.bestx[i];}delete [] Q;delete [] K.w;delete [] K.p;delete [] K.bestx;delete [] K.H;return bestp;}int main(){cout<<"请在input.txt文件中输入物品数量、背包容量"<<endl;int N ;in>>N;Typew c; //背包容量in>>c;int bestx[N+1]; //最优解int bestp; //最优值Typep p[N+1];//物品价值Typew w[N+1];//物品重量cout<<"在input.txt文件中读取的物品总数N = "<< N<<",背包容量C = "<< c<<endl; cout<<"请选择生成数据的规模大小:200请输入1,2000请输入2,20000请输入3"<<endl; int x;cin>>x;if(x==1){ofstream in1("input1.txt");srand(time(NULL));int n=200;int *a=new int[n];for(int i=0;i<n;i++){a[i]=rand()%91;in1<<a[i]<<" ";}cout<<"随机数已请生成到input1文件中,请将数据添加到input.txt文件中"<<endl; }else if(x==2){ofstream in1("input1.txt");srand(time(NULL));int n=2000;int *a=new int[n];for(int i=0;i<n;i++){a[i]=rand()%91;in1<<a[i]<<" ";}cout<<"随机数已请生成到input1文件中,请将数据添加到input.txt文件中"<<endl; }else if(x==3){ofstream in1("input1.txt");srand(time(NULL));int n=20000;int *a=new int[n];for(int i=0;i<n;i++){a[i]=rand()%91;in1<<a[i]<<" ";}cout<<"随机数已请生成到input1文件中,请将数据添加到input.txt文件中"<<endl;}cout<<"添加完毕后请输入1"<<endl;int m;cin>>m;clock_t start,finish;start=clock();for (int i = 1; i <= N; i++){in>>w[i];}for (int i = 1; i <= N; i++){in>>p[i];}cout<<"已在input文件中读取物品重量和价值。
数据结构(八):优先队列-最大最小优先

数据结构(⼋):优先队列-最⼤最⼩优先⼀、优先队列的概述 在前⾯的数据结构(三):线性表-栈,队列中记录到,队列是先进先出的结构,元素在队列末端添加,在队列前头删除,若使⽤该队列的数据结构,则当要找出队列中的最⼤最⼩值时,需要遍历队列 对每个元素做⽐较后得出,这样在实际的⽣产应⽤中效率是很低的,这时就需要有⼀种队列,能快捷的获取队列中的最⼤或最⼩值,叫做优先队列。
使⽤优先队列保存数据元素,能快速的获取队列的最⼤或最⼩值,⽐如计算机中有多个排队的任务,但是需要按照优先级⼀⼀执⾏,此时优先队列的优势便得到了体现,在前⼀章对堆的记录中 我们发现堆能快速的找到最⼤或最⼩值并删除,符合优先队列的应⽤场景,因此本章我们使⽤堆来实现最⼤,最⼩优先队列和索引优先队列⼆、最⼩优先队列 1、最⼩优先队列实际就是⼀个⼩顶堆,即每次插⼊堆中的元素,都存储⾄堆末端,通过上浮操作⽐较,⼩于⽗节点则和⽗节点交换元素,直到根结点为⽌,这样就形成了⼀个⼩顶堆。
2、在获取最⼩值时,由于堆是数组的结构,只需获取根结点的值,即数组下标为1的值即可。
3、获取最⼩值并删除,则可以交换根结点和尾结点,之后删除尾结点,并对根结点进⾏下沉操作,保证每个⽗节点都⼩于两个左右⼦树即可public class MinPriorityQueue<T extends Comparable<T>> {// 初始化堆private T[] items;// 初始化个数private int N;/*** 返回优先队列⼤⼩*** @return*/public int size() {return N;}/*** 队列是否为空** @return*/public boolean isEmpty() {return N==0;}/*** 构造⽅法,传⼊堆的初始⼤⼩** @param size*/public MinPriorityQueue(int size) {items = (T[]) new Comparable[size + 1]; N = 0;}/*** 判断堆中索引i处的值是否⼩于j处的值** @param i* @param j* @return*/private boolean bigger(int i, int j) {return items[i].compareTo(items[j]) > 0; }/*** 元素位置的交换** @param col* @param i* @param j*/private void switchPos(int i, int j) {T temp = items[i];items[i] = items[j];items[j] = temp;}/*** 删除堆中最⼤的元素,并且返回这个元素 ** @return*/public T delMin() {// 获取根结点最⼤值T minValue = items[1];// 交换根结点和尾结点switchPos(1, N);// 尾结点置空items[N] = null;// 堆数量减1N--;// 根结点下沉sink(1);return minValue;}/*** 往堆中插⼊⼀个元素t** @param t*/public void insert(T t) {items[++N] = t;swim(N);}/*** 使⽤上浮算法,使堆中索引k处的值能够处于⼀个正确的位置 ** @param k*/private void swim(int k) {while (k > 1) {if (bigger(k / 2, k)) {switchPos(k, k /2);}k = k / 2;}}/*** 使⽤下沉算法,使堆中索引k处的值能够处于⼀个正确的位置 ** @param k*/private void sink(int k) {while (2 * k <= N) {int min;// 存在右⼦结点的情况if (2 * k + 1 <= N) {if (bigger(2 * k, 2 * k + 1)) {min = 2 * k + 1;} else {min = 2 * k;}} else {min = 2 * k;min = 2 * k;}// 当前结点不⽐左右⼦树结点的最⼩值⼩,则退出if (bigger(min, k)) {break;}switchPos(k, min);k = min;}}public static void main(String[] args) {String[] arr = { "S", "O", "R", "T", "E", "X", "A", "M", "P", "L", "E" };MinPriorityQueue<String> minpq = new MinPriorityQueue<>(20);for (String s : arr) {minpq.insert(s);}String del;while (!minpq.isEmpty()) {del = minpq.delMin();System.out.print(minpq.size());System.out.println(del + ",");}}}三、最⼤优先队列 1、最⼤优先队列实际就是⼀个⼤顶堆,即每次插⼊堆中的元素,都存储⾄堆末端,通过上浮操作⽐较,⼤于⽗节点则和⽗节点交换元素,直到根结点为⽌,这样就形成了⼀个⼤顶堆。
数据结构:优先队列

下沉操作核心代码如下:
private void sink(int k) { while (2 * k <= N) { int j = 2 * k; if (j < N && less(j, j + 1)) { j++; } if (!less(k, j)) { break; } exch(k, j); k = j; }
}
public boolean isEmpty() { return n == 0; } public int size() { return n; } public Key delMax() { return pq[--n]; }
public void insert(Key key) { int i = n-1; while (i >= 0 && less(key, pq[i])) { pq[i+1] = pq[i]; i--; } pq[i+1] = key; n++;
pq[N + 1] = null; sink(1); return max; }
private boolean less(int i, int j) { return pq[i].compareTo(pq[j]) < 0;
}
private void exch(int i, int j) { Key temp = pq[i]; pq[i] = pq[j]; pq[j] = temp;
例如,我们有一台能够运行多个程序的计算机。计算机通过给每个应用一个优先级属性,将应用根据优先级进行排列,计算机总是处理 下一个优先级最高的元素。
优先队列及其应用场景

优先队列及其应用场景优先队列是一种常见的数据结构,它在很多应用场景中都有广泛的应用。
本文将介绍优先队列的基本概念、实现方式以及一些常见的应用场景。
一、优先队列的基本概念优先队列是一种特殊的队列,其中每个元素都有一个与之关联的优先级。
在优先队列中,元素的出队顺序不仅取决于它们进入队列的顺序,还取决于它们的优先级。
具有较高优先级的元素会被先出队列,而具有较低优先级的元素会被后出队列。
二、优先队列的实现方式实现优先队列的方法有多种,常见的有两种:基于堆和基于有序数组。
1. 基于堆的优先队列:堆是一种满足堆性质的完全二叉树,可以用数组实现。
在基于堆的优先队列中,堆顶元素具有最高的优先级,每次出队列时都会选择堆中优先级最高的元素。
插入和删除操作的时间复杂度都是O(log n)。
2. 基于有序数组的优先队列:在基于有序数组的优先队列中,元素按照优先级有序排列。
插入操作时,需要找到合适的位置将元素插入到有序数组中;删除操作时,从有序数组中删除优先级最高的元素。
插入的时间复杂度为O(n),删除的时间复杂度为O(1)。
三、优先队列的应用场景优先队列在很多实际问题中都有重要的应用,下面介绍几个常见的应用场景。
1. 任务调度:在操作系统中,有很多任务需要按照优先级进行调度。
优先队列可以用来存储这些任务,每次选择优先级最高的任务进行调度。
通过合理设置任务的优先级,可以实现高效的任务调度。
2. 模拟系统:在模拟系统中,需要对事件按照发生的顺序进行处理。
优先队列可以用来存储待处理的事件,每次选择发生时间最早的事件进行处理。
通过使用优先队列,可以模拟实际系统中的事件处理过程。
3. 图算法:在图算法中,优先队列可以用来存储待访问的节点或边。
每次选择优先级最高的节点或边进行访问,可以实现一些基于优先级的图算法,如最短路径算法、最小生成树算法等。
4. 哈夫曼编码:哈夫曼编码是一种常见的无损压缩算法,可以将原始数据编码为较短的二进制串。
分支界限法0-1背包问题(优先队列式分支限界法)
分⽀界限法0-1背包问题(优先队列式分⽀限界法)输⼊要求有多组数据。
每组数据包含2部分。
第⼀部分包含两个整数C (1 <= C <= 10000)和 n (1 <= n <= 10,分别表⽰背包的容量和物品的个数。
第⼆部分由n⾏数据,每⾏包括2个整数 wi(0< wi <= 100)和 vi(0 < vi <= 100),分别表⽰第i个物品的总量和价值输出要求对于每组输⼊数据,按出队次序输出每个结点的信息,包括所在层数,编号,背包中物品重量和价值。
每个结点的信息占⼀⾏,如果是叶⼦结点且其所代表的背包中物品价值⼤于当前最优值(初始为0),则输出当前最优值 bestv 和最优解bestx(另占⼀⾏)参见样例输出测试数据输⼊⽰例5 32 23 22 3输出⽰例1 1 0 02 2 2 23 5 2 24 10 4 5bestv=5, bestx=[ 1 0 1 ]4 11 2 23 4 5 42 3 0 0⼩贴⼠可采⽤如下的结构体存储结点:typedef struct{int no; // 结点在堆中的标号int sw; // 背包中物品的重量int sv; // 背包中物品的价值double prior; // 优先值 sv/sw}Node;#include<stdio.h>#include<math.h>#include<string.h>typedef struct {int no; // 结点标号int id; // 节点idint sw; // 背包中物品的重量int sv; // 背包中物品的价值double prior; // sv/sw}Node;int surplusValue(int *v,int n,int y) {int sum = 0;for(int i = y; i <= n; i++) {sum += v[i];}return sum;}void qsort(Node *que,int l,int r) {int len = r - l + 1;int flag;for(int i = 0; i < len; i ++) {flag = 0;for(int j = l; j < l + len - i; j++) {if(que[j].prior < que[j+1].prior) {Node t = que[j];que[j] = que[j+1];que[j+1] = t;flag = 1;}}//if(!flag ) return;}}void branchknap(int *w,int *v,int c,int n) {int bestv = 0;int f = 0;int r = 0;Node que[3000];memset(que,0,sizeof(que));int path[15];que[0].no = 1;que[0].id = que[0].sv = que[0].sw = que[0].prior = 0;while(f <= r) {Node node = que[f];printf("%d %d %d %d\n",node.id+1,node.no,node.sw,node.sv);if(node.no >= pow(2,n)) {if(node.sv > bestv) {bestv = node.sv;printf("bestv=%d, bestx=[",bestv);int temp = node.no;int i = 0;while(temp > 1) {if(temp % 2 == 0)path[i] = 1;elsepath[i] = 0;temp /= 2;i++ ;}i--;while(i >= 0) {while(i >= 0) {printf(" %d",path[i]);i--;}printf(" ]\n");}} else {if((node.sw + w[node.id + 1]) <= c && surplusValue(v,n,node.id+1) + node.sv > bestv) { r++;que[r].id = node.id + 1;que[r].no = node.no*2;int id = node.id + 1;que[r].sv = node.sv + v[id];que[r].sw = node.sw + w[id];que[r].prior = que[r].sv / (que[r].sw*1.0);}if(surplusValue(v,n,node.id+2) + node.sv > bestv) {r++;que[r].id = node.id + 1;que[r].no = node.no*2 + 1;que[r].sv = node.sv;que[r].sw = node.sw;que[r].prior = node.prior;}}f++;qsort(que,f,r);}}int main() {int c,n;int w[15],v[15];while(~scanf("%d %d",&c,&n)){for(int i = 1; i <= n; i++) {scanf("%d %d",&w[i],&v[i]);}branchknap(w,v,c,n);}return 0;}#include<stdio.h>#include<math.h>#include<string.h>typedef int bool;#define true 1#define false 0struct Node{int no; // ?áµ?±êo?int id; //jie dian idint sw; // ±3°ü?D·µá?int sv; // ±3°ü?D·µ?µdouble prior;};struct Node queuee[2000];int w[15],v[15];int bestv = 0,c,n;int path[15]; //lu jingint surplusValue(int y) {int sum = 0;for(int i = y; i <= n; i++)sum += v[i];return sum;}void qsort(int l,int r) {// printf("------\n");int len = r - l + 1;//printf("----%d %d %d-----\n",l,r,len);bool flag;for(int i = 0; i < len ; i++) {flag = false;for(int j = l; j <l+ len -i ;j++) {if(queuee[j].prior < queuee[j+1].prior) {struct Node temp = queuee[j];queuee[j] = queuee[j+1];queuee[j+1] = temp;flag = true;}//if(!flag) return;}}// printf("---排序嘻嘻---\n");//for(int i = l; i <= r;i++ )// printf("***%d : %.2lf\n",queuee[i].no,queuee[i].prior);// printf("\n------\n");}void branchknap() {bestv = 0;int f = 0;int r = 0;queuee[0].no = 1;queuee[0].id = 0;queuee[0].sv = 0;queuee[0].sw = 0;queuee[0].prior = 0;// printf("f: %d r: %d\n",f,r);while(f <= r) {struct Node node = queuee[f];printf("%d %d %d %d\n",node.id+1,node.no,node.sw,node.sv);if(node.no >= pow(2,n)) {if(node.sv > bestv) {bestv = node.sv;//TODOprintf("bestv=%d, bestx=[",bestv);int temp = node.no;int i = 0;while(temp > 1) {if(temp%2 == 0)path[i] = 1;elsepath[i] = 0;temp /= 2;i++;}i--;while(i >= 0) {while(i >= 0) {printf(" %d",path[i]);i--;}printf(" ]\n");}} else {if((node.sw + w[node.id+1]) <= c && surplusValue(node.id+1) + node.sv > bestv) { r++;//printf("%d\n",(node.sw + w[node.id+1]));queuee[r].id = node.id+1;queuee[r].no = node.no*2;int id = node.id+1;queuee[r].sv = node.sv + v[id];queuee[r].sw = node.sw + w[id];queuee[r].prior = queuee[r].sv/(queuee[r].sw*1.0);//printf("进队id: %d\n",queuee[r].no) ;//printf("%d %d %d\n",id,v[id], w[id]);}if(surplusValue(node.id+2) + node.sv > bestv) {r++;queuee[r].id = node.id+1;queuee[r].no = node.no*2 + 1;queuee[r].sv = node.sv ;queuee[r].sw = node.sw ;queuee[r].prior = node.prior;//printf("进队id: %d\n",queuee[r].no) ;}}f++;qsort(f,r);}}int main() {while(~scanf("%d %d",&c,&n)){memset(queuee,0,sizeof(queuee));for(int i = 1; i <= n; i++) {scanf("%d %d",&w[i],&v[i]);}branchknap();}return 0;}。
数据结构优先队列图等总结及习题
优先队列、图等总结及习题一、优先队列1、定义优先队列(priority queue)是0个或多个元素的集合,每个元素都有一个优先权或值。
与FIFO结构的队列不同,优先队列中元素出队列的顺序由元素的优先级决定。
从优先队列中删除元素是根据优先权高或低的次序,而不是元素进入队列的次序.对优先队列执行的操作有:1)查找一个元素2)插入一个新元素3)删除一个元素2、描述线性表、堆、左高树(1)线性表⏹采用无序线性表描述最大优先队列公式化描述(利用公式Location(i)=i-1)◆插入:表的右端末尾执行,时间: Θ(1) ;◆删除:查找优先权最大的元素,时间:Θ(n) ;使用链表,◆插入:在链头执行,时间: Θ(1) ;◆删除: Θ(n) ;⏹采用有序线性表描述最大优先队列公式化描述(利用公式Location(i)=i-1,元素按递增次序排列)◆插入: O(n) ;删除: O(1) ;使用链表(按递减次序排列)插入: O(n) ;删除: O(1)(2)堆◆最大/最小树◆最大/最小堆初始化、插入、删除。
(3)左高树定义(重量优先、高度优先);操作:创建、插入、删除。
3、应用(1)堆排序(2)哈夫曼编码(3)归并排序二、图1、定义⏹图(graph)是一个用线或边连接在一起的顶点或节点的集合。
G = (V,E)V 是顶点集. E是边集.顶点也叫作节点( nodes)和点(points).E中的每一条边连接V中两个不同的顶点。
边也叫作弧(arcs)或连线(lines) 。
可以用(i,j)来表示一条边,其中i和j是E所连接的两个顶点。
不带方向的边叫无向边(undirected edge)。
对无向边来说,(i,j)和(j,i)是一样的。
带方向的边叫有向边(directed edge),而对有向边来说,(i,j)和(j,i)是不同的。
有向图、无向图、带权有向图、带权无向图2、描述邻接矩阵、邻接压缩表、邻接链表(1)邻接矩阵(2)邻接压缩表(3)邻接链表3、基本操作及应用(1)基本操作求是否存在边、顶点度数…,DFS、BFS(2)应用求路径、求连通分支、判别连通性…三、贪心算法1、单源最短路径2、拓扑排序3、最小耗费生成树四、分而治之1、快速排序2、归并排序习题:1、归并排序-优先队列练习232、已知图G 的邻接矩阵如下所示:由邻接矩阵画出相应的图G ;图中所有顶点是否都在它的拓扑有序序列中?⎥⎥⎥⎥⎦⎤⎢⎢⎢⎢⎣⎡01000001010010103、分别用深度优先搜索和宽度优先搜索遍历下图所示的无向图,给出以1为起点的顶点访问序列(同一个顶点的多个邻接点,按数字顺序访问),给出一棵深度优先生成树和宽度优先生成树。
java优先队列用法
java优先队列用法Java中的优先队列(PriorityQueue)是一种特殊的队列,它的元素按照优先级进行排序。
在优先队列中,元素可以通过自然排序(natural ordering)或者根据自定义的比较器(Comparator)进行排序。
优先队列经常用于解决一些优先级相关的问题,例如任务调度、事件处理等。
下面是一些关于Java优先队列的使用方法和相关参考内容。
创建优先队列:要使用优先队列,首先需要创建一个PriorityQueue对象,例如:```PriorityQueue<Integer> pq = new PriorityQueue<>();```上面的代码创建了一个容量为11的优先队列,并通过自然顺序进行元素排序。
可以通过指定Comparator来创建自定义排序的优先队列,例如:```PriorityQueue<Integer> pq = newPriorityQueue<>(Collections.reverseOrder());```上面的代码创建了一个降序排列的优先队列。
添加元素:可以使用add()或offer()方法将元素添加到优先队列中,例如:```pq.add(10);pq.offer(20);```在添加元素时,优先队列会根据元素的优先级进行排序。
获取队首元素:要获取优先队列中的队首元素,可以使用peek()方法,例如:```int firstElement = pq.peek();```peek()方法返回队首元素,但不会删除它。
删除队首元素:要删除优先队列中的队首元素,可以使用poll()方法,例如:```int firstElement = pq.poll();```poll()方法返回队首元素,并将其从优先队列中删除。
判断队列是否为空:要判断优先队列是否为空,可以使用isEmpty()方法,例如:```boolean isEmpty = pq.isEmpty();```isEmpty()方法返回true,表示队列为空;返回false,表示队列不为空。
STL优先队列的使用方法_进阶篇
// 如果这个会了,那优先队列就全部OK了// 优先队列在堆里放指针时候的运用// 即用stl来构建最大堆最小堆// 但是不同于一般的堆这里讲的是堆中放的是指针是指针!!!!!!// 简单易懂浅显但不深刻,能迅速应用,后面的要自己在实际操作中理解//#include <Query.h>#include <queue>//注意这里的头文件定义写成上面的那个是不行的#include <iostream>using namespace std;//这句话一定不能忘记//STL在这里的操作类似JAVA的类的概念,需要重新定义一下类的操作优先队列的模板里面放的是某各class 所以我们要定义类//重写struct bb{int num;//这里你可以放任意你愿意放的类但是这个class 要有自己的比大小操作符bb(int n=0){num=n;}//初始化};// 重点!!!!!!!!!////运用指针来比较类实例大小的时候要注意存在模板中的第三个类,重载的东西是操作符()//为此,我们要重写优先级别的定义优先队列模板中的最后一个运算类相当于运算符class op{public:bool operator()(bb* a,bb* b){return a->num<b->num;}//这里放进来的就是class bb 的指针了而这个我们自己定义的op运算就是比较指针所指向的bb类的实例的大小注意返回为bool//大顶堆小于大顶堆大于小顶堆};//测试int main(){priority_queue<bb*,vector<bb*>,op>Q;//这里用的是一个类模板//第一个参数bb*的意思是优先队列里的内容是什么bb* 指针//第二个参数vector<bb*>的意思是优先队列的储存方式是什么vector线性数组list 链表//第三个参数op的意思采用哪种方式确定优先队列的优先级别的运算我们采用指针的比较op 类运算bb a(1),b(2),c(3),d(5),e(6),f(7);//实例//指针实例bb*aa=&a;bb *bi=&b;//不可以用bb哦bb* cc=&c;bb* dd=&d;bb* ee=&e;bb* ff=&f;Q.push(aa);Q.push(bi);Q.push(cc);Q.push(dd);Q.push(ee);Q.push(ff);//编译成功后说明语法正确否则检查指针op类等//输出测试cout<<Q.top()->num<<endl;}。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
2 9 11 6
3 7
8
4
10
5
34
9.3.4 最大堆的初始化
1
2 9 11 6
7 3
8
4
10
5
35
9.3.4 最大堆的初始化
1
2 9 11 6
7 3
8
4
10
5
36
9.3.4 最大堆的初始化
1
11
9 6
7 3
8
4
10
5
为 2 找位置
37
9.3.4 最大堆的初始化
1
11
9 10 6
7 3
8
4
5
为 2 找位置
38
9.3.4 最大堆的初始化
1
11
9 10 6
7 3
8Hale Waihona Puke 42539
9.3.4 最大堆的初始化
1
11 9 10 6
7 3
8
4
2
5
40
9.3.4 最大堆的初始化
11
7 9 10 6 3
8
4
2
5
为 1 找位置
41
9.3.4 最大堆的初始化
11
10 9 6
7 3
8
4
2
5
为 1 找位置
“查找/删除”操作用来“搜索/删除”优先权最 大的元素。
优先权队列中的元素可以有相同的优先权。
5
最大优先权队列的抽象数据类型描述
抽象数据类型 MaxPriorityQueue{ 实例 有限的元素集合,每个元素都有一个优先权 操作 Create():创建一个空的优先队列 Size():返回队列中的元素数目 Max():返回具有最大优先权的元素 Insert(x):将x插入队列 DeleteMax(x):从队列中删除具有最大优先权的元素, 并将该元素返回至x }
26
9.3.4 最大堆的初始化
1. 通过在初始化为空的堆中执行n次插入
操作来构造。
O(nlog2n)
更快的堆的初始化策略? 2. 通过必要时对树进行调整的方法构造。
(n)
27
思想
从第一个具有孩子的节点开始,
这个元素在数组中的位置为i=[n/2]
如果以这个元素为根的子树已是最大堆,则此 时不需调整
采用有序线性表描述最大优先队列
公式化描述(利用公式Location(i)=i-1,元素按递增次序 排列) 插入: O(n) ;删除: O(1) ; 使用链表(按递减次序排列) 插入: O(n) ;删除: O(1) ; 8
9.3 堆(Heaps)
9.3.1 定义 定义[最大树(最小树)] 每个节点的值
16
9.3.2 最大堆的插入
9 20 7
6
5 1 7
8
2
6
17
9.3.2 最大堆的插入
20 9 7
6
5 1 7
8
2
6
18
9.3.2 最大堆的插入
插入的时间复杂性:
每一层的工作,耗时:(1) 实现插入策略的时间复杂性为:O(height) = O(log2n), ( n 是堆的大小)
19
9.3.3 最大堆的删除
20 15 6 5 1 7 9 8 2 7 6
最大元素在根上。
20
9.3.3 最大堆的删除
15
7
6
5 1 7
9
8
2
6
最大元素被删除以后
21
9.3.3 最大堆的删除
15
7
6
5 1 7
9
8
2
6
具有10个节点的堆. 在堆中重新插入8 .
22
9.3.3 最大堆的删除
8 15 6 9 2 7 6
否则必须调整子树使之成为堆。
随后,继续检查以i-1,i-2等节点为根的 子树 直到检查到整个二叉树的根节点(其位置 为1)。
28
8/16/2015
9.3.4 最大堆的初始化
例: 输入数组 = [1,2,3,4,5,6,7,8,9,10,11]
1
2
3
4
5
6
7
8
9
10
11
29
9.3.4 最大堆的初始化
}
}
heap[c/2] = y;
// heap[c] 应是较大的同胞节点 if (c < CurrentSize && heap[c] < heap[c+1]) c++; //能把y放入heap[c/2]吗? if (y >= heap[c]) break; // 能 // 不能 heap[c/2] = heap[c]; // 将孩子上移 c *= 2; // 下移一层 }
从数组中最右一个有孩子的节点开始 这个元素的位置
i= n/2 .
1
2
3
4
5
6
7
8
9
10
11
30
9.3.4 最大堆的初始化
1
2 4 11 6
3
7
8
9
10
5
31
9.3.4 最大堆的初始化
1
2 4 11 6
3
7
8
9
10
5
32
9.3.4 最大堆的初始化
1
2 9 11 6
3 7
8
4
10
5
33
9.3.4 最大堆的初始化
5
1
7
需要进行调整(或重构)。左子树和右子树是最大堆
23
9.3.3 最大堆的删除
15 8 6 5 1 7 9 2 7 6
24
9.3.3 最大堆的删除
15 9 6 5 1 7 8 2 7 6
25
9.3.3 最大堆的删除
删除的时间复杂性:
删除的时间复杂性与插入的时间复杂性相同. 每一层的工作,耗时:(1) 实现删除策略的时间复杂性为:O(height) = O(log2n), ( n 是堆的大小)
{// 构造函数
MaxSize = MaxHeapSize; heap = new T[MaxSize+1]; CurrentSize = 0;
}
48
最大堆的插入
template<class T> MaxHeap<T>& MaxHeap<T>::Insert(const T& x) {//把x插入到最大堆中 if (CurrentSize==MaxSize) throw NoMem(); //为x寻找相应插入位置 //i从新的叶节点开始,并沿着树上升 int i=++CurrentSize; while (i!=1 && x>heap[i/2]){ //不能把x放入heap[i] heap[i]=heap[i/2]; i/=2; } heap[i]=x; return *this; }
8/16/2015 51
void MaxHeap<T>::Initialize(T a[], int size, int ArraySize) {// 把数组a初始化为最大堆. delete [] heap; heap = a; CurrentSize = size; MaxSize = ArraySize; // 产生一个最大堆 for (int i = CurrentSize/2; i >= 1; i--) { T y = heap[i]; // 子树的根 // 寻找放置y的位置 int c = 2*i; // c的父节点是y的目标位置 while (c <= CurrentSize) {
8/16/2015 49
最大堆的删除(1/2)
template<class T> MaxHeap<T>& MaxHeap<T>::DeleteMax(T& x)
{//将最大元素放入x,并从堆中删除最大元素
//检查堆是否为空 if (CurrentSize==0) throw OutOfBounds(); //队列空 x=heap[1];//最大元素 //重构堆 T y=heap[CurrentSize--];//最后一个元素
//从根开始,为y寻找合适的位置
int i=1, //堆的当前节点 ci=2;//i的孩子
8/16/2015 8/16/2015 50
最大堆的删除(2/2)
while (ci<=CurrentSize) { //heap[ci]应该是i较大的孩子 if(ci<CurrentSize && heap[ci]<heap[ci+1]) ci++; //能把y放入heap[i]吗? if (y>=heap[ci]) break; //能 //不能 heap[i]=heap[ci]; i=ci; ci*=2; } heap[i]=y; return *this; }
堆是完全二叉树,可用一维数组有效地描述堆.
9
8 6 7 2
7 6
5
heap
1
9 8 7 6 7 2 6 5 1 0 1 2 3 4 5 6 7 8 9 10
currentsize
……
Maxsize
47
MaxHeap构造函数
template<class T>
MaxHeap<T>::MaxHeap(int MaxHeapSize)