/*
** Scan over keys equal to the partitioning element instead of
** stopping the scans when we encounter them.
*/
int partition(item_t *array,int left,int right)
{
	item_t v=array[right];
	int i,j;

	i=left-1;
	j=right;
	while(1){
		while(compare_item(array[++i],v)<=0)
			if(i==right)
				break;
		while(compare_item(array[--j],v)>=0){
			if(j==left)
				break;
		}
		if(i>=j)
			break;
		
		swap_item(&array[i],&array[j]);
	}

	swap_item(&array[i],&array[right]);

	return(i);
}
示例#2
0
void
min_heapify(int heapsize, int i)
{
	int min = i;
	int left = LEFT_CLD(i);
	int right = RIGHT_CLD(i);
	if(left<heapsize && compare_item(queue+min, queue+left)>0)
		min = left;
	if(right<heapsize && compare_item(queue+min, queue+right)>0)
		min = right;
	if(min != i) {
		swap(i, min);
		min_heapify(heapsize, min);
	}
}
static pqueue_link_t do_pqueue_construct(item_t *array,int left,int right)
{
	pqueue_link_t r;
	int middle=(left+right)/2;
	item_t max_item;

	r=malloc(sizeof(*r));
	r->left=NULL;
	r->right=NULL;

	if(right==left){
		r->item=array[left];
	
		return(r);
	}

	r->left=do_pqueue_construct(array,left,middle);
	r->right=do_pqueue_construct(array,middle+1,right);
	
	copy_item(&max_item,&r->left->item);
	if(compare_item(r->right->item,max_item)>0){
		copy_item(&max_item,&r->right->item);
	}
	copy_item(&r->item,&max_item);

	return(r);
}
void merge(item_t *a,int left,int middle,int right)
{
    int n=right-left+1;
    item_t *aux=malloc(n*sizeof(*aux));
    int i,j,k;

    for(k=0,i=left; i<=middle; i++) {
        aux[k++]=a[i];
    }
    for(i=right; i>middle; i--) {
        aux[k++]=a[i];
    }

    for(i=0,j=n-1,k=left; k<=right; k++) {
        /*
        ** When aux[i]==aux[j], considering the aux[i] first can
        ** make the merge stable.
        */
        if(compare_item(aux[i],aux[j])<=0) {
            a[k]=aux[i++];
        } else {
            a[k]=aux[j--];
        }
    }

    free(aux);
}
/*
** This heap_select function selects the kth largest element from
** the array. The idea is building a priority queue of size k at
** the right end of the array. Then do N-k replace_the_minimum (insert
** followed by delete_the_minimum) operations, so the k largest of the
** N elements of the array will be left in the heap-based priority queue.
** (You can prove this idea by yourself.) So the smallest element in
** the priority queue is the kth largest element of the whole array, that
** is, heap[1] in the minimum-oriented heap.
*/
item_t heap_select(item_t *array,int left,int right,int k)
{
	item_t *heap=array+right-k;
	int i;

	/*
	** Construct a heap-based priority queue of size k.
	*/
	for(i=k/2;i>=1;i--){
		heapify_top_down_min(heap,i,k);
	}

	/*
	** Do N-k replace_the_minimum operations, while N==right-left+1.
	*/
	for(i=right-k;i>=left;i--){
		if(compare_item(array[i],heap[1])<=0){
			continue;	
		}

		swap_item(&array[i],&heap[1]);
		heapify_top_down_min(heap,1,k);
	}

	return(heap[1]);
}
/*
** To restore the heap condition when a node's priority is decreased, we
** move down the heap, exchanging the node at position k with the largest
** of that node's two children if necessary and stopping when the node at
** k is not smaller then either child or the bottom is reached. Note that
** if n is even and k is n/2, then the node at k has only one child -- this
** case must be treated properly.
*/
void heapify_top_down(item_t *heap,int k,int n)
{
	int j;

	while(2*k<=n){
		j=2*k;
		if(j+1<=n && compare_item(heap[j+1],heap[j])>0){
			j++;
		}

		if(compare_item(heap[k],heap[j])>=0){
			break;
		}
		swap_item(&heap[k],&heap[j]);
		k=j;
	}
}
int partition_three_way(item_t *array,int left,int right)
{
	int i,j,k,l,p,q;
	item_t v=array[right];

	if(right-left+1 <= 1){
		return;
	}

	i=left;
	j=right-1;
	p=left-1;
	q=right;
	while(1){
		for(;compare_item(array[i],v)<0;i++)
			;
		for(;compare_item(array[j],v)>0;j--)
			if(j==left)
				break;
		if(i>=j)
			break;

		swap_item(&array[i],&array[j]);
		if(compare_item(array[i],v)==0){
			swap_item(&array[i++],&array[++p]);	
		}
		if(compare_item(array[j],v)==0){
			swap_item(&array[j--],&array[--q]);
		}
	}

	if(i==j && compare_item(array[i],v)==0){
		swap_item(&array[i++],&array[++p]);	
	}

	for(k=left;k<=p;k++,j--){
		swap_item(&array[k],&array[j]);
	}
	for(l=j,k=right;k>=q;k--,i++){
		swap_item(&array[k],&array[i]);
	}

	return(l);
}
示例#8
0
int guild_storage_additem(struct map_session_data* sd, struct guild_storage* stor, struct item* item_data, int amount)
{
	struct item_data *data;
	int i;

	nullpo_retr(1, sd);
	nullpo_retr(1, stor);
	nullpo_retr(1, item_data);

	if(item_data->nameid <= 0 || amount <= 0)
		return 1;

	data = itemdb_search(item_data->nameid);

	if( !itemdb_canguildstore(item_data, pc_isGM(sd)) || item_data->expire_time || item_data->bound )
	{	//Check if item is storable. [Skotlex]
		clif_displaymessage (sd->fd, msg_txt(264));
		return 1;
	}

	if( sd->state.secure_items )
	{
		clif_displaymessage(sd->fd, "You can't store items on Guild Storage. Blocked with @security");
		return 1;
	}

	if(itemdb_isstackable2(data)){ //Stackable
		for(i=0;i<MAX_GUILD_STORAGE;i++){
			if(compare_item(&stor->items[i], item_data)) {
				if(stor->items[i].amount+amount > MAX_AMOUNT)
					return 1;
				stor->items[i].amount+=amount;
				clif_storageitemadded(sd,&stor->items[i],i,amount);
				stor->dirty = 1;
				if(log_config.enable_logs&0x1000)
					log_pick_pc(sd, "G", item_data->nameid, -amount, item_data, 0);
				return 0;
			}
		}
	}
	//Add item
	for(i=0;i<MAX_GUILD_STORAGE && stor->items[i].nameid;i++);
	
	if(i>=MAX_GUILD_STORAGE)
		return 1;
	
	memcpy(&stor->items[i],item_data,sizeof(stor->items[0]));
	stor->items[i].amount=amount;
	stor->storage_amount++;
	clif_storageitemadded(sd,&stor->items[i],i,amount);
	clif_updateguildstorageamount(sd,stor->storage_amount);
	stor->dirty = 1;
	if(log_config.enable_logs&0x1000)
		log_pick_pc(sd, "G", item_data->nameid, -amount, item_data, item_data->serial );
	return 0;
}
示例#9
0
/**
 * Attempt to add an item in guild storage, then refresh it
 * @param sd : player attempting to open the guild_storage
 * @param stor : guild_storage
 * @param item_data : item to add
 * @param amount : number of item to add
 * @return 0 : success, 1 : fail
 */
