priority_queue sort 自定义比较终极模板 C++ & JAVA

265 篇文章 1 订阅
231 篇文章 0 订阅

共同可以使用的模版有

 

class cmp2 {
 public:
   bool operator()(const Node& a, const Node& b) {
     return a.x < b.x;
   }
};

在make_heap和sort里用cmp2(), 在priority_queue里用priority_queue<Node, vector<Node>, cmp2()>

注意传引用之前一定要加const!!!!写成这样就太差了。。。

class cmp2 {
 public:
   bool operator()(Node a, Node b) {
     return a.x < b.x;
   }
};







比较有两种重载,一种是类内部的bool operator<( 只有一个参数 ),当然bool operator< 也可以拿到类的外面;另外一种是写一个cmp,利用cmp返回作为sort的第三个参数,就是这样。第一种方法,这里上代码:

#include <iostream>
#include <stdio.h>
#include <queue>
#include <stdlib.h>
#include <functional>
#include <algorithm>
using namespace std;
class Node{
public:		
    int x, y;
    Node( int a= 0, int b= 0 ):x(a),y(b) {}
    bool operator<(Node m)const{
		return x<m.x;
	} 
};

/*
重载可以放在外面,不用const修饰 
bool operator<( Node a, Node b ){
    if( a.x== b.x ) return a.y> b.y;
    return a.x> b.x; 
}
*/

int main()
{
    priority_queue<Node> q;
    vector<Node> qq;
	
    
    for( int i= 0; i< 10; ++i ){
    	q.push( Node( rand(), rand() ) );
    	qq.push_back( Node( rand(),rand() ) );
	}
	sort(qq.begin(),qq.end());
	printf("The result of q is :\n");
    while( !q.empty() )
    {
        cout << q.top().x << ' ' << q.top().y << endl;
        q.pop();
    }
	printf("The result of qq is :\n");
	for(int i=0;i<qq.size();i++){
		printf("%d %d\n",qq[i].x,qq[i].y);
	}	
    return 0;
}

第二种方法:

#include <algorithm>
#include <stdio.h>
using namespace std;

class Node {
 public:
  int x,y;
  Node(int a = 0, int b = 0):x(a),y(b) {}
};
bool cmp(int x, int y) {
  return x < y;
}
bool cmp1(const Node a, const Node b) {
  return a.x < b.x;
}
class cmp2 {
 public:
   bool operator()(const Node& a, const Node& b) {
     return a.x < b.x;
   }
};
int main() {
  int a[] = {4,3,1,2,3,5};
  sort(a, a + sizeof(a)/sizeof(int), cmp);
  for (int i = 0; i < sizeof(a)/sizeof(int); ++i)
    printf("%d ",a[i]);
  printf("\n-----------------------------------------\n");
  Node b[] = {Node(4,4),Node(3,3),Node(1,1),Node(2,2),Node(3,3),Node(5,5)};

  //sort(b, b + sizeof(b)/sizeof(Node), cmp1);
  sort(b, b + sizeof(b)/sizeof(Node), cmp2());

  for (int i = 0; i < sizeof(b)/sizeof(Node); ++i)
    printf("%d-%d ",b[i].x, b[i].y);
  printf("\n-----------------------------------------\n");
  
  return 0;
}


虽然说bool operator<比较简单,但是bool operator<(ListNode* a, ListNode* b)这样是无法通过的,因此,必须在某些时候定义用于比较的类。其实就是在一个类里放一个bool operator(ListNode* a, ListNode* b)即可,以leetcode中Merge k Sorted lists 为例,转网上某人的一个代码:

#include<iostream>
#include<stdio.h>
#include<stack>
#include<vector>
#include<string>
#include<unordered_set>
#include<unordered_map>

#include<set>

#include<queue>
#include<map>

using namespace std;

struct ListNode {
	int val;
	ListNode *next;
	ListNode(int x) : val(x), next(NULL) {}
};

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
 
class cmp
{
public:
    bool operator() (ListNode *a,ListNode *b)
    {
        return a->val > b->val;   
    }
};
 
class Solution {
public:
    ListNode *mergeKLists(vector<ListNode *> &lists) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        if(lists.size() == 0)
            return NULL; 
        priority_queue< ListNode * , vector<ListNode *> , cmp > que;//time O(klogn) , space O(k)
        
        for(int i=0;i<=lists.size()-1;i++)
        {
            if(lists[i]!=NULL)
                que.push(lists[i]);//each first Node in the K Lists
        }
        
        ListNode *head=NULL,*pre=NULL,*tmp;
        
        while(!que.empty())
        {
            tmp=que.top();
            que.pop();
            
            if(head==NULL)
                head=tmp;
            else
                pre->next=tmp; 
            
            pre=tmp;
            
            if(tmp->next!=NULL)
                que.push(tmp->next);
        }
        return head;
    }
};



int main(){
	Solution s;
	//vector<string> res;
	//  res=s.restoreIpAddresses("172162541");
	//bool hello = s.str2num("172162541",3,5);
	//int m = 3, n = 6, k = 5, i, j;
	//i = ( m) / (m + n) * (k - 1);
	ListNode *l11 = new ListNode(1);
	ListNode *l12 = new ListNode(4);
	ListNode *l13 = new ListNode(7);
	l11->next = l12;
	l12->next = l13;

	ListNode *l21 = new ListNode(2);
	ListNode *l22 = new ListNode(5);
	ListNode *l23 = new ListNode(8);
	l21->next = l22;
	l22->next = l23;

	ListNode *l31 = new ListNode(3);
	ListNode *l32 = new ListNode(6);
	ListNode *l33 = new ListNode(9);
	l31->next = l32;
	l32->next = l33;
	vector<ListNode*> lists;
	lists.push_back(l11);
	lists.push_back(l21);
	lists.push_back(l31);
	ListNode* res = s.mergeKLists(lists);
	while (res != NULL) {
	  cout<<res->val<<" ";
	  res = res->next;
	}

	return 0;
}

