zu finden Ich habe eine 3D-Matrix mat[100][100][100]
. Was ist der effiziente Weg, um eine Zeile mit den gleichen Elementen zu finden, die in mat[0][][], mat[1][][],....,mat[99][][]
erscheint? Ein einfacher Ansatz wäre der Vergleich jeder Zeile von mat[0][][]
mit allen Zeilen der restlichen 99 Matrizen, aber es wäre nicht sehr effizient (ich denke). Gibt es einen besseren Weg, es zu tun?Effiziente Möglichkeit, Zeilen mit gleichen Elementen in einer 3D-Matrix in C
Antwort
Um den Kommentar von @chux zu erweitern, besteht der erste Schritt darin, einen Hash-Wert für jede Zeile jeder Matrix zu berechnen. Das sind insgesamt 10000 Hashwerte. Die Ergebnisse sollten in einem Array von 10000 Strukturen gespeichert werden.
struct info
{
int m; // the matrix number
int row; // the row number
uint32_t hash; // the hash value for mat[m][row]
};
static struct info hashArray[10000];
Nachdem alle 10000 Einträge der hashArray
in Füllen sortiert das Array von Hash-Wert. Dann können Sie das Array einfach durchsuchen, um doppelte Hashwerte zu finden. Wenn Sie Dubletten finden, müssen Sie dies durch einen Vergleich der Zeilenelemente bestätigen.
Erstellen Sie eine inhaltsadressierbare Tabelle der ersten Werte in jeder Zeile. Dann gehe durch jede Zeile, nimm den ersten Wert und schaue auf den Tisch. Wenn die Suche mehrere Zeilen zurückgibt, sollten diese Zeilen auf Übereinstimmung überprüft werden. Die gesuchten Zeilen sollten zur Steigerung der Effizienz beibehalten werden, da die geprüften Zeilen nicht erneut überprüft werden müssen. Sie erhalten eine Liste mit identischen Zeilengruppierungen.
Diese Methode wird viel schneller sein als die Verwendung einer Hash-Tabelle. –
Und wie siehst du in der Tabelle nach? Dies würde immer noch das direkte Suchen (langsam) oder die Verwendung einer besser angepassten Struktur erfordern, z. eine Hash-Tabelle. – Olaf
Zuerst müssen Sie keine Hash-Tabelle erstellen, wodurch Sie viel Zeit sparen. Die inhaltsadressierbare Tabellensuche ist schneller, weil Sie nach einem Treffer für einen einzelnen Wert suchen. Dieser einzelne Treffer gibt Ihnen eine Liste aller Zeilen, die mit dem gleichen Wert beginnen. –
Ich fand endlich etwas Zeit, um den Inhalt adressierbaren Code zu schreiben. Es erweist sich als viel schneller als die Verwendung von Hash-Tabellen. Aber der Haken ist, dass der Code viel komplexer ist und das Programm WEISE mehr Speicher braucht. Meine abschließende Meinung ist, dass, wenn Sie nicht wirklich die zusätzliche Geschwindigkeit brauchen, bleiben Sie bei der Hash-Tabelle.
Einige Beispiele für Testläufe sind nachstehend aufgeführt. Das Argument für das Programm gibt die Anzahl der eindeutigen Zeilen an. Das Programm füllt den Rest mit zufällig ausgewählten vorhandenen Zeilen. Dann werden die Reihen gemischt. Das Programm sucht nach allen doppelten Zeilen und meldet die Anzahl der doppelten Zeilen und die Zeit, die es für Hash- und inhaltsadressierbare Tabellen benötigt.
[email protected] ~ $ cc -O2 cattest.c -o cattest
[email protected] ~ $ ./cattest 500
CAT Test 9500 0.0083
Hash Test 9500 0.0499
[email protected] ~ $ ./cattest 5000
CAT Test 5000 0.0195
Hash Test 5000 0.1477
[email protected] ~ $ ./cattest 9000
CAT Test 1000 0.0321
Hash Test 1000 0.1092
/* content addressable table vs hash table */
/* written by Bing H Bang */
/* I DONOT give permission to any snot-nosed students to copy my work and turn it in
as their own */
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <time.h>
#include <pthread.h>
#include <errno.h>
#include <string.h>
#include <sys/time.h>
#include <sys/sysinfo.h>
double etime()
{
struct timeval tv;
double dt, df;
gettimeofday(&tv, NULL);
dt = (double)(tv.tv_sec);
df = ((double)(tv.tv_usec))/1000000.0;
return(dt+df);
}
struct CAT_entry
{
unsigned fval;
unsigned short rows[10000];
unsigned short num;
unsigned short used;
struct CAT_entry *next;
} *CAT[256] = {NULL};
struct CAT_entry stmem[10000];
int stidx = 0;
unsigned dat[100][10000];
char map[10000];
unsigned hasht[10000];
#define highbit (1 << ((sizeof(unsigned)*8)-1))
unsigned
rotxor(unsigned sum, unsigned v)
{
if((sum & highbit) == 0)
return ((sum << 1)^v);
else
return (((sum << 1) | 1)^v);
}
unsigned
compute_hash(int y)
{
int x;
unsigned sum = 0;
for(x = 0; x < 100; ++x)
sum = rotxor(sum, dat[x][y]);
return sum;
}
void
mk_hasht()
{
int y;
for(y = 0; y < 10000; ++y)
hasht[y] = compute_hash(y);
}
clearmap()
{
memset((void *)map, 0, 10000);
}
comprow(int y, int yd)
{
int x;
for(x = 0; x < 100; ++x)
if(dat[x][y] != dat[x][yd])
return 0;
return 1;
}
struct CAT_entry **
srch_CAT(unsigned value)
{
struct CAT_entry **p = &(CAT[value&255]);
static struct CAT_entry *r = NULL;
while(*p != NULL)
{
if((*p)->fval == value)
break;
if((*p)->fval > value)
return &r;
else
p = &((*p)->next);
}
return p;
}
void
add_entry(int y, unsigned value)
{
struct CAT_entry **p = &(CAT[value&255]), *q;
while(*p != NULL)
{
q = *p;
if(q->fval == value)
{
q->rows[q->num] = y;
q->num++;
return;
}
if(q->fval > value)
break;
p = &(q->next);
}
q = *p;
//*p = malloc(sizeof(struct CAT_entry));
*p = &stmem[stidx++];
(*p)->next = q;
q = *p;
q->fval = value;
q->num = 0;
q->used = 0;
}
void
mk_CAT()
{
int x,y;
struct CAT_entry **p, *q;
for(y = 0; y < 10000; y++)
add_entry(y, dat[0][y]);
for(x=0; x < 256; ++x)
{
p = &(CAT[x]);
while(*p != NULL)
{
q = *p;
if(q->num == 0)
{
*p = q->next;
//free(q);
}
else
p = &(q->next);
}
}
}
void
gen_data(int npat)
{
int x, y, rnum, limit;
unsigned r;
srandom(time(NULL));
rnum = npat * 100;
for(y = 0; y < rnum; ++y)
dat[y%100][y/100] = random();
for(y = npat; y < 10000; ++y)
{
rnum = random() % npat;
for(x = 0; x < 100; ++x)
dat[x][y]=dat[x][rnum];
}
for(y = 0; y < 10000; ++y)
{
rnum = random() % 10000;
if(rnum == y)
continue;
for(x = 0; x < 100; ++x)
{
r = dat[x][y];
dat[x][y]=dat[x][rnum];
dat[x][rnum] = r;
}
}
}
int
do_CATtest()
{
int y, yd, count = 0, i;
struct CAT_entry **p, *q;
mk_CAT();
clearmap();
for(y = 0; y < 9999; ++y)
{
if(map[y] == 0)
{
map[y] = 1;
if(*(p = srch_CAT(dat[0][y])) != NULL)
{
for(q = *p, i = 0; i < q->num; ++i)
{
yd = q->rows[i];
if(map[yd] == 0)
{
if(comprow(y, yd))
{
map[yd] = 1;
++count;
q->used++;
}
}
}
if(q->num <= q->used)
*p = q->next;
}
}
}
return count;
}
int
do_hashtest()
{
unsigned h;
int x, y, yd, count = 0;
mk_hasht();
clearmap();
for(y = 0; y < 9999; ++y)
{
if(map[y] != 0)
continue;
map[y] = 1;
h = hasht[y];
for(yd = y+1; yd < 10000; ++yd)
{
if(map[yd] != 0)
continue;
if(h == hasht[yd])
if(comprow(y, yd))
{
map[yd] = 1;
++count;
}
}
}
return count;
}
main(int c, char *v[])
{
int npat = 0, count;
double t1, t2;
if(c == 2)
npat = atoi(v[1]);
if(npat <= 0 || npat >= 10000)
{
puts("input param error");
exit(1);
}
gen_data(npat);
npat = 10000 - npat;
t1 = etime();
if((count = do_CATtest()) != npat)
{
printf("CAT test error, %d matches found, not %d", count, npat);
exit(1);
}
t2 = etime();
printf("CAT Test %d %.4f\n", npat, t2-t1);
t1 = etime();
if((count = do_hashtest()) != npat)
{
printf("hash test error, %d matches found, not %d", count, npat);
exit(1);
}
t2 = etime();
printf("Hash Test %d %.4f\n", npat, t2-t1);
}
Die Hardware, die ich verwendete, war ein i7 4core 8thrd mit 4,4 GHz mit 4 GB mem. –
- 1. Effiziente Gruppierung von Elementen einer Liste
- 2. Effiziente Möglichkeit, alle Zeilen eines DataGridView in DB einzufügen?
- 3. R: zeige ALLE Zeilen mit doppelten Elementen in einer Spalte
- 4. Effiziente Möglichkeit, eine Zeichenkette zu token - C
- 5. Effiziente Bildmanipulation in C#
- 6. C# Linq, Suche nach gleichen Elementen in zwei Listen
- 7. Die effiziente Möglichkeit, eine Tabelle in GO
- 8. Effiziente Möglichkeit, umorderbare Artikel in einer Datenbank zu speichern
- 9. Effiziente Möglichkeit, in einer Zeichenfolge gespeicherte Codezeilen zu entfernen
- 10. MySQL Gruppe Zeilen mit der gleichen ID in einer Zeile
- 11. Auswählen von Elementen in einer Listbox mit C#
- 12. Quick-Sort-Algorithmus-Progression mit gleichen Elementen
- 13. Was ist eine einfache und effiziente Möglichkeit, Zeilen mit Zeitintervallüberlappungen in SQL zu finden?
- 14. Ausrichten von Elementen in der gleichen Zeile
- 15. Pythonic und effiziente Möglichkeit, eine elementweise "in" mit numpy
- 16. Den gleichen String allen Elementen in einer Liste voranstellen
- 17. Python: eine effiziente Möglichkeit, eine Liste mit einer Indexliste zu schneiden
- 18. Effiziente Möglichkeit, Wörterbuch (Hash) in Datei mit Python zu speichern?
- 19. Deserialize Xml mit leeren Elementen in C#
- 20. Format C++ Code mit entsprechenden Elementen über mehrere Zeilen
- 21. ein 4x4 3DMatrix in AS3 von Bildern verwendet Skew
- 22. Effiziente Möglichkeit zum Schreiben von Bestellinstanzen?
- 23. effiziente Möglichkeit, das Element in einem Wörterbuch in Python mit einer Schleife zu zählen
- 24. effiziente Möglichkeit, ungleiche Partitionen einer ganzen Zahl zu finden
- 25. Effiziente Abfrage von abstrakten Elementen mit WikiData Sparql
- 26. Beste/effiziente Möglichkeit, eine Base64-String zu gleichen Länge Chunks zu über HTTP in Android
- 27. Effiziente Methode zum Auffinden von Elementen in MATLAB-Matrix
- 28. Effiziente "Screenshots" einer Ansicht?
- 29. Effiziente Möglichkeit, FOLDER und DATEIEN zu entfernen
- 30. Dynamisches Hinzufügen von Elementen zu einer UI in C#
Erstellen Sie einen Hash-Code für jede Zeile und vergleichen Sie Hash. Wenn Hash übereinstimmt, dann vergleichen Sie Element für Element. – chux
Wenn ich es richtig verstanden habe, muss ich 100 Hash-Zeilen für die 1. Matrix erstellen und dann mit den restlichen Matrizen vergleichen. – husna