功能简单的优先级队列 堆实现 SCU 3369 SCU 3365

最近写 Prim 和 Disjkstra , 顺便复习一下堆和优先级队列的知识 :

#include <bits/stdc++.h>
using namespace std ;
#define Init_Data 0     // 设置初始数据
typedef int Data_type ; // 数据类型, 在本程序只是单一类型

class My_Priority_queue{// 优先级队列默认为小顶堆
private:
	int Max_size ;      // 优先级队列的最大容量
	int n ;             // 优先级队列当前的元素个数
	Data_type *a ;      // 数据指针, 顺序表
public:
	My_Priority_queue() ;              // 构造函数
	~My_Priority_queue() ;             // 析构函数
	void push( Data_type weight ) ;    // 往优先级队列中 push 数据
	void pop() ;                       // pop 堆顶
	Data_type top() ;                  // 访问栈顶元素
	bool empty() ;                     // 判断堆是否为空
	int size() ;                       // 堆大小
	void Shift_down( int u ) ;         // 递归   堆向下调整
	void Shift_down_2( int u ) ;       // 非递归 堆向下调整
} ;

My_Priority_queue::My_Priority_queue(){
	n = 0 ;
	Max_size = 256 ;
	a = new Data_type[Max_size] ;
	if( a ){
		for( int i = 0 ; i < Max_size ; ++i ) // 初始化
		    a[i] = Init_Data ;
	    cout << endl << "优先级队列初始化准备完毕 " << endl ;
	}
	else  
		cout << endl << "内存分配失败 !" << endl ;
}

My_Priority_queue::~My_Priority_queue(){
	if( a ) 
	    delete a , a = NULL ;         // 队列分配了空间 , 释放掉
	cout << endl << "优先级队列的内存已释放完毕 " << endl ;
}

void My_Priority_queue::push( Data_type weight ){
	if( n+1 > Max_size ){
		cout << endl << "优先级队列重新分配空间" << endl ;
		int cur = Max_size ;
		Max_size += cur ;
		Data_type *temp = new Data_type[Max_size] ;
		for( int i = 0 ; i < Max_size ; ++i )
			temp[i] = Init_Data ;
		for( int i = 1 ; i <= cur ; ++i )    // 保存原始数据
			temp[i] = a[i] ;
		delete a , a = NULL ;
		a = temp ;
		temp = NULL ;
		cout << endl << "优先级队列已重新就绪" << endl ;
	}
	a[++n] = weight ;                    // push 压入的新元素放在末尾
	int parent = n >> 1 , i = n ;        // 因为前面的都是小顶堆
	while( parent ){               
		if( a[i] < a[parent] ) 
			swap( a[i] , a[parent] ) ;
		i = parent ;
		parent /= 2 ;                    // 从下向上调整, 只要和父亲相比
	}
}

void My_Priority_queue::pop(){
	if( empty() ){
		cout << "It's empty !" << endl ;
		return ;
	}
	swap( a[1] , a[n--] ) ;             // 把最后一个元素交换到堆顶, 堆大小 -1
	Shift_down_2( 1 ) ;                 // 从堆顶开始向下调整
}
 
Data_type My_Priority_queue::top(){     // 取堆顶元素 , 优先级队列中最小的元素
	return a[1] ;
}

bool My_Priority_queue::empty(){        // 判断优先级队列 ( 堆 ) 是否为空
	return n < 1 ;
}

int My_Priority_queue::size(){         // 取优先级队列元素个数
	return n ;
}

void My_Priority_queue::Shift_down( int u ){         // 递归
	int ans = u ;
	if( 2*u <= n && a[2*u] < a[ans] )            // 比较左孩子
		ans = 2*u ;
	if( 2*u+1 <= n && a[2*u+1] < a[ans] )        // 比较右孩子
		ans = 2*u+1 ;
	if( ans != u )                               // 最小的元素 a[ans] 在两个孩子当中
		swap( a[ans] , a[u] ) , Shift_down( ans ) ; // 交换 , 继续向下调整
}

void My_Priority_queue::Shift_down_2( int u ){          // 非递归
	int i = 2*u ;
	for( ; i <= n ; i = 2*u ){                      // 每次交换之后, i 都恢复为 2*u , 这时候的 u 不是原来的 u
		if( i+1 <= n && a[i+1] < a[i] )         // 比较右孩子
			++i ;
		if( a[i] >= a[u] ) return ;             // 如果最小的元素就是自己, 不在孩子当中
		swap( a[i] , a[u] ) ;
		u = i ;                                 // 交换最小的元素 , 更大的继续向下调整
	}
}

