148 lines
4.1 KiB
C++
148 lines
4.1 KiB
C++
#include<stdio.h>
|
|
|
|
// Ein Listenelement
|
|
struct IntListElem {
|
|
IntListElem* next; // Zeiger auf nächstes Element
|
|
int value; // Daten zu diesem Element
|
|
} ;
|
|
|
|
// Eine Liste
|
|
struct IntList {
|
|
int count; // Anzahl Elemente in der Liste
|
|
IntListElem* first; // Zeiger auf erstes Element der Liste
|
|
} ;
|
|
|
|
|
|
// Initialisiere eine Listenstruktur
|
|
void empty_list (IntList* l)
|
|
{
|
|
l->first = 0; // 0 ist keine gueltige Adresse: Liste ist leer
|
|
l->count = 0;
|
|
}
|
|
|
|
// Fuege ein Element nach einem gegebenem ein
|
|
void insert_in_list (IntList* list, IntListElem* where, IntListElem* ins)
|
|
{
|
|
if (where==0) // fuege am Anfang ein
|
|
{
|
|
ins->next = list->first;
|
|
list->first = ins;
|
|
list->count = list->count + 1;
|
|
}
|
|
else // fuege nach where ein
|
|
{
|
|
ins->next = where->next;
|
|
where->next = ins;
|
|
list->count = list->count + 1;
|
|
}
|
|
}
|
|
|
|
// Entferne ein Element nach einem gegebenem
|
|
// Liefere das entfernte Element zurueck
|
|
IntListElem* remove_from_list (IntList* list, IntListElem* where)
|
|
{
|
|
IntListElem* p; // das entfernte Element
|
|
|
|
// where==0 dann entferne erstes Element
|
|
if (where==0)
|
|
{
|
|
p = list->first;
|
|
if (p!=0)
|
|
{
|
|
list->first = p->next;
|
|
list->count = list->count - 1;
|
|
}
|
|
return p;
|
|
}
|
|
|
|
// entferne Element nach where
|
|
p = where->next;
|
|
if (p!=0)
|
|
{
|
|
where->next = p->next;
|
|
list->count = list->count - 1;
|
|
}
|
|
return p;
|
|
}
|
|
|
|
// creates a cyclic list with a linear part of k elements
|
|
// and a cyclic part of n elements
|
|
IntList* make_cyclic_list(int k, int n) {
|
|
IntList* list = new IntList();
|
|
empty_list(list);
|
|
|
|
// create cyclic list of length n
|
|
if (n > 0) {
|
|
// create last element of list (its inserted first)
|
|
IntListElem* last = new IntListElem();
|
|
last->value = n+k;
|
|
// insert the (now first, but later) last element into the list
|
|
insert_in_list(list, 0, last);
|
|
// now iterate over every other number
|
|
for (int i = n+k-1; i > k; i--) {
|
|
// and create a new list element
|
|
IntListElem* elem = new IntListElem();
|
|
// with the given number
|
|
elem->value = i;
|
|
// and add it to the list in the very beginning
|
|
insert_in_list(list, 0, elem);
|
|
}
|
|
// make the last element reference the first one
|
|
last->next = list->first;
|
|
}
|
|
IntListElem* firstCyclic = list->first;
|
|
// add a linear part
|
|
for (int i = k; i > 0; i--) {
|
|
// create new list element
|
|
IntListElem* elem = new IntListElem();
|
|
// with given value
|
|
elem->value = i;
|
|
// and insert in the very beginning
|
|
insert_in_list(list, 0, elem);
|
|
// if it is the (first inserted, but later) last element of the linear
|
|
// part, make it point to the first cyclic element
|
|
if (i == k) {
|
|
elem->next = firstCyclic;
|
|
}
|
|
}
|
|
return list;
|
|
}
|
|
|
|
// Hase-Igel Algorithmus zum Finden eines Zyklus in einer Liste
|
|
int hase_igel(IntList* list) {
|
|
// create igel, that goes on by one
|
|
IntListElem* igel = list->first;
|
|
// create hase that always skips one element
|
|
IntListElem* hase = list->first;
|
|
// count the number of steps needed
|
|
int n = 0;
|
|
// this is the first occurence of a cycle
|
|
int first = 0;
|
|
// move forward with igel and hase until we hit the end of the list
|
|
while (igel != 0 && hase != 0) {
|
|
// increment igel and hase
|
|
igel = igel->next;
|
|
hase = hase->next->next;
|
|
// increment the step counter
|
|
n++;
|
|
// if igel and hase point to the same element, there
|
|
// has to be a cycle
|
|
if (igel == hase) {
|
|
// save the first occurence
|
|
if (first == 0) {
|
|
first = n;
|
|
// if we find the second one, return the difference
|
|
} else {
|
|
return n - first;
|
|
}
|
|
}
|
|
}
|
|
// if there is an end, there can't be a cycle
|
|
return 0;
|
|
}
|
|
|
|
int main() {
|
|
IntList* list = make_cyclic_list(10, 0);
|
|
printf("Laenge des Zyklus: %d\n", hase_igel(list));
|
|
}
|