char guild_storage_additem(struct map_session_data* sd, struct guild_storage* stor, struct item* item_data, int amount)
{
	struct item_data *data;
	int i;

	nullpo_retr(1, sd);
	nullpo_retr(1, stor);
	nullpo_retr(1, item_data);

	if(item_data->nameid == 0 || amount <= 0)
		return 1;

	data = itemdb_search(item_data->nameid);

	if( data->stack.guildstorage && amount > data->stack.amount )
	{// item stack limitation
		return 1;
	}

	if( !itemdb_canguildstore(item_data, pc_get_group_level(sd)) || item_data->expire_time )
	{	//Check if item is storable. [Skotlex]
		clif_displaymessage (sd->fd, msg_txt(sd,264));
		return 1;
	}

	if( (item_data->bound == BOUND_ACCOUNT || item_data->bound > BOUND_GUILD) && !pc_can_give_bounded_items(sd) ) {
		clif_displaymessage(sd->fd, msg_txt(sd,294));
		return 1;
	}

	if(itemdb_isstackable2(data)){ //Stackable
		for(i=0;i<MAX_GUILD_STORAGE;i++){
			if(compare_item(&stor->items[i], item_data)) {
				if( amount > MAX_AMOUNT - stor->items[i].amount || ( data->stack.guildstorage && amount > data->stack.amount - stor->items[i].amount ) )
					return 1;
				stor->items[i].amount+=amount;
				clif_storageitemadded(sd,&stor->items[i],i,amount);
				stor->dirty = 1;
				return 0;
			}
		}
	}
	//Add item
	for(i=0;i<MAX_GUILD_STORAGE && stor->items[i].nameid;i++);

	if(i>=MAX_GUILD_STORAGE)
		return 1;

	memcpy(&stor->items[i],item_data,sizeof(stor->items[0]));
	stor->items[i].amount=amount;
	stor->storage_amount++;
	clif_storageitemadded(sd,&stor->items[i],i,amount);
	clif_updatestorageamount(sd, stor->storage_amount, MAX_GUILD_STORAGE);
	stor->dirty = 1;
	return 0;
}
示例#10
0
/**
 * Make a player add an item to his storage
 * @param sd : player
 * @param item_data : item to add
 * @param amount : quantity of items
 * @return 0:success, 1:failed
 */