int main(){
	My_Priority_queue One ;
	Data_type weight ;
	int n = 600 ;
	srand( time( NULL ) ) ;
	for( int i = 1 ; i <= n ; ++i ){
		weight = rand() % 100 + 1 ; 
		One.push( weight ) ;
	}
	while( !One.empty() ){
		cout << One.top() << "  " ; 
		One.pop() ;
	}
	cout << endl ;
	return 0 ;
}

 SCU 3369 自主编写最小堆  Prim

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <queue>
using namespace std ;
#define INF 0x3f3f3f
typedef pair<int,int> P ;
int n , m , i , u , v , w ;
vector<P> One[10050] ;
int dis[10050] , C[10050] , book[10050] ;
struct Pair{
	int dis , u ;
	Pair(){}
	Pair( int _dis , int _u ){
		dis = _dis , u = _u ;
	}
} ;

class My_Priority_queue{// 优先级队列默认为小顶堆
private:
	int n ;             // 优先级队列当前的元素个数
	int Max_size ;
	Pair **a ;      // 数据指针, 顺序表
public:
	My_Priority_queue( int _Max_size ) ;              // 构造函数
	~My_Priority_queue() ;             // 析构函数
	void push( Pair *weight ) ;    // 往优先级队列中 push 数据
	void pop() ;                       // pop 栈顶
	Pair *top() ;                  // 访问栈顶元素
	bool empty() ;                     // 判断栈是否为空
	void Shift_down( int u ) ;         // 递归   堆向下调整
} ;

My_Priority_queue::My_Priority_queue( int _Max_size ){
	n = 0 ;
	Max_size = _Max_size ;
	a = new Pair*[3*Max_size] ;
	for( int i = 0 ; i < 3*Max_size ; ++i )
		a[i] = NULL ;
}

My_Priority_queue::~My_Priority_queue(){
	for( int i = 0 ; i < 3*Max_size ; ++i )
		a[i] = NULL ;
	if( a ) delete []  a ;
}

void My_Priority_queue::push( Pair *weight ){
	a[++n] = weight ;                    // push 压入的新元素放在末尾
	int parent = n >> 1 , k = n ;        // 因为前面的都是小顶堆
	while( parent ){               
		if( a[k]->dis < a[parent]->dis ) 
			swap( a[k] , a[parent] ) ;
		k = parent ;
		parent /= 2 ;                    // 从下向上调整, 只要和父亲相比
	}
}

void My_Priority_queue::pop(){
	if( empty() )  return ;
	swap( a[1] , a[n--] ) ;             // 把最后一个元素交换到堆顶, 堆大小 -1
	Shift_down( 1 ) ;                 // 从堆顶开始向下调整
}
 
Pair *My_Priority_queue::top(){     // 取堆顶元素 , 优先级队列中最小的元素
	return a[1] ;
}

bool My_Priority_queue::empty(){        // 判断优先级队列 ( 堆 ) 是否为空
	return n < 1 ;
}

void My_Priority_queue::Shift_down( int u ){
	int ans = u ;
	if( 2*u <= n && a[2*u]->dis < a[ans]->dis )            // 比较左孩子
		ans = 2*u ;
	if( 2*u+1 <= n && a[2*u+1]->dis < a[ans]->dis )        // 比较右孩子
		ans = 2*u+1 ;
	if( ans != u )                               // 最小的元素 a[ans] 在两个孩子当中
		swap( a[ans] , a[u] ) , Shift_down( ans ) ; // 交换 , 继续向下调整
}

void Prim(){
	memset( dis , INF , sizeof( dis ) ) ;
	memset( book , 0 , sizeof( book ) ) ;
	int ans = 0 , u , v , w ;
	My_Priority_queue Q( n ) ;
	Pair *cur = new Pair( dis[1] = 0 , 1 ) ;
	Q.push( cur ) ;
	while( !Q.empty() ){
		Pair *top = Q.top() ;
		Q.pop() ;
		u = top->u ;
		if( book[u] )
			continue ;
		book[u] = 1 ;
		ans += top->dis ;
		for( i = 0 ; i < (int)One[u].size() ; ++i ){
			v = One[u][i].first , w = One[u][i].second ;
			if( !book[v] && dis[v] > w ){
				Pair *t = new Pair( dis[v] = w , v ) ; 
				Q.push( t ) ;
			}
		}
	}
	printf( "%d\n" , ans+*min_element( C+1 , C+n+1 ) ) ;
}

int main(){
	while( ~scanf( "%d%d" , &n , &m ) ){
		for( i = 1 ; i <= n ; ++i )
			scanf( "%d" , &C[i] ) , One[i].clear() ;
		for( i = 1 ; i <= m ; ++i ){
			scanf( "%d%d%d" , &u , &v , &w ) ;
			w = 2*w + C[u] + C[v] ;
			One[u].push_back( P( v , w ) ) ;
			One[v].push_back( P( u , w ) ) ;
		}
		Prim() ;
	}
	return 0 ;
}

 SCU 3365 Disjkstra  ( LCA 被我用 Disjkstra 做了, haha )

#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <queue>
using namespace std ;
#define INF 0x3f3f3f
typedef pair<int,int> P ;
int N , Q ;
vector<P> One[1001] ;
int dp[1001][1001] ;
int dis[1001] ;

struct Pair{
	int dis , u ;
	Pair(){}
	Pair( int _dis , int _u ){
		dis = _dis , u = _u ;
	}
} ;

class My_Priority_queue{// 优先级队列默认为小顶堆
private:
	int n ;             // 优先级队列当前的元素个数
	int Max_size ;
	Pair **a ;      // 数据指针, 顺序表
public:
	My_Priority_queue( int _Max_size ) ;              // 构造函数
	~My_Priority_queue() ;             // 析构函数
	void push( Pair *weight ) ;    // 往优先级队列中 push 数据
	void pop() ;                       // pop 栈顶
	Pair *top() ;                  // 访问栈顶元素
	bool empty() ;                     // 判断栈是否为空
	void Shift_down( int u ) ;         // 递归   堆向下调整
} ;

My_Priority_queue::My_Priority_queue( int _Max_size ){
	n = 0 ;
	Max_size = _Max_size ;
	a = new Pair*[3*Max_size] ;
	for( int i = 0 ; i < 3*Max_size ; ++i )
		a[i] = NULL ;
}

My_Priority_queue::~My_Priority_queue(){
	for( int i = 0 ; i < 3*Max_size ; ++i )
		a[i] = NULL ;
	if( a ) delete []  a ;
}

void My_Priority_queue::push( Pair *weight ){
	a[++n] = weight ;                    // push 压入的新元素放在末尾
	int parent = n >> 1 , k = n ;        // 因为前面的都是小顶堆
	while( parent ){               
		if( a[k]->dis < a[parent]->dis ) 
			swap( a[k] , a[parent] ) ;
		k = parent ;
		parent /= 2 ;                    // 从下向上调整, 只要和父亲相比
	}
}

void My_Priority_queue::pop(){
	if( empty() )  return ;
	swap( a[1] , a[n--] ) ;             // 把最后一个元素交换到堆顶, 堆大小 -1
	Shift_down( 1 ) ;                 // 从堆顶开始向下调整
}
 
Pair *My_Priority_queue::top(){     // 取堆顶元素 , 优先级队列中最小的元素
	return a[1] ;
}

bool My_Priority_queue::empty(){        // 判断优先级队列 ( 堆 ) 是否为空
	return n < 1 ;
}

void My_Priority_queue::Shift_down( int u ){
	int ans = u ;
	if( 2*u <= n && a[2*u]->dis < a[ans]->dis )            // 比较左孩子
		ans = 2*u ;
	if( 2*u+1 <= n && a[2*u+1]->dis < a[ans]->dis )        // 比较右孩子
		ans = 2*u+1 ;
	if( ans != u )                               // 最小的元素 a[ans] 在两个孩子当中
		swap( a[ans] , a[u] ) , Shift_down( ans ) ; // 交换 , 继续向下调整
}


int Dijkstra( int src , int des ){
	int i , u , v , w ;
	memset( dis , INF , sizeof( dis ) ) ;
	My_Priority_queue Q( N ) ;
	Pair *cur = new Pair( dis[src] = 0 , src ) ;
	Q.push( cur ) ;
	while( !Q.empty() ){
		Pair *top = Q.top() ;
		Q.pop() ;
		u = top->u ;
		if( dis[u] < top->dis ) 
			continue ;
		for( i = 0 ; i < (int)One[u].size() ; ++i ){
			v = One[u][i].first , w = One[u][i].second ;
			if( dis[v] > dis[u] + w ){
				Pair *t = new Pair( dis[v] = dis[u] + w , v ) ; 
				Q.push( t ) ;
			}
		}
	}
	for( i = 1 ; i <= N ; ++i )
		dp[src][i] = dp[i][src] = dis[i] ;
	return dis[des] ;
}

int main(){
	int i , u , v , w ;
	while( ~scanf( "%d%d" , &N , &Q ) ){
		for( i = 1 ; i <= N ; ++i )
			One[i].clear() ;
		for( i = 1 ; i <= N-1 ; ++i ){
			scanf( "%d%d%d" , &u , &v , &w ) ;
			One[u].push_back( P( v , w ) ) ;
			One[v].push_back( P( u , w ) ) ;
		}
		memset( dp , 0 , sizeof( dp ) ) ;
		while( Q-- ){
			scanf( "%d%d" , &u , &v ) ;
			printf( "%d\n" , dp[u][v] ? dp[u][v] : Dijkstra( u , v ) ) ;
		}
	}
	return 0 ;
}




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值