Como classificar matriz de seqüências de caracteres que contém números positivos e negativos em c ++.?

8
String str[]={"-123","89","-10","456"};

stré uma matriz de cadeias, com cada cadeia no formato de um número inteiro, e você deve executar a classificação nessa matriz no O(n log n)tempo.

As cadeias em strpodem representar números inteiros positivos e negativos. O comprimento máximo dessas seqüências é 1024 caracteres.

Eu sei que uma solução desse problema é converter as seqüências de caracteres em números e compará-las além disso; existe alguma outra solução para esse problema?

Emp1
fonte
1024 caracteres - ie dígitos - você vai precisar muito grandes inteiros para ...
Aconcagua
@RSahu meu erro eu editei a pergunta agora #
211 Emp1
@Aconcaguan sim eu tenho biblioteca usada impulso multiprecision da CPP para isso
Emp1
Outra versão da idéia nas respostas que fazem comparações baseadas em cadeias: você pode particionar a lista em partes negativas e não negativas e, em seguida, usar duas funções de comparação mais simples para cada categoria para classificar as partes.
Aschepler # 23/19

Respostas:

13

Outra solução é implementar sua própria função de comparação:

  • Verifique o primeiro caractere das duas strings. Se um começa com um dígito e o outro começa com a -, a sequência que começa com - é o número menor.
  • Se ambas as cadeias começarem com um dígito, compare o comprimento das cadeias. A cadeia mais curta é o número menor. Se as duas seqüências tiverem o mesmo comprimento, faça uma comparação padrão.
  • Se ambas as strings começarem -, compare o comprimento das strings. A cadeia mais longa é o número menor. Se as duas seqüências tiverem o mesmo comprimento, faça uma comparação padrão, mas negue o resultado.
user3386109
fonte
Mas precisamos assumir que não há zeros à esquerda, eles teriam que ser ignorados ao considerar o comprimento das strings. Zeros negativos ( "-0"), se existirem, iria ficar ordenado na frente do que os normais, mas que parece-me muito bem ...
Aconcagua
3
Isso pode ser facilmente remediado. Use o índice de find_first_not_of("0")e passe-os para compare()sobrecarregar, o que pede pos / len para os dois lados da comparação.
quer
@Aconcagua Você está certo que eu não tinha considerado zeros à esquerda. Agradecemos ao @ TanveerBadar por fornecer a solução para isso. Quanto aos zeros negativos, classificá-los antes de zeros positivos também parece bom para mim.
User3386109
12

Aqui está um exemplo mínimo e potencialmente insuficiente (não lida com zeros à esquerda, espaços em branco etc.) que faz o que você deseja.

Os comentários explicam o que estão fazendo. :)

#include <algorithm>
#include <iostream>
#include <string>
#include <vector>

int main() {
  std::vector<std::string> strings = {
      "-1", "-1", "-20", "-4", "3", "0", "-0", "1", "20", "20", "44020",
  };

  // Assumes everything in "strings" has no whitespace in it.
  // Assumes everything in "strings" does not have leading zeroes.
  // Assumes everything in "strings" is an ascii representaion of an integer.
  // Assumes everything in "strings" is nonempty.
  std::sort(strings.begin(), strings.end(),
            [](const std::string &a, const std::string &b) {
              const bool a_is_negative = a[0] == '-';
              const bool b_is_negative = b[0] == '-';
              if (a_is_negative != b_is_negative) {
                // If they have different signs, then whichever is negative is
                // smaller.
                return a_is_negative;
              } else if (a.length() != b.length()) {
                // If they have the same sign, then whichever has more
                // characters is larger in magnitude. When the sign is negative,
                // the longer (more digits) number is "more negative". When
                // positive, the longer (more digits) number is "more positive".
                return (a.length() < b.length()) != a_is_negative;
              } else {
                // Otherwise a lexicographic comparison of "a" and "b" will
                // determine which string is larger in magnitude. Using the same
                // logic above, we account for the "negative vs. positive"
                // comparison.
                return (a < b) != a_is_negative;
              }
            });

  for (const auto &str : strings) {
    std::cout << str << " ";
  }
  std::cout << std::endl;
}
druckermanly
fonte
Ah, parece que a outra resposta descreve a mesma lógica que escrevi na minha resposta. Vou deixar isso como se fossem os primeiros. Eu usei código para expressar minha resposta, ele usou palavras. :)
druckermanly 23/10/19
A conversão explícita em bool não é necessária se você fornecer o tipo de retorno (à direita). Pessoalmente, consideraria isso mais legível. Você também pode usar em !=vez de ^ter o mesmo resultado para booleanos, mas o resultado já é booleano, novamente tornando a conversão explícita obsoleta (e adicionalmente os parênteses ...).
Aconcagua
1
Droga, você roubou minha (oportunidade de) resposta: Minha demo no coliru . ;-)
Scheff
Nice @Aconcagua - Eu estava sendo preguiçoso e escrevendo meus pensamentos, em vez de pensar em escrever código limpo. Adotei suas sugestões, pois elas não alteram materialmente a resposta.
Druckermanly 23/10/19
Enquanto o lambda pode ser bom, acho que o lambda é grande e faz sentido ter uma função dedicada ( less_as_number?).
Jarod42