static int storage_additem(struct map_session_data* sd, struct item* item_data, int amount)
{
	struct storage_data* stor = &sd->status.storage;
	struct item_data *data;
	int i;

	if( item_data->nameid == 0 || amount <= 0 )
		return 1;

	data = itemdb_search(item_data->nameid);

	if( data->stack.storage && amount > data->stack.amount )
	{// item stack limitation
		return 1;
	}

	if( !itemdb_canstore(item_data, pc_get_group_level(sd)) )
	{	//Check if item is storable. [Skotlex]
		clif_displaymessage (sd->fd, msg_txt(sd,264));
		return 1;
	}

	if( (item_data->bound > BOUND_ACCOUNT) && !pc_can_give_bounded_items(sd) ) {
		clif_displaymessage(sd->fd, msg_txt(sd,294));
		return 1;
	}

	if( itemdb_isstackable2(data) )
	{//Stackable
		for( i = 0; i < sd->storage_size; i++ )
		{
			if( compare_item(&stor->items[i], item_data) )
			{// existing items found, stack them
				if( amount > MAX_AMOUNT - stor->items[i].amount || ( data->stack.storage && amount > data->stack.amount - stor->items[i].amount ) )
					return 1;
				stor->items[i].amount += amount;
				clif_storageitemadded(sd,&stor->items[i],i,amount);
				return 0;
			}
		}
	}

	// find free slot
	ARR_FIND( 0, sd->storage_size, i, stor->items[i].nameid == 0 );
	if( i >= sd->storage_size )
		return 1;

	// add item to slot
	memcpy(&stor->items[i],item_data,sizeof(stor->items[0]));
	stor->storage_amount++;
	stor->items[i].amount = amount;
	clif_storageitemadded(sd,&stor->items[i],i,amount);
	clif_updatestorageamount(sd, stor->storage_amount, sd->storage_size);

	return 0;
}
void insertion_sort(item_t *array,int left,int right)
{
    int i,j;
    item_t temp;

    for(i=left+1; i<=right; i++)
        if(compare_item(array[i],array[left]) < 0)
            swap_item(&array[i],&array[left]);

    for(i=left+2; i<=right; i++) {
        temp=array[i];

        for(j=i-1; compare_item(array[j],temp) > 0; j--) {
            array[j+1]=array[j];
        }

        array[j+1]=temp;
    }
}
/*
** An abstract in-place merge that uses extra space equal to
** the size of the smaller of the two arrays to be merged.
*/
void merge(item_t *a,int left,int middle,int right)
{
	int m=middle-left+1;
	int n=right-middle;
	item_t *aux;
	int i,j,k;

	/*
	** Dynamically allocate the auxiliary array whose size is
	** equal to the size of the smaller of the two subfiles.
	** Then copy the smaller subfile to the array aux in reverse
	** order, move another subfile backward to the end of the array a. 
	*/
	if(m<=n){
		aux=malloc(m*sizeof(*aux));
		for(k=0;k<m;k++){
			aux[k]=a[middle-k];
		}
		i=m-1;
		j=middle+1;
	}else{
		aux=malloc(n*sizeof(*aux));
		for(k=0;k<n;k++){
			aux[k]=a[right-k];
		}
		for(j=right,k=middle;k>=left;k--){
			a[j--]=a[k];
		}
		i=n-1;
		j=right+1-m;
	}

	/*
	** Merge the two subfiles, leaving the result in array a.
	*/
	for(k=left;k<=right;k++){
		if(i==-1){
			a[k]=a[j++];
			continue;	
		}
		if(j==right+1){
			a[k]=aux[i--];
			continue;
		}

		if(compare_item(aux[i],a[j])<0){
			a[k]=aux[i--];
		}else{
			a[k]=a[j++];
		}
	}

	free(aux);
}
/*
** The Floyd's improvement of heapify_top_down. The main idea is avoiding
** the check for whether the element has reached its position, simply
** promoting the larger of the two children until the bottom is reached,
** then moving back up the heap to the proper position.
*/
void heapify_top_down(item_t *heap,int k,int n)
{
	int i,j;

	while(3*k-1<=n){
		j=3*k-1;
		i=j+2;
		if(j+1<=n && (count_comp++,compare_item(heap[j+1],heap[j]))>0){
			j++;			
		}
		if(i<=n && (count_comp++,compare_item(heap[i],heap[j]))>0){
			j=i;
		}

		swap_item(&heap[k],&heap[j]);
		k=j;
	}

	heapify_bottom_up(heap,k);
}
示例#14
0
/*==========================================
 * Internal add-item function.
 *------------------------------------------*/
