Seite 1 von 3

Die nächstkleinste freie Zahl in einer Liste finden

Verfasst: 11.06.2014 08:49
von Bisonte
Hallo.

Ich habe eine Liste : Nummer.i()
In dieser Liste sind zufällige Zahlen, wobei keine der Zahlen doppelt sein darf.

wie kann ich ermitteln welche nächste kleinstmögliche Zahl ich der Liste hinzufügen kann ?

Bsp: Wie bekomme ich die 2 heraus ?

Code: Alles auswählen

NewList Nummer.i()

AddElement(Nummer()) : Nummer() = 4
AddElement(Nummer()) : Nummer() = 3
AddElement(Nummer()) : Nummer() = 1
AddElement(Nummer()) : Nummer() = 7
AddElement(Nummer()) : Nummer() = 5

SortList(Nummer(), #PB_Sort_Ascending)

ForEach Nummer()
  Debug Nummer()
Next
Ich seh den Wald bestimmt vor lauter Bäumen nicht ;)

Re: Die nächstkleinste freie Zahl in einer Liste finden

Verfasst: 11.06.2014 10:09
von matbal
Überprüfe einfach, ob nächstes Element um 1 größer ist

Code: Alles auswählen

Procedure GetNumber(List Nummer())
   Protected n
   
   ForEach Nummer()
      n + 1
      If Nummer() <> n
         ProcedureReturn n
      EndIf
   Next 
   
   ProcedureReturn n + 1
   
EndProcedure


Re: Die nächstkleinste freie Zahl in einer Liste finden

Verfasst: 11.06.2014 13:21
von Chimorin
Das geht ja nicht, weil die Zahlen zufällig sind.

Mir fällt da nur ein:
Liste sortieren und DANN nachschauen, wo eine Zahl fehlt. Vom unteren Rand aus.

Re: Die nächstkleinste freie Zahl in einer Liste finden

Verfasst: 11.06.2014 13:32
von NicTheQuick
Wie viele Zahlen werden es denn später so ungefähr sein? Und wie läuft das ganze überhaupt ab? Sind am Anfang alle Zahlen da, dann werden welche heraus genommen und dann willst du erst wissen, welche die kleinste ist, die fehlt? Oder bekommst du von Anfang an diese unsortierte Liste und willst dann die kleinste fehlende Zahl finden? Und gibt es nach oben Grenzen oder nicht? Wenn es nach oben nämlich keine Grenzen gibt und außerdem alle Zahlen Ganzzahlen sind, dann würde sich ein Radixsort anbieten. Und für den ersten Fall könnte man auch einen Heap nutzen.

Re: Die nächstkleinste freie Zahl in einer Liste finden

Verfasst: 11.06.2014 13:43
von Bisonte
Sinn und Zweck der Übung ist es eine Art Objektverwaltung wie PB zu realisieren. Also wenn ein Objekt mit
#PB_Any erstellt wird, eine freie Nummer zu bekommen. Es wird also laufend etwas hinzugefügt und entfernt. deswegen auch am besten
immer die kleinste Nummer.... Heisst natürlich aber auch, das da keine doppelten Nummern existieren dürfen.


(Wollte ich dann mit einer Map() realisieren)

Re: Die nächstkleinste freie Zahl in einer Liste finden

Verfasst: 11.06.2014 14:20
von NicTheQuick
Achso, okay.

Ich hatte da auch mal sowas gemacht. Schon Ewigkeiten her. Ich hab das mal eben umgebaut auf Module:

Code: Alles auswählen

DeclareModule ID
	Structure IDList
		count.i
		List freeIDs.i()
	EndStructure
	Global NewMap IDs.IDList()
	
	Declare.i newID(type.s)
	Declare.i freeID(type.s, id.i)
EndDeclareModule

Module ID
	Procedure.i newID(type.s)
		Protected *idList.IDList = FindMapElement(IDs(), type)
		Protected tmp.i
		
		If (*idList)
			If (FirstElement(*idList\freeIDs()))
				tmp = *idList\freeIDs()
				DeleteElement(*idList\freeIDs())
				ProcedureReturn tmp
			Else
				*idList\count + 1
				ProcedureReturn *idList\count - 1
			EndIf
		Else
			*idList = AddMapElement(IDs(), type, #PB_Map_NoElementCheck)
			If (Not *idList)
				ProcedureReturn -1
			EndIf
			*idList\count + 1
			ProcedureReturn 0
		EndIf
	EndProcedure
	
	Procedure.i freeID(type.s, id.i)
		Protected *idList.IDList = FindMapElement(IDs(), type)
		
		If (Not *idList)
			ProcedureReturn #False
		EndIf
		
		With *idList
			
			If (id = \count - 1)
				\count - 1
			Else
				If AddElement(\freeIDs())
					\freeIDs() = id
					SortList(\freeIDs(), #PB_Sort_Ascending)
					
					;Räume die Liste auf
					While LastElement(\freeIDs())
						If (\freeIDs() = \count - 1)
							DeleteElement(\freeIDs())
							\count - 1
						Else
							Break
						EndIf
					Wend
				EndIf
			EndIf
			
		EndWith
		
		ProcedureReturn #True
	EndProcedure
EndModule


Debug ID::newID("window")
Debug ID::newID("gadget")
Debug ID::newID("gadget")
Debug ID::newID("gadget")
Debug ID::newID("gadget")

ID::freeID("gadget", 2)
ID::freeID("gadget", 1)

Debug ID::newID("gadget")
Debug ID::newID("gadget")
Ich speichere eigentlich einfach nur die wieder frei gegebenen freien IDs und nimm die wieder aus der Liste heraus, wenn man eine neue braucht. Das 'SortList()' kann man mit einem Heap etwas effizienter machen, aber ob sich das lohnt, kommt auf das Einsatzgebiet an.

///Edit:
Hab noch eine kleine Aufräumroutine eingebaut, die sicher stellt, dass die interne 'freeIDs()'-Liste immer so klein wie möglich ist.

Re: Die nächstkleinste freie Zahl in einer Liste finden

Verfasst: 11.06.2014 16:08
von DrShrek
Nimm doch einfach eine Map + etwas Logik beim generieren des Keys: JJJJMMDDHHMMSSmmm => das sollte fast schon sicher sein.

Re: Die nächstkleinste freie Zahl in einer Liste finden

Verfasst: 11.06.2014 16:20
von Derren
Ich würde das mit 2 Listen machen. Eine kleine Zahl wird ja nur frei wenn du etwas löscht. Ansonsten stapelst du ja immer oben drauf, musst also nur die zuletzt hinzugefügte Zahl speichern.
Wenn du jetzt was löscht, speicherst du die Zahl in einer zweiten Liste, welche sortiert ist (diese Liste sollte ja jederzeit ziemlich klein sein, weshalb das sortieren relativ schnell geht).

Re: Die nächstkleinste freie Zahl in einer Liste finden

Verfasst: 11.06.2014 17:48
von Chimorin
Derrens Idee finde ich super :allright:

Re: Die nächstkleinste freie Zahl in einer Liste finden

Verfasst: 11.06.2014 17:51
von Derren
Hab mir den Code nicht genau angeschaut, aber ich glaube Nic's Code macht genau das, dem Kommentar unter dem Code nach zu urteilen.