Как ранжировать (отсортировать) массив по значению? * С изюминкой *
Я хотел бы отсортировать массив в порядке возрастания, используя C/C++
. Результатом является массив, содержащий индексы элементов. Каждый индекс соответствует положению элемента в отсортированном массиве.
Пример
Input: 1, 3, 4, 9, 6
Output: 1, 2, 3, 5, 4
Изменить: я использую процедуру сортировки оболочки. Индексы повторяющихся значений выбираются произвольно на основе того, какие повторяющиеся значения находятся первыми в исходном массиве.
Обновлять:
Несмотря на все мои усилия, мне не удалось реализовать алгоритм сортировки для массива указателей. Текущий пример не компилируется.
Может кто-нибудь сказать мне, что случилось?
Буду очень признателен за помощь!
void SortArray(int ** pArray, int ArrayLength)
{
int i, j, flag = 1; // set flag to 1 to begin initial pass
int * temp; // holding variable orig with no *
for (i = 1; (i <= ArrayLength) && flag; i++)
{
flag = 0;
for (j = 0; j < (ArrayLength - 1); j++)
{
if (*pArray[j + 1] > *pArray[j]) // ascending order simply changes to <
{
&temp = &pArray[j]; // swap elements
&pArray[j] = &pArray[j + 1]; //the problem lies somewhere in here
&pArray[j + 1] = &temp;
flag = 1; // indicates that a swap occurred.
}
}
}
};
Ответов (7)7
Поскольку вы используете C++, я бы сделал что-то вроде этого. SortIntPointers
Функция может быть любой алгоритм сортировки, важной частью является то , что он сортирует массив указателей , основываясь на int
том , что они указывают на. Как только это будет сделано, вы можете пройтись по массиву указателей и назначить их отсортированный индекс, который окажется в исходной позиции в исходном массиве.
int* intArray; // set somewhere else
int arrayLen; // set somewhere else
int** pintArray = new int*[arrayLen];
for(int i = 0; i < arrayLen; ++i)
{
pintArray[i] = &intArray[i];
}
// This function sorts the pointers according to the values they
// point to. In effect, it sorts intArray without losing the positional
// information.
SortIntPointers(pintArray, arrayLen);
// Dereference the pointers and assign their sorted position.
for(int i = 0; i < arrayLen; ++i)
{
*pintArray[i] = i;
}
Надеюсь, это достаточно ясно.
Параллельная сортировка вектора с использованием boost :: lambda ...
std::vector<int> intVector;
std::vector<int> rank;
// set up values according to your example...
intVector.push_back( 1 );
intVector.push_back( 3 );
intVector.push_back( 4 );
intVector.push_back( 9 );
intVector.push_back( 6 );
for( int i = 0; i < intVector.size(); ++i )
{
rank.push_back( i );
}
using namespace boost::lambda;
std::sort(
rank.begin(), rank.end(),
var( intVector )[ _1 ] < var( intVector )[ _2 ]
);
//... and because you wanted to replace the values of the original with
// their rank
intVector = rank;
Примечание: я использовал vectorS вместо массивов, потому что это яснее / проще, также я использовал индексирование в стиле C, которое начинает отсчет с 0, а не с 1.
Это решение на языке c
#include <stdio.h>
void swap(int *xp, int *yp) {
int temp = *xp;
*xp = *yp;
*yp = temp;
}
// A function to implement bubble sort
void bubbleSort(int arr[], int n) {
int i, j;
for (i = 0; i < n - 1; i++)
// Last i elements are already in place
for (j = 0; j < n - i - 1; j++)
if (arr[j] > arr[j + 1])
swap(&arr[j], &arr[j + 1]);
}
/* Function to print an array */
void printArray(int arr[], int size) {
for (int i = 0; i < size; i++)
printf("%d ", arr[i]);
printf("\n");
}
int main() {
int arr[] = {64, 34, 25, 12, 22, 11, 98};
int arr_original[] = {64, 34, 25, 12, 22, 11, 98};
int rank[7];
int n = sizeof(arr) / sizeof(arr[0]);
bubbleSort(arr, n);
printf("Sorted array: \n");
printArray(arr, n);
//PLACE RANK
//look for location of number in original array
//place the location in rank array
int counter = 1;
for (int k = 0; k < n; k++){
for (int i = 0; i < n; i++){
printf("Checking..%d\n", i);
if (arr_original[i] == arr[k]){
rank[i] = counter;
counter++;
printf("Found..%d\n", i);
}
}
}
printf("Original array: \n");
printArray(arr_original, n);
printf("Rank array: \n");
printArray(rank, n);
return 0;
}
создать новый массив с увеличивающимися значениями от 0 до n-1 (где n - длина массива, который вы хотите отсортировать). Затем отсортируйте новый массив на основе значений в старом массиве, проиндексированных значениями в новом массиве.
Например, если вы используете пузырьковую сортировку (легко объяснить), то вместо сравнения значений в новом массиве вы сравниваете значения в старом массиве в позиции, проиндексированной значением в новом массиве:
function bubbleRank(A){
var B = new Array();
for(var i=0; i<A.length; i++){
B[i] = i;
}
do{
swapped = false;
for(var i=0; i<A.length; i++){
if(A[B[i]] > A[B[i+1]]){
var temp = B[i];
B[i] = B[i+1];
B[i+1] = temp;
swapped = true;
}
}
}while(swapped);
return B;
}
Что ж, есть тривиальное решение n ^ 2.
В питоне:
newArray = sorted(oldArray)
blankArray = [0] * len(oldArray)
for i in xrange(len(newArray)):
dex = oldArray.index(newArray[i])
blankArray[dex] = i
В зависимости от размера вашего списка это может сработать. Если ваш список очень длинный, вам нужно будет провести странную сортировку параллельных массивов, которая не выглядит забавной и является быстрым способом внести дополнительные ошибки в ваш код.
Также обратите внимание, что приведенный выше код принимает уникальные значения в oldArray. Если это не так, вам нужно будет выполнить некоторую пост-обработку, чтобы решить связанные значения.
Хорошо, вот моя попытка на C++
#include <iostream>
#include <algorithm>
struct mycomparison
{
bool operator() (int* lhs, int* rhs) {return (*lhs) < (*rhs);}
};
int main(int argc, char* argv[])
{
int myarray[] = {1, 3, 6, 2, 4, 9, 5, 12, 10};
const size_t size = sizeof(myarray) / sizeof(myarray[0]);
int *arrayofpointers[size];
for(int i = 0; i < size; ++i)
{
arrayofpointers[i] = myarray + i;
}
std::sort(arrayofpointers, arrayofpointers + size, mycomparison());
for(int i = 0; i < size; ++i)
{
*arrayofpointers[i] = i + 1;
}
for(int i = 0; i < size; ++i)
{
std::cout << myarray[i] << " ";
}
std::cout << std::endl;
return 0;
}