static int storage_additem(struct map_session_data* sd, struct item* item_data, int amount, int flag)
{
	struct storage_data* stor = &sd->status.storage;
	struct item_data *data;
	int i;

	if( item_data->nameid <= 0 || amount <= 0 )
		return 1;
	
	data = itemdb_search(item_data->nameid);

	if( !itemdb_canstore(item_data, pc_isGM(sd)) )
	{	//Check if item is storable. [Skotlex]
		clif_displaymessage (sd->fd, msg_txt(264));
		return 1;
	}
	
	if( itemdb_isstackable2(data) )
	{//Stackable
		for( i = 0; i < MAX_STORAGE; i++ )
		{
			if( compare_item(&stor->items[i], item_data) )
			{// existing items found, stack them
				if( amount > MAX_AMOUNT - stor->items[i].amount )
					return 1;
				stor->items[i].amount += amount;
				if( flag ) clif_storageitemadded(sd,&stor->items[i],i,amount);
				if(log_config.enable_logs&0x800)
					log_pick_pc(sd, "R", item_data->nameid, -amount, item_data, 0);
				return 0;
			}
		}
	}

	// find free slot
	ARR_FIND( 0, MAX_STORAGE, i, stor->items[i].nameid == 0 );
	if( i >= MAX_STORAGE )
		return 1;

	// add item to slot
	memcpy(&stor->items[i],item_data,sizeof(stor->items[0]));
	stor->storage_amount++;
	stor->items[i].amount = amount;
	if( flag )
	{
		clif_storageitemadded(sd,&stor->items[i],i,amount);
		clif_updatestorageamount(sd,stor->storage_amount);
	}
	if(log_config.enable_logs&0x800)
		log_pick_pc(sd, "R", item_data->nameid, -amount, item_data, item_data->serial );

	return 0;
}
示例#15
0
void
up_heapify(int from)
{
	int cld, pt;
	cld = from;
	pt = PARENT(cld);
	while(cld>0 && compare_item(queue+cld, queue+pt)<0) {
		swap(cld, pt);
		cld = pt;
		pt = PARENT(cld);
	}
}
item_t pqueue_del_max(void)
{
	int i,max;

	for(max=0,i=1;i<N;i++){
		if(compare_item(pq[i],pq[max])>0){
			max=i;
		}
	}
	swap_item(&pq[max],&pq[N-1]);

	return(pq[--N]);
}
/*
** This function joins two equal-size 2-power heaps into one. We need to change
** only a few links to combine two equal-sized 2-power heaps into onde 2-power
** heap that is twice the size of the original size. This pair_2_power_heap procedure
** is one key to the efficiency of the binomial queue algorithm.
*/
pqueue_link_t pair_2_power_heap(pqueue_link_t roota,pqueue_link_t rootb)
{
    if(compare_item(roota->item,rootb->item)>0) {
        rootb->right=roota->left;
        roota->left=rootb;

        return(roota);
    } else {
        roota->right=rootb->left;
        rootb->left=roota;

        return(rootb);
    }
}
int check_sorted_array(item_t *array,int left,int right)
{
	int i;

	for(i=left;i<right;i++){
		if(compare_item(array[i],array[i+1])>0)
			break;
	}

	if(i==right)
		return(1);

	return(0);
}
/*
** Partition function without using a break statement.
*/
int partition(item_t *array,int left,int right)
{
	item_t v=array[right];
	int i,j;

	for(i=left;compare_item(array[i],v)<0;i++)
			;
	for(j=right-1;j>=left && compare_item(array[j],v)>0;j--)
			;

	while(i<j){
		swap_item(&array[i],&array[j]);

		for(;compare_item(array[i],v)<0;i++)
			;
		for(;j>=left && compare_item(array[j],v)>0;j--)
			;
	}

	swap_item(&array[i],&array[right]);

	return(i);
}
示例#20
0
/*==========================================
 * Internal add-item function.
 *------------------------------------------
 */
static int storage_additem(struct map_session_data *sd,struct storage *stor,struct item *item_data,int amount)
{
	struct item_data *data;
	int i;

	if (sd->state.finalsave)
		return 1;

	if(item_data->nameid <= 0 || amount <= 0)
		return 1;
	
	data = itemdb_search(item_data->nameid);

	if (!itemdb_canstore(item_data, pc_isGM(sd)))
	{	//Check if item is storable. [Skotlex]
		clif_displaymessage (sd->fd, msg_txt(264));
		return 1;
	}
	
	if(itemdb_isstackable2(data)){ //Stackable
		for(i=0;i<MAX_STORAGE;i++){
			if( compare_item (&stor->storage_[i], item_data)) {
				if(amount > MAX_AMOUNT - stor->storage_[i].amount)
					return 1;
				stor->storage_[i].amount+=amount;
				clif_storageitemadded(sd,stor,i,amount);
				stor->dirty = 1;
				if(log_config.enable_logs&0x800)
					log_pick_pc(sd, "R", item_data->nameid, -amount, item_data);
				return 0;
			}
		}
	}
	//Add item
	for(i=0;i<MAX_STORAGE && stor->storage_[i].nameid;i++);
	
	if(i>=MAX_STORAGE)
		return 1;

	memcpy(&stor->storage_[i],item_data,sizeof(stor->storage_[0]));
	stor->storage_[i].amount=amount;
	stor->storage_amount++;
	clif_storageitemadded(sd,stor,i,amount);
	clif_updatestorageamount(sd,stor);
	stor->dirty = 1;
	if(log_config.enable_logs&0x800)
		log_pick_pc(sd, "R", item_data->nameid, -amount, item_data);
	return 0;
}
void sort_array(item_t *array,int left,int right)
{
	int i,j;
	item_t temp;

	for(i=left+1;i<=right;i++){
		temp=array[i];

		for(j=i-1;j>=left && compare_item(array[j],temp)>0;j--){
			array[j+1]=array[j];
		}
		
		array[j+1]=temp;
	}
}
static pqueue_link_t do_pqueue_del_max(pqueue_link_t r)
{
	item_t max_item;
	pqueue_link_t t;

	if(r->left==NULL && r->right==NULL){
		free(r);
		return(NULL);
	}

	if(compare_item(r->left->item,r->item)==0){
		r->left=do_pqueue_del_max(r->left);

		if(r->left==NULL){
			t=r->right;
			free(r);
			return(t);
		}
	}else{
		r->right=do_pqueue_del_max(r->right);

		if(r->right==NULL){
			t=r->left;
			free(r);
			return(t);
		}
	}

	copy_item(&max_item,&r->left->item);
	if(compare_item(r->right->item,max_item)>0){
		copy_item(&max_item,&r->right->item);
	}
	copy_item(&r->item,&max_item);

	return(r);
}
void selection_sort(item_t *array,int left,int right)
{
	int i,j;
	int min;

	for(i=left;i<right;i++){
		min=i;

		for(j=i+1;j<=right;j++){
			if(compare_item(array[j],array[min]) < 0){
				min=j;
			} 
		}

		swap_item(&array[i],&array[min]);
	}
}
void merge(item_t *a,int left,int middle,int right)
{
	int m=middle-left+1;
	int n=right-middle;
	item_t *aux;
	int i,j,k;

	if(m<=n){
		aux=malloc(m*sizeof(*aux));
		for(k=0;k<m;k++){
			aux[k]=a[middle-k];
		}
		i=m-1;
		j=middle+1;
	}else{
		aux=malloc(n*sizeof(*aux));
		for(k=0;k<n;k++){
			aux[k]=a[right-k];
		}
		for(j=right,k=middle;k>=left;k--){
			a[j--]=a[k];
		}
		i=n-1;
		j=right+1-m;
	}

	for(k=left;k<=right;k++){
		if(i==-1){
			a[k]=a[j++];
			continue;	
		}
		if(j==right+1){
			a[k]=aux[i--];
			continue;
		}

		if(compare_item(aux[i],a[j])<0){
			a[k]=aux[i--];
		}else{
			a[k]=a[j++];
		}
	}

	free(aux);
}
void merge_ab(item_t *c,item_t *a,int m,item_t *b,int n)
{
	int i,j,k;

	for(i=0,j=0,k=0;k<m+n;k++){
		if(i==m){
			c[k]=b[j++];
			continue;
		}
		if(j==n){
			c[k]=a[i++];
			continue;	
		}

		if(compare_item(a[i],b[j])<0){
			c[k]=a[i++];
		}else{
			c[k]=b[j++];
		}
	}
}
示例#26
0
/**
 * Attempt to add an item in guild storage, then refresh i
 * @param stor : guild_storage
 * @param item : item to add
 * @param amount : number of item to add
 * @return True : success, False : fail
 */
bool gstorage_additem2(struct guild_storage *stor, struct item* item, int amount)
{
	struct item_data *id;
	int i;

	nullpo_retr(false, stor);
	nullpo_retr(false, item);

	if (item->nameid == 0 || amount <= 0 || !(id = itemdb_exists(item->nameid)))
		return false;

	if (item->expire_time)
		return false;

	if (itemdb_isstackable2(id)) { //Stackable
		for (i = 0; i < MAX_GUILD_STORAGE; i++) {
			if (compare_item(&stor->items[i], item)) {
				//Set the amount, make it fit with max amount
				amount = min(amount, ((id->stack.guildstorage) ? id->stack.amount : MAX_AMOUNT) - stor->items[i].amount);
				if (amount != item->amount)
					ShowWarning("gstorage_additem2: Stack limit reached! Altered amount of item \""CL_WHITE"%s"CL_RESET"\" (%d). '"CL_WHITE"%d"CL_RESET"' -> '"CL_WHITE"%d"CL_RESET"'.\n", id->name, id->nameid, item->amount, amount);
				stor->items[i].amount += amount;
				stor->dirty = true;
				return true;
			}
		}
	}

	//Add the item
	for (i = 0; i < MAX_GUILD_STORAGE && stor->items[i].nameid; i++);
	if (i >= MAX_GUILD_STORAGE)
		return false;

	memcpy(&stor->items[i], item, sizeof(stor->items[0]));
	stor->items[i].amount = amount;
	stor->storage_amount++;
	stor->dirty = true;
	return true;
}
link_t merge_list(link_t heada,link_t headb)
{
	link_t c,t;
	link_t head=malloc(sizeof(*head));
	
	c=head;
	c->next=NULL;
	while(heada!=NULL && headb!=NULL){
		if(compare_item(heada->item,headb->item)<=0){
			t=heada;
			heada=t->next;
			t->next=NULL;

			c->next=t;
			c=t;
		}else{
			t=headb;
			headb=t->next;
			t->next=NULL;

			c->next=t;
			c=t;
		}
	}

	if(heada==NULL){
		c->next=headb;
	}else{
		c->next=heada;
	}

	t=head;
	head=head->next;
	free(t);

	return(head);
}
void heapify_bottom_up(item_t *heap,int k)
{
	for(;k>1 && compare_item(heap[k],heap[(k+1)/3])>0;k=(k+1)/3){
		swap_item(&heap[k],&heap[(k+1)/3]);
	}
}
static void heapify_bottom_up(item_t *heap,int k)
{
	for(;k>1 && compare_item(heap[k],heap[k/2])>0;k=k/2){
		swap_item(&heap[k],&heap[k/2]);
	}
}
/*
** The implementation of top-down quicksort of linked list pointed to 
** by head. First take out the first node from the list head, save as
** current. Partition the whole file into two sublists, one sublist save
** the elements smaller than current->item, pointed to by head1. Another
** sublist head2, holds the elements larger than or equal to current->item.
** Call recursively quicksort_list to sort each of the two sublists. Then
** merge them with current to make the whole list sorted.
*/
link_t quicksort_list(link_t head)
{
	link_t head1,tail1;
	link_t head2,tail2;
	link_t current,t;

	if(head==NULL || head->next==NULL){
		return(head);
	}

	current=head;
	head=head->next;
	current->next=NULL;
	
	/*
	** Partition the list into two subfiles.
	*/
	head1=tail1=NULL;
	head2=tail2=NULL;
	while(head!=NULL){	
		t=head;
		head=head->next;
		t->next=NULL;

		if(compare_item(t->item,current->item)<0){			
			if(tail1==NULL){
				head1=tail1=t;
			}else{
				tail1->next=t;
				tail1=t;
			}
		}else{				
			if(tail2==NULL){
				head2=tail2=t;
			}else{
				tail2->next=t;
				tail2=t;
			}
		}
	}

	head1=quicksort_list(head1);
	head2=quicksort_list(head2);

	/*
	** This is a point you may ignore. After the recursive quicksort_list
	** call above, the pointer tail1 may not point to the tail of the sublist
	** head1. So you should traverse the sublist head1 to make sure tail1 points
	** to its tail.
	*/
	for(tail1=head1;tail1!=NULL && tail1->next!=NULL;tail1=tail1->next);
		;

	/*
	** Merge the two subfiles head1, head2 with current.
	*/
	if(tail1 != NULL){
		tail1->next=current;
		current->next=head2;
		head=head1;
	}else{
		current->next=head2;
		head=current;
	}

	return(head);
}