另外,使用priority_queue时建堆的复杂度为O(nlogn), 今天还发现STL里有一个建堆复杂度为O(n)的模版,建堆的复杂度本来就应该是O(n),把刚才那题用这种方式再敲一遍:

需要注意的地方在于pop_heap()这个函数,当pop之后,函数并没有把极值元素删除,而是放在vector末位。


而push_heap()这个函数,它假设vector最后一个是新添加进来的,之前已经是堆了,再做调整。


pop_heap();

它的函数原型是:void pop_heap(first_pointer,end_pointer,compare_function);

作用:pop_heap()不是真的把最大(最小)的元素从堆中弹出来。而是重新排序堆。它
把first和last交换,然后将[first,last-1)的数据再做成一个堆。

接着是push_heap() void pushheap(first_pointer,end_pointer,compare_function);

作用:push_heap()假设由[first,last-1)是一个有效的堆,然后,再把堆中的新元素加
进来,做成一个堆。

可以单步以下代码观察这个现象:


// range heap example
#include <iostream>     // std::cout
#include <algorithm>    // std::make_heap, std::pop_heap, std::push_heap, std::sort_heap
#include <vector>       // std::vector

int main () {
  int myints[] = {10,20,30,5,15};
  std::vector<int> v(myints,myints+5);

  std::make_heap (v.begin(),v.end());
  std::cout << "initial max heap   : " << v.front() << '\n';

  std::pop_heap (v.begin(),v.end()); 
  v.pop_back();
  std::cout << "max heap after pop : " << v.front() << '\n';


  v.push_back(99); 
  std::push_heap (v.begin(),v.end());
  std::cout << "max heap after push: " << v.front() << '\n';

  std::sort_heap (v.begin(),v.end());

  std::cout << "final sorted range :";
  for (unsigned i=0; i<v.size(); i++)
    std::cout << ' ' << v[i];

  std::cout << '\n';

  return 0;
}

其实priority_queue就是这么个东西:

#include <iostream>  
#include <algorithm>  
#include <vector>  
 
using namespace std;  
 
class priority_queue  
{  
    private:  
        vector<int> data;  
          
    public:  
        void push( int t ){   
            data.push_back(t);   
            push_heap( data.begin(), data.end());   
        }  
          
        void pop(){  
            pop_heap( data.begin(), data.end() );  
            data.pop_back();  
        }  
          
        int top()    { return data.front(); }  
        int size()   { return data.size();  }  
        bool empty() { return data.empty(); }  
};  
 
int main()  
{  
    priority_queue  test;  
    test.push( 3 );  
    test.push( 5 );  
    test.push( 2 );  
    test.push( 4 );  
      
    while( !test.empty() ){  
        cout << test.top() << endl;  
        test.pop(); }  
          
    return 0;  
}  





好,这个题总算是完整地过了:

注意使用cmp()或者cmp1都可以:

class cmp {
 public:
  bool operator()(ListNode* a, ListNode* b) {
    return a->val > b->val;
  }
};

bool cmp1 (ListNode* a, ListNode* b) {
  return a->val > b->val;
}

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */

class cmp {
 public:
  bool operator()(ListNode* a, ListNode* b) {
    return a->val > b->val;
  }
};

bool cmp1 (ListNode* a, ListNode* b) {
  return a->val > b->val;
}
class Solution {
 public:
  
  ListNode *mergeKLists(vector<ListNode *> &lists) {
    // Note: The Solution object is instantiated only once and is reused by each test case.
    ListNode *head = NULL, *cur = NULL;
    vector<ListNode*>::iterator it = lists.begin();
    while (it != lists.end()) {
      if (*it == NULL)
        lists.erase(it);
      else
        it++;
    }
    if (lists.size() < 1)
      return NULL;
    make_heap(lists.begin(), lists.end(), cmp());
    while (lists.size() > 0) {
      if (head == NULL)
        head = cur = lists[0];
      else {
        cur->next = lists[0];
        cur = cur->next;
      }
      pop_heap(lists.begin(), lists.end(), cmp());
      if (lists[lists.size() - 1]->next != NULL) {
        lists[lists.size() - 1] = lists[lists.size() - 1]->next;
        push_heap(lists.begin(), lists.end(), cmp());
      }
      else
        lists.pop_back();
      
    }
    return head;
  }
};



import java.util.*;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;

public class Test {
	public String name;
	public int ID;
	Test(String name, int ID){
		this.name = name;
		this.ID = ID;
	}
	public static void main(String args[]) {
		Comparator<Test> cmp = new Comparator<Test>() {
			@Override
			public int compare(Test o1, Test o2) {
				// Different from cpp, 1, 0, -1 are all needed to be defined
				return o1.ID>=o2.ID?1:-1;
			}
		};		
		Queue<Test> priorityQueue = new PriorityQueue<Test>(1, cmp);
		priorityQueue.add(new Test("t2",2));
		priorityQueue.add(new Test("t3",3));
		priorityQueue.add(new Test("t1",1));
		priorityQueue.add(new Test("t4",4));
		System.out.print("name:"+priorityQueue.peek().name);
		
	}
}







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值