https://github.com/cran/sbioPN
Raw File
Tip revision: cb9bccd9cb9d3b21276ae307fb246f69810e9c43 authored by Roberto Bertolusso on 15 March 2014, 00:00:00 UTC
version 1.1.0
Tip revision: cb9bccd
quicksort.c
// -*- mode: C; c-indent-level: 2; c-basic-offset: 2; tab-width: 8 -*-
//
// Copyright (C) 2009-2014 Roberto Bertolusso and Marek Kimmel
//
// This file is part of sbioPN.
//
// sbioPN is free software: you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 2 of the License, or
// (at your option) any later version.
//
// sbioPN is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with sbioPN. If not, see <http://www.gnu.org/licenses/>.

// Based on quick sort algorithm found on Wikibooks:
// http://en.wikibooks.org/wiki/Algorithm_implementation/Sorting/Quicksort#C
// No licence specified. Considered public domain.
// Modifications performed on this file by Roberto Bertolusso released as 
// above copyright.


int partition(int* piIndex, int* piValue, int left, int right);
int findMedianOfMedians(int* piIndex, int* piValue, int left, int right);
int findMedianIndex(int* piIndex, int* piValue, int left, int right, int shift);
void swap(int* a, int* b);

//Quicksort the array
void quicksort(int* piIndex, int* piValue, int left, int right)
{
  if(left >= right)
    return;
  
  int index = partition(piIndex, piValue, left, right);
  quicksort(piIndex, piValue, left, index - 1);
  quicksort(piIndex, piValue, index + 1, right);
}

//Partition the piIndex into two halves and return the
//index about which the piIndex is partitioned
int partition(int* piIndex, int* piValue, int left, int right)
{
  //Makes the leftmost element a good pivot,
  //specifically the median of medians
  findMedianOfMedians(piIndex, piValue, left, right);
  int pivotIndex = left, pivotValue = piValue[piIndex[pivotIndex]], index = left, i;
  
  swap(&piIndex[pivotIndex], &piIndex[right]);
  for(i = left; i < right; i++)
    {
      if(piValue[piIndex[i]] > pivotValue)
        {
	  swap(&piIndex[i], &piIndex[index]);
	  index += 1;
        }
    }
  swap(&piIndex[right], &piIndex[index]);
  
  return index;
}

//Computes the median of each group of 5 elements and stores
//it as the first element of the group. Recursively does this
//till there is only one group and hence only one Median
int findMedianOfMedians(int* piIndex, int* piValue, int left, int right)
{
  if(left == right)
    return piValue[piIndex[left]];
  
  int i, shift = 1;
  while(shift <= (right - left))
    {
      for(i = left; i <= right; i+=shift*5)
        {
	  int endIndex = (i + shift*5 - 1 < right) ? i + shift*5 - 1 : right;
	  int medianIndex = findMedianIndex(piIndex, piValue, i, endIndex, shift);
	  
            swap(&piIndex[i], &piIndex[medianIndex]);
        }
      shift *= 5;
    }
  
  return piValue[piIndex[left]];
}

//Find the index of the Median of the elements
//of piIndex that occur at every "shift" positions.
int findMedianIndex(int* piIndex, int* piValue, int left, int right, int shift)
{
  int i, groups = (right - left)/shift + 1, k = left + groups/2*shift;
  for(i = left; i <= k; i+= shift)
    {
      int minIndex = i, minValue = piValue[piIndex[minIndex]], j;
      for(j = i; j <= right; j+=shift)
	if(piValue[piIndex[j]] > minValue)
	  {
	    minIndex = j;
	    minValue = piValue[piIndex[minIndex]];
	  }
      swap(&piIndex[i], &piIndex[minIndex]);
    }
  
  return k;
}

//Swap two integers
void swap(int* a, int* b)
{
  int temp;
  temp = *a;
  *a = *b;
  *b = temp;
}
back to top