so here is the code that gives me headache :
void newCopy(ListNode* n, List* l) {
if (n == NULL) { return; }
if (n->next == NULL) {
push(n->data, l);
return;
}
else {
newCopy(n->next, l);
push(n->data, l);
return;
}
}
As you can see if n == NULL then the function is supposed to end but you see it coming : it's not ending the function.
I'm getting "read access violation" on if (n->next == NULL) because n is NULL.
I also get error randomly on other functions, all related to memory access.
The function you should investigate is State* progDynState(List* taskList) because everything is done here.
I know some people want minimal reproductible exemple, I can't produce one because everything is used, so here is the entire code.
File Main :
#include "Tools.h"
#include <time.h>
int main()
{
/* initialize random seed: */
srand(time(NULL));
//List creation
//
List* taskList = consList();
Task* task = NULL;
//Task number
/*int n = (rand() % 14 + 4);
//Generate random tasks
for(int i = 1; i <= n; i++) {
task = consTask(i + (rand() % 10 + 1) - rand() % 5 , i + (rand() % 10 + 1) - rand() % 5);
push(task, taskList);
}*/
for (int i = 1; i <= 4; i++) {
task = consTask(i,i);
push(task, taskList);
}
std::cout << "Display origin : \n" << listToString_Task(taskList) << " \n";
//--- CLASSIC ---
//SOLVE PROBLEM - PROG DYN STATE
State* opt = progDynState(taskList);
//--- FPTAS ---
double sigma = 1; //TO CHANGE DEPENDING ON PRECISION
//Get deltas
double deltaD = findDeltaD(taskList, sigma);
double deltaL = findDeltaL(taskList, sigma);
//Rounded values
List* rL = rounding(taskList, deltaD, deltaL);
//SOLVE PROBLEM - PROG DYN STATE
std::cout << "ROUNDED OPT : \n";
State* roundedOpt = progDynState(rL);
//Transpose the solution on the original instance
List* pair = createListTaskPair(taskList, rL);
State* FPTASopt = transpose(roundedOpt, pair);
std::cout << "Optimal Solution 2 : \n" << stateToString(FPTASopt) << " \n";
}
File ProblemElement.h
#pragma once
#include <string>
#include <iostream>
#include <sstream>
#include <cmath>
#include <algorithm>
#ifndef PROBLEM
#define PROBLEM
// -----------------------------------------------------//
// ------------------ LIST ------------------//
// -----------------------------------------------------//
typedef struct ListNode ListNode;
struct ListNode
{
void *data;
struct ListNode *next;
};
typedef struct List List;
struct List
{
struct ListNode *head;
struct ListNode *tail;
int size;
};
//Initialize a list's value
void empty(List* l);
//Create an empty list
List* consList() //allocate and initialize to NULL values
{
List* list = (List*)calloc(1,sizeof(List*));
while(list == NULL) list = (List*)calloc(1,sizeof(List*));
empty(list);
return list;
}
//Add data to the head of the list
void push(void *data, List *list)
{
if (list == NULL) return;
if (data == NULL) return;
ListNode *newNode = (ListNode*)calloc(1,sizeof(ListNode));
newNode->data = data;
newNode->next = list->head;
if (list->head == NULL) //the list is empty
{
list->head = newNode;
list->tail = list->head;
}
else
{
list->head = newNode;
}
list->size++;
}
//Add data to the tail of the list
void append(void *data, List *list)
{
if (list == NULL) return;
if (data == NULL) return;
ListNode *newNode = (ListNode*)calloc(1,sizeof(ListNode));
newNode->data = data;
newNode->next = NULL;
if (list->head == NULL) //the list is empty
{
list->head = newNode;
list->tail = list->head;
}
else
{
list->tail->next = newNode;
list->tail = newNode;
}
list->size++;
}
//Remove first element
void pop(List* l) {
if (l == NULL) return;
if (l->head->next == NULL) {
free(l->head);
empty(l);
}
else {
ListNode* ln = l->head;
l->head = ln->next;
free(ln);
}
l->size--;
}
void endPop(List* l) {
if (l == NULL) return;
if (l->head->next == NULL) {
pop(l);
}
else {
ListNode* curr = l->head;
ListNode* prev = NULL;
while (curr != l->tail) {
prev = curr;
curr = curr->next;
}
free(l->tail);
prev->next = NULL;
l->size--;
}
}
//Remove element contening data
void removeData(void *data, List *list){
if (data == NULL) return;
if (list == NULL) return;
if (list->head == NULL) return;
//Head to be removed
if (data == list->head->data) {
pop(list);
return;
}
//Tail to be removed
if (data == list->tail->data){
endPop(list);
return;
}
//Other node
ListNode* curr = list->head;
ListNode* prev = NULL;
while (curr->data != data) {
prev = curr;
curr = curr->next;
}
prev->next = curr->next;
free(curr);
list->size--;
}
//Make l1's head and tail point to l2's
void assignTo(List* l1, List* l2) {
if (l1 == NULL) return;
if (l2 == NULL) return;
l1->head = l2->head;
l1->tail = l2->tail;
l1->size = l2->size;
}
//Initialize a list's value
void empty(List* l) {
if (l == NULL) return;
l->head = NULL;
l->tail = NULL;
l->size = 0;
}
//Free memory of all nodes
void freeNodes(List* l) {
if (l == NULL) return;
if (l->head->next == NULL) {
pop(l);
return;
}
while (l->head != NULL) {
pop(l);
}
}
//Create a copy of n in l with new elements, shared data pointer
void newCopy(ListNode* n, List* l) {
if (n == NULL) { return; }
if (n->next == NULL) {
push(n->data, l);
return;
}
else {
newCopy(n->next, l);
push(n->data, l);
return;
}
}
// -----------------------------------------------------//
// ------------------ STATE ------------------//
// -----------------------------------------------------//
typedef struct State State;
struct State
{
double _eOe; //End of execution
double _t; //Start of next task on first machine
//First machine
List* _task1;
//Second machine
List* _task2;
};
//Constructor of State
State* consState(double eOe = 0, double t = 0) {
State* s = (State*)malloc(sizeof(State));
s->_t = t;
s->_eOe = eOe;
s->_task1 = consList();
s->_task2 = consList();
return s;
}
//Describe a list of task
std::string listToString_Task(List* tL);
//Describe a state
std::string stateToString(struct State * s) {
std::string st;
st += "State : ( t = " + std::to_string(s->_t) + " , eOe = " + std::to_string(s->_eOe) + " ) \n";
st += "Task on machine 1 : (" + listToString_Task(s->_task1) + ") \n";
st += "Task on machine 2 : (" + listToString_Task(s->_task2) + ") \n";
st += "End of execution : " + std::to_string(s->_eOe);
return st;
}
// -----------------------------------------------------//
// ------------------ TASK ------------------//
// -----------------------------------------------------//
typedef struct Task Task;
struct Task
{
double _dur;//task duration
double _lat;//task latency
};
//Constructor of Task
Task* consTask(double dur = 0, double lat = 0) {
Task* t = (Task*)malloc(sizeof(Task));
t->_dur = dur;
t->_lat = lat;
return t;
}
//Describe a task
std::string taskToString(struct Task * t) {
return "Task : ( _dur = " + std::to_string(t->_dur) + " , _lat = " + std::to_string(t->_lat) + " )";
}
// -----------------------------------------------------//
// ------------------ PAIR : TASK | ROUNDED TASK ------------------//
// -----------------------------------------------------//
typedef struct TaskPair TaskPair;
struct TaskPair
{
Task* _origin;//original Tasks
Task* _rounded;//rounded Tasks
};
//Constructor of TaskPair
TaskPair* consTaskPair(Task* origin, Task* rounded) {
TaskPair* t = (TaskPair*)malloc(sizeof(TaskPair));
t->_origin = origin;
t->_rounded = rounded;
return t;
}
//Describe a task
std::string taskPairToString(struct TaskPair * t) {
return "TaskPair : ( origin = " + taskToString(t->_origin) + " , rounded = " + taskToString(t->_rounded) + " )";
}
#endif // !PROBLEM
File Tools.h
#pragma once
#include "ProblemElements.h"
#ifndef TOOLS
#define TOOLS
// -----------------------------------------------------//
// ------------------ GENERAL TOOLS ------------------//
// -----------------------------------------------------//
std::string listToString_State(List* sL);
//Keeps only the best state of a PElement<State>.
List* keepBestState(List* sL) {
if (sL == NULL) return NULL;
if (sL->head->next == NULL) return sL;
std::cout << "Size : " << std::to_string(sL->size) << "\n";
std::cout << "sL : " << listToString_State(sL) << "\n";
State* currS = (State*)sL->head->data;
State* nextS = (State*)sL->head->next->data;
//Current element is better, removing following element | Following element is better, removing current element
if(currS->_eOe <= nextS->_eOe)
removeData(sL->head->next->data, sL);
else
pop(sL);
return keepBestState(sL);
}
//Split List in two half
void splitList(List* sL, List* half2) {
//Size of list to sort
int listSize = sL->size;
//Half of size list
if (listSize % 2 == 0) {
listSize = listSize / 2;
sL->size = listSize;
half2->size = listSize;
}
else {
listSize = (listSize + 1) / 2;
sL->size = listSize;
half2->size = listSize-1;
}
ListNode* front = sL->head;
for (int i = 1; i < listSize; i++)
front = front->next;
//Start 2 half
half2->head = front->next;
//Cut main list
front->next = NULL;
//Set tails
half2->tail = sL->tail;
sL->tail = front;
}
//Merge two list of States sorted in increasing order into one list which is in increasing order || Comparing _t value
ListNode* sortedMerge_State(ListNode* a, ListNode* b)
{
ListNode* result = NULL;
//BASE CASE
if (a == NULL)
return(b);
if (b == NULL)
return(a);
State* state1 = (State*)a->data;
State* state2 = (State*)b->data;
//Sort current value
if (state1->_t <= state2->_t)
{
result = a;
result->next = sortedMerge_State(a->next, b);
}
else
{
result = b;
result->next = sortedMerge_State(a, b->next);
}
return result;
}//Merge two list of States sorted in increasing order into one list which is in increasing order
//Merge two list of Tasks sorted in decreasing order into one list which is in decreasing order || Comparing _lat value
ListNode* sortedMerge_Task(ListNode* a, ListNode* b)
{
ListNode* result = NULL;
if (a == NULL)
return(b);
if (b == NULL)
return(a);
Task* task1 = (Task*)a->data;
Task* task2 = (Task*)b->data;
if (task1->_lat >= task2->_lat)
{
result = a;
result->next = sortedMerge_Task(a->next, b);
}
else
{
result = b;
result->next = sortedMerge_Task(a, b->next);
}
return result;
}
//Sort a list of States by increasing order || Comparing _t value
void fusionSort_State(List* sL) {
ListNode* head = sL->head;
List* half2 = consList();
if (head == NULL || head->next == NULL) return;
//Cut list in two half
splitList(sL, half2);
//Recursiv call || Sort the two half
fusionSort_State(sL);
fusionSort_State(half2);
//Merge and sort the sorted halfs
sL->head = sortedMerge_State(sL->head,half2->head);
sL->size = sL->size + half2->size;
for (head = sL->head; head->next != NULL; head = head->next);
sL->tail = head;
}
//Sort a list of Tasks by decreasing order || Comparing _lat value
void fusionSort_Task(List* sL) {
ListNode* head = sL->head;
List* half2 = consList();
if (head == NULL || head->next == NULL) return;
splitList(sL, half2);
fusionSort_Task(sL);
fusionSort_Task(half2);
sL->head = sortedMerge_Task(sL->head,half2->head);
sL->size = sL->size + half2->size;
for (head = sL->head; head->next != NULL; head = head->next);
sL->tail = head;
}
//Removes multiple occurence t
List* removeMultOcc(List* sL) {
if (sL == NULL) return NULL;
if (sL->head == NULL) return NULL;
if (sL->size == 1) return sL;
fusionSort_State(sL);
ListNode* curr = sL->head;
State* state1 = NULL;
State* state2 = NULL;
//SIMILAR t
while (curr != NULL && curr->next != NULL) {
state1 = (State*)curr->data;
state2 = (State*)curr->next->data;
//Current and following element considered as duplicate
if (state1->_t == state2->_t) {
//Remove bad duplicate
if (state1->_eOe <= state2->_eOe)
removeData(state2, sL);
else
removeData(state1, sL);
}
//Next duplicate group
else curr = curr->next;
}
return sL;
}
//Summ of _dur
double sumDurTaskList(ListNode* tL) {
if (tL == NULL) return NULL;
Task* task = (Task*)tL->data;
if (tL->next == NULL) return task->_dur;
return task->_dur + sumDurTaskList(tL->next);
}
//Describe a list of state
std::string listToString_State(List* sL) {
if (sL == NULL) return "List : [ NOT INITIALIZED ].\n";
if (sL->size == 0) return "List : [ EMPTY ].\n";
if (sL->size == 1) return "START OF LIST OF STATE : [ " + stateToString((State*)sL->head->data) + " ]. END OF LIST OF STATE\n";
ListNode* curr = sL->head;
std::string st = "START OF LIST OF STATE : [\n ";
while (curr != NULL) {
st += stateToString((State*)curr->data);
if (curr->next != NULL) st += "\n \n";
curr = curr->next;
}
return st + " \n]. END OF LIST OF STATE \n \n \n";
}
//Describe a list of task
std::string listToString_Task(List* tL) {
if (tL == NULL) return "List : [ NOT INITIALIZED ].\n";
if (tL->size == 0) return "List : [ EMPTY ].\n";
if (tL->size == 1) return "START OF LIST OF TASK : [ " + taskToString((Task*)tL->head->data) + " ]. END OF LIST OF TASK\n";
ListNode* curr = tL->head;
std::string st = "START OF LIST OF TASK : [ \n";
while (curr != NULL) {
st += taskToString((Task*)curr->data);
if (curr->next != NULL) st += "\n";
curr = curr->next;
}
return st + "\n]. END OF LIST OF TASK\n \n \n";
}
//Describe a list of taskpair
std::string listToString_TaskPair(List* tL) {
if (tL == NULL) return "List : [ NOT INITIALIZED ].\n";
if (tL->size == 0) return "List : [ EMPTY ].\n";
if (tL->size == 1) return "START OF LIST OF TASKPAIR : [ " + taskPairToString((TaskPair*)tL->head->data) + " ]. END OF LIST OF TASKPAIR\n";
ListNode* curr = tL->head;
std::string st = "START OF LIST OF TASKPAIR : [ \n";
while (curr != NULL) {
st += taskPairToString((TaskPair*)curr->data);
if (curr->next != NULL) st += "\n";
curr = curr->next;
}
return st + "\n]. END OF LIST OF TASKPAIR\n \n \n";
}
// -----------------------------------------------------//
// ------------------ FPTAS TOOLS ------------------//
// -----------------------------------------------------//
//All Task on machine 2, Tasks sorted by decreasing order of latency
State* heuristic(List* l) {
//Copy list to not modify original instance
List* copyL = consList();
newCopy(l->head, copyL);
//Sort by decreasing order
fusionSort_Task(copyL);
ListNode* curr = copyL->head;
Task* currT = (Task*)curr->data;
//Heuristic's result
State* H = consState();
double temp_t = 0;
double temp_q = 0;
//Placed Task total duration
double Ak = 0;
//Heuristic
while (curr != NULL) {
temp_t = Ak / 2 + (currT->_dur / 2);
temp_q = fmax(temp_t + currT->_lat, H->_eOe);
H->_eOe = temp_q;
append(currT, H->_task2);
Ak += currT->_dur;
curr = curr->next;
}
return H;
}
//Return the delta value for duration
double findDeltaD(List* l, double sigma) { return (sigma*sumDurTaskList(l->head)) / (4 * l->size); }
//Return the delta value for latency
double findDeltaL(List* l, double sigma) {
List* copyL = consList();
newCopy(l->head, copyL);
return (sigma*heuristic(copyL)->_eOe) / (6 * l->size);
}
//Round duration depending on deltaD and latency depending on deltaL || Create a new list
List* rounding(List* taskList, double deltaD, double deltaL) {
//Current node
ListNode* curr = taskList->head;
//Current task
Task* currT = NULL;
//Rounded task
Task* newT = NULL;
//Rounded task list
List* l = consList();
if (taskList->size == 1) {
currT = (Task*)curr->data;
newT = consTask(std::ceil(currT->_dur / deltaD) * deltaD, std::ceil(currT->_lat / deltaL) * deltaL);
push(newT, l);
return l;
}
while (curr != NULL) {
currT = (Task*)curr->data;
newT = consTask(std::ceil(currT->_dur / deltaD) * deltaD, std::ceil(currT->_lat / deltaL) * deltaL);
append(newT, l);
curr = curr->next;
}
return l;
}
//Create a new list pairing the corresponding original and rounded Tasks
List* createListTaskPair(List* origin, List* rounded) {
//Paired list
List* pairL = consList();
ListNode* currO = origin->head;
ListNode* currR = rounded->head;
TaskPair* pair = NULL;
while (currO != NULL) {
//Create pair
pair = consTaskPair((Task*)currO->data, (Task*)currR->data);
//Add pair
append(pair, pairL);
//Next value
currO = currO->next;
currR = currR->next;
}
return pairL;
}
//Transpose Optimal Solution of a rounded instance to it's original instance
State* transpose(State* opt, List* taskPair){
//Transposed State || result
State* trueOpt = consState();
ListNode* currStateTask1 = opt->_task1->head;
ListNode* currStateTask2 = opt->_task2->head;
ListNode* currPair = taskPair->head;
//Placed Task total duration
double Ak = 0;
//Transpose Machine 1 Task
while (currStateTask1 != NULL) {
//Current Task
Task* currT = (Task*)currStateTask1->data;
bool found = false;
TaskPair* currP = NULL;
//Search in Pairs
while (!found) {
currP = (TaskPair*)currPair->data;
if (currT == currP->_rounded) found = true;
else currPair = currPair->next;
}
//Add Task to transposed State
append(currP->_origin, trueOpt->_task1);
//Add Task duration to _t
trueOpt->_t += currP->_origin->_dur;
//Define new _eOe
trueOpt->_eOe = fmax(trueOpt->_t + currP->_origin->_lat , trueOpt->_eOe);
//Remove Task to speed up next research
removeData(currP, taskPair);
//Reinitialize to head
currPair = taskPair->head;
//Next Task to transpose
currStateTask1 = currStateTask1->next;
}
//Only Machine 1 execution
Ak = trueOpt->_t;
//Transpose Machine 2 Task
while (currStateTask2 != NULL) {
//Current Task
Task* currT = (Task*)currStateTask2->data;
bool found = false;
TaskPair* currP = NULL;
//Search in Pairs
while (!found) {
currP = (TaskPair*)currPair->data;
if (currT == currP->_rounded) found = true;
else currPair = currPair->next;
}
//Add Task to transposed State
append(currP->_origin, trueOpt->_task2);
//Define new _eOe
trueOpt->_eOe = fmax((Ak - trueOpt->_t)/2 + currP->_origin->_dur/2 + currP->_origin->_lat, trueOpt->_eOe);
//Add curr Task time to Ak
Ak += currP->_origin->_dur;
//Remove Task to speed up next research
removeData(currP, taskPair);
//Reinitialize to head
currPair = taskPair->head;
//Next Task to transpose
currStateTask2 = currStateTask2->next;
}
return trueOpt;
}
// -----------------------------------------------------//
// ------------------ PROG DYN ALGO ------------------//
// -----------------------------------------------------//
//Use Dynamic Programmation based on States to find an Optimal Solution
State* progDynState(List* taskList) {
std::cout << "PROG DYN | State ==>> \n";
std::cout << "Task List :: \n" << listToString_Task(taskList) << "\n";
//Get-through list
ListNode * currT = taskList->head;
//Start state, (0 , 0 , 0 , 0)
State* start = consState();
//State list
List* sL = consList(); //Xi-1
push(start, sL);
List* sL2 = consList();//Xi
//Get through list
ListNode* currS = sL->head;
//Placed Task total duration
double Ak = 0;
while (currT != NULL) {
Task* ctask = (Task*)currT->data;
empty(sL2);
//Create new States with new Task and old States
while (currS != NULL) {
State* cstate = (State*)currS->data;
//std::cout << "MM |||| MM - Mother State : " << stateToString(cstate) << "\n\n";
//ON MACHINE 1
//new start, start of state + task duration
double temp_t = cstate->_t + ctask->_dur;
//max between (start of state + latency of task) and (end of original state)
double temp_q = fmax(temp_t + ctask->_lat, cstate->_eOe);
State * s1 = consState(temp_q, temp_t);
//Keep track of tasks on first machine
newCopy(cstate->_task1->head, s1->_task1);
append(currT->data, s1->_task1);
//Keep track of tasks on second machine
newCopy(cstate->_task2->head, s1->_task2);
//std::cout << "S1 |||| S1 - State 1 : " << stateToString(s1) << "\n\n";
//Add state to list
push(s1, sL2);
//ON MACHINE 2
//new start, start of state + task duration
temp_t = (Ak - cstate->_t) / 2 + (ctask->_dur / 2);
//max between (start of state + latency of task) and (end of original state)
temp_q = fmax(temp_t + ctask->_lat, cstate->_eOe);
State * s2 = consState(temp_q, cstate->_t);
//Keep track of tasks on second machine
newCopy(cstate->_task2->head, s2->_task2);
append(currT->data, s2->_task2);
//Keep track of tasks on first machine
newCopy(cstate->_task1->head, s2->_task1);
//std::cout << "S2 |||| S2 - State 2 : " << stateToString(s2) << "\n\n";
//Add state to list
push(s2, sL2);
//Next list member
currS = currS->next;
}
//Xi CREATED
//ERASE OLD SET OF STATE --- Xi-1
freeNodes(sL);
//SET IT ANEW --- Xi-1 = Xi
assignTo(sL, sL2);
//OPTIMIZATION
//Removes multiple occurence of t value, only keeping the best of each.
sL = removeMultOcc(sL);
//Keeps best state
//sL = keepBestState(sL);
currS = sL->head;
//END OF OPTIMIZATION
//Add curr Task time to Ak
Ak += ctask->_dur;
//Next list member
currT = currT->next;
}
//std::cout << "Best States : \n" << listToString_State(sL) << " \n\n";
sL = keepBestState(sL);
std::cout << "Optimal Solution : \n" << stateToString((State*)sL->head->data) << " \n";
return (State*)sL->head->data;
}
#endif // !TOOLS
What is wrong with my code ?
It seems like something is bad in my memory management but I can't find where. I thank you greatly for your help !
I'm using Visual Studio 2019.
Related
I am trying to implement an algorithm in C which splits a linked list. So what I am trying to do is, I have a linked list of all entries, I am trying to split that linked list into two separate lists based on distance of elements from a specific node.
What shiftAndCluster does is takes in a linked list list, 2 empty lists oldFreshList and newList and 2 nodes best1 and best2. It first searches for these 2 nodes in list and pushed them into 2 empty lists respectively. Then the function iterates over each node of list and calculates its distance from either of the nodes and pushes it to the list containing the closer best node.
The code goes like this
void shiftAndCluster(SinglyLinkedList* list, SinglyLinkedList* oldFreshList, SinglyLinkedList* newList, SinglyLinkedListNode *best1, SinglyLinkedListNode *best2)
{
SinglyLinkedListNode *curr1 = list->front;
SinglyLinkedList *temp = cloneFullList(list);
SinglyLinkedListNode *prev = curr1;
while (curr1 != NULL)
{
if (curr1 == best2)
{
break;
} //reach till best2 in the list, so we have the prev of best2 with us
prev = curr1;
curr1 = curr1->next;
}
if (prev == curr1)
{
list->front = curr1->next;
list->size--;
SinglyLinkedList_pushFront(newList,curr1);
}
else
{
prev->next = curr1->next;
list->size--;
SinglyLinkedList_pushFront(newList,curr1);
}
curr1 = list->front;
prev = curr1;
while(curr1 != NULL)
{
if (curr1 == best1) {
// break when found best1
break;
};
prev = curr1;
curr1 = curr1->next;
}
// first, middle and last
if (prev == curr1)
{
list->front = curr1->next;
list->size--;
SinglyLinkedList_pushFront(oldFreshList,curr1);
}
else
{
prev->next = curr1->next;
list->size--;
SinglyLinkedList_pushFront(oldFreshList,curr1);
}
int firstSize = 1;
int secondSize = 1;
curr1 = list->front;
double dist1, dist2;
while (curr1 != NULL && list->size)
{
curr1=list->front;
SinglyLinkedList_popFront(list);
dist1 = calculateDistance(curr1,best1);
dist2 = calculateDistance(curr1,best2);
if (dist1 < dist2)
{
SinglyLinkedList_pushFront(oldFreshList,curr1);
firstSize++;
if (firstSize == 10) break;
}
else
{
SinglyLinkedList_pushFront(newList,curr1);
secondSize++;
if (secondSize == 10) break;
}
}
list->front = temp->front;
list->size = temp -> size;
}
The size of list is 11 nodes so the algorithm stops when either of the new list reaches size 10. At the end, the old list is repopulated with it's original entries.
The struct has been defined as
typedef struct SinglyLinkedListNode
{
void *data;
struct SinglyLinkedListNode *next;
}SinglyLinkedListNode;
typedef struct SinglyLinkedList
{
int size;
struct SinglyLinkedListNode *front;
}SinglyLinkedList;
Helper functions are:
SinglyLinkedListNode* cloneList(SinglyLinkedListNode *head) {
if(head == NULL) return NULL;
SinglyLinkedListNode *result = (SinglyLinkedListNode *)malloc(sizeof(SinglyLinkedListNode));
result->data = head->data;
result->next = cloneList(head->next);
return result;
}
SinglyLinkedList* cloneFullList(SinglyLinkedList *list) {
if(list == NULL) return NULL;
SinglyLinkedList *result = (SinglyLinkedList *)malloc(sizeof(SinglyLinkedList));
result->size = list->size;
result->front = cloneList(list->front);
return result;
}
pushFront, popFront and calculateDistance functions are trivial and work correctly. (Can provide them if required, but I have tested them extensively, they work correctly)
The issue I am facing is that when I try to use this function in a loop, it breaks after a single iteration.
Example is
//templist is a normal linked list containing 11 nodes
SinglyLinkedListNode *ppp1 = templist->front;
SinglyLinkedListNode *ppp2 = templist->front;
int ctrin = 0, ctr=0;
while (ppp1 != NULL)
{
ctr++;
ppp2 = templist->front;
ctrin = 0;
while (ppp2 != NULL)
{
SinglyLinkedList* tp2 = createEmptyList();
SinglyLinkedList* np2 = createEmptyList();
ctrin++;
if (ppp1 == ppp2)
{
ppp2 = ppp2->next;
ctrin++;
}
shiftAndCluster(templist, tp2, np2, ppp1, ppp2, listType, 1);
templist = cloneFullList(list);
printf("(%d, %d)\n", ctr, ctrin);
ppp2 = ppp2->next;
}
iter++;
ppp1 = ppp1->next;
}
createEmptyList function just creates an empty list.
The output prints (1,2) indicating it does check for (1,1) and skip it and after shifting and clustering once, it breaks down. The incoming list is fine and I think there are issues with the logic of the function. Can someone please help?
May not be the only problem but when you do :
prev = curr1;
curr1 = curr1->next;
prev will always be different of curr1. So the test if (prev == curr1) if always false except if list->front is NULL
I'm coding a generic AVL tree as both a challenge to myself and, if I can do it properly, a resource for other CS students out there.
As one usually would, I started by implementing a recursive insertion function, which works. However, due to efficiency, I tried to implement the same function, but iteratively. I searched online and found lots of implementations, but the rest of the code was always too different from mine, which led me to continue attempting to create an implementation from scratch.
These are the relevant defined types:
typedef struct info {
int id;
char name[200];
} data;
typedef struct avl_node {
void * data;
struct avl_node * left;
struct avl_node * right;
int height;
} * avl_node_t;
typedef struct avl_tree {
avl_node_t root;
int num_nodes;
int (*less)(const void * first, const void * second);
int (*key)(const void * data);
} * avl_t;
And as follows is the iterative insertion function (which doesn't work as intended):
avl_node_t
avl_insert(avl_node_t node, void * data)
{
long key1 = 0, key2 = 0;
avl_node_t aux = NULL;
while (1) {
if (node == NULL) {
node = avl_node_create(data);
break;
}
key1 = key((void*)&data);
key2 = key((void*)&(node->data));
aux = node;
if (less((void*)&key1, (void*)&key2))
node = node->left;
else
node = node->right;
}
if (aux != NULL) {
if (less((void*)&key1, (void*)&key2))
aux->right = node;
else if (less((void*)&key2, (void*)&key1))
aux->left = node;
}
node = avl_balance(node);
return node;
}
In which the avl_balance function is defined as such:
static short
balance(avl_node_t node)
{
if (node == NULL)
return 0;
return avl_node_height(node->left) - avl_node_height(node->right);
}
static avl_node_t
avl_balance(avl_node_t node)
{
short balance_factor;
if (node == NULL)
return node;
balance_factor = balance(node);
if (balance_factor > 1)
if (balance(node->left) >= 0)
node = avl_rotRight(node);
else
node = avl_rotLeftRight(node);
else if (balance_factor < -1)
if (balance(node->right) <= 0)
node = avl_rotLeft(node);
else
node = avl_rotRightLeft(node);
else
update_height(node);
return node;
}
This is the code I'm using to test the AVL tree:
int main()
{
data d1 = { 1, "we are number one" };
data d2 = { 2, "boneless pizza" };
data d3 = { 3, "hehe" };
data d4 = { 4, "achoo" };
data d5 = { 5, "I like C" };
data d6 = { 6, "Assembly is cool too" };
data d7 = { 7, "SIGSEGV" };
avl_t tree = avl_create();
avl_node_t root = tree->root;
root = avl_insert(root, (void*)&d1);
traverse(root);
root = avl_insert(root, (void*)&d2);
traverse(root);
root = avl_insert(root, (void*)&d3);
root = avl_insert(root, (void*)&d4);
root = avl_insert(root, (void*)&d5);
root = avl_insert(root, (void*)&d6);
root = avl_insert(root, (void*)&d7);
traverse(root);
free(tree);
exit(0);
}
In which traverse is defined as such:
void visit(void * d)
{
data * my_data = (data*)d;
printf("I am element number %d named %s\n", (*my_data).id, (*my_data).name);
fflush(stdout);
}
void traverse(avl_node_t node)
{
if (node == NULL)
return;
traverse(node->left);
traverse(node->right);
visit(node->data);
}
And finally, this is the output I'm getting from this test:
I am element number 1 named we are number one
I am element number 2 named boneless pizza
I am element number 7 named SIGSEGV
Thank you in advance.
If you do not mind, i implemented it in c++ version.
// In the view of C, just omit the template declaration and replace the class with struct
template<typename T>
class AVL_tree{
private:
class AVL_Node{
public:
T val;
AVL_Node* left;
AVL_Node* right;
AVL_Node* parent;
int height;
// Node Constructor -
AVL_Node():left{nullptr}, right{nullptr}, parent{nullptr}, val{}, height{0}{}
AVL_Node(T val): left{nullptr}, right{nullptr}, parent{nullptr}, height{0}, val{val}{}
};
AVL_Node* root;
short (*cmp_func)(T, T);
// Utility -
void add_child(AVL_Node* prev_nd, AVL_Node* chd_nd){
if(prev_nd == nullptr){
this->root = chd_nd;
return;
}
// update parent pointer first.
switch(cmp_func(chd_nd->val, prev_nd->val)){
case 1:
prev_nd->right = chd_nd;
break;
case 0:
prev_nd->left = chd_nd;
break;
case -1:
cerr << "Warning : The element should not be duplicate." << endl;
return;
default:
cerr << "ERROR_MESSAGE : The self-defin compare func should return triple value (1, 0, -1)." << endl;
return;
}
// update parent pointer of child node
chd_nd->parent = prev_nd;
}
AVL_Node* find_node(T val){
AVL_Node* prev_ptr = nullptr;
for(AVL_Node* tmp_ptr = this->root ; tmp_ptr != nullptr ; ){
prev_ptr = tmp_ptr;
switch(cmp_func(val, tmp_ptr->val)){
case 1:
tmp_ptr = tmp_ptr->right;
break;
case 0:
tmp_ptr = tmp_ptr->left;
break;
case -1:
return prev_ptr;
}
}
// for not find the node, return their parent node.
return prev_ptr;
}
int get_max(int a, int b){ return (a >= b) ? a : b; }
int get_height(AVL_Node* ptr_nd){
if(ptr_nd == nullptr)
return -1;
return ptr_nd->height;
}
int cal_balance(AVL_Node* nd_ptr){ return get_height(nd_ptr->left) - get_height(nd_ptr->right); }
AVL_Node* Right_rotate(AVL_Node* curr_nd){
AVL_Node* lft_chd = curr_nd->left;
AVL_Node* rgt_suc = lft_chd->right;
// Perform rotation
lft_chd->right = curr_nd;
curr_nd->left = rgt_suc;
// update parent pointer of current pointed node and child node
lft_chd->parent = curr_nd->parent;
curr_nd->parent = lft_chd;
if(rgt_suc != nullptr)
rgt_suc->parent = curr_nd;
// Update heights
lft_chd->height = get_max(get_height(lft_chd->left), get_height(lft_chd->right)) + 1;
curr_nd->height = get_max(get_height(curr_nd->left), get_height(curr_nd->right)) + 1;
return lft_chd;
}
AVL_Node* Left_rotate(AVL_Node* curr_nd){
AVL_Node* rgt_chd = curr_nd->right;
AVL_Node* lft_suc = rgt_chd->left;
// Perform rotation
rgt_chd->left = curr_nd;
curr_nd->right = lft_suc;
// update parent pointer of current pointed node and child node
rgt_chd->parent = curr_nd->parent;
curr_nd->parent = rgt_chd;
if(lft_suc != nullptr)
lft_suc->parent = curr_nd;
// Update heights
rgt_chd->height = get_max(get_height(rgt_chd->left), get_height(rgt_chd->right)) + 1;
curr_nd->height = get_max(get_height(curr_nd->left), get_height(curr_nd->right)) + 1;
return rgt_chd;
}
void splice(AVL_Node* ptr_nd){
/* remove node confirm that the ptr_nd have successor in single side.
Case 1. ; Case 2. */
AVL_Node* succsor_nd = (ptr_nd->left != nullptr) ? ptr_nd->left : ptr_nd->right;
if(ptr_nd == this->root){ // for remove the root.
this->root = succsor_nd;
}else{
AVL_Node* par_nd = ptr_nd->parent;
if(par_nd->left == ptr_nd)
par_nd->left = succsor_nd;
else
par_nd->right = succsor_nd;
if(succsor_nd != nullptr) succsor_nd->parent = par_nd;
}
}
public:
enum Order{ // for the order traversal.
pre_order,
post_order,
in_order
};
// Constructor -
AVL_tree():root{nullptr}, cmp_func{&defau_cmp<T>}{}
AVL_tree(short (*def_cmp_func)(T, T)):root{nullptr}, cmp_func{def_cmp_func}{}
// Operation -
void insert(T val){
// BST insertion operation
AVL_Node* prev_nd = find_node(val);
AVL_Node* chd_nd = new AVL_Node(val);
add_child(prev_nd, chd_nd);
// Balance the tree
for(AVL_Node* nd_ptr = prev_nd ; nd_ptr != nullptr ; nd_ptr = nd_ptr->parent){
const int& bf = cal_balance(nd_ptr);
// Left bias unbalance
if( bf > 1 ){
if(val > nd_ptr->left->val)
nd_ptr->left = Left_rotate(nd_ptr->left);
// update parent's pointer
AVL_Node* par_ptr = nd_ptr->parent;
if(par_ptr != nullptr && par_ptr->right == nd_ptr)
par_ptr->right = Right_rotate(nd_ptr);
else if(par_ptr != nullptr && par_ptr->left == nd_ptr)
par_ptr->left = Right_rotate(nd_ptr);
else
Right_rotate(nd_ptr);
// Right bias unbalance
}else if(bf < -1){
if(val < nd_ptr->right->val)
nd_ptr->right = Right_rotate(nd_ptr->right);
// update parent's pointer
AVL_Node* par_ptr = nd_ptr->parent;
if(par_ptr != nullptr && par_ptr->right == nd_ptr)
par_ptr->right = Left_rotate(nd_ptr);
else if(par_ptr != nullptr && par_ptr->left == nd_ptr)
par_ptr->left = Left_rotate(nd_ptr);
else // nd_ptr equal root
Left_rotate(nd_ptr);
// else, the sub-tree is already balanced
}else{
nd_ptr->height = get_max(get_height(nd_ptr->left), get_height(nd_ptr->right)) + 1;
}
// finally update the new root pointer
if(nd_ptr->parent == nullptr)
this->root = nd_ptr;
}
}
// remove operation is still working on it though.
// Smart_queue just like a queue offer general interface, you can use stl-container.
void BF_print(){
Smart_queue<AVL_Node*> nd_que(this->root);
while(!nd_que.is_empty()){
AVL_Node* tmp_ptr = nd_que.pop();
if(tmp_ptr == nullptr)
continue;
cout << tmp_ptr->val << " ";
nd_que.push(tmp_ptr->left);
nd_que.push(tmp_ptr->right);
}
}
};
I need to segregate even and odd nodes in a Linked List in C.
Example:
Original list: 3,1,8,2,5,6
After change: 8,2,6,3,1,5
I have a problem when the head list data is an odd number, it is cutting out the even numbers.
Example:
Original list: 3,1,8,2,5,6
After change: 3,1,5
typedef struct Node {
int data; // store information
struct Node * next; //referance to the next node
}Node;
Node * create(Node * L, int value)
{
Node *current = L ,* new_node = (Node*)malloc(sizeof(Node)); // create and allocate a node
new_node->data = value;
new_node->next = NULL;
if (L == NULL)
{
L = new_node;
current = new_node;
}
else
{
while (current->next != NULL)
current = current->next;
current->next = new_node;
current = new_node;
}
return L;
}
Node * Change_Even_Odd(Node * L)
{
Node *oddhead = NULL, *evenhead = NULL, *lastodd = NULL, *lasteven = NULL, *current = L;
while (current != NULL)
{
// if current is even node
if (current->data % 2 == 0)
{
if (evenhead == NULL)
{
evenhead = current;
lasteven = current;
}
else
{
lasteven->next = current; // to connect the node to the list in the end
lasteven = current; // final list
}
}
else
{
// if current is odd node
if (oddhead == NULL)
{
oddhead = current;
lastodd = current;
}
else
{
lastodd->next = current;
lastodd = current;
}
}
current = current->next;
}
if (evenhead != NULL) // to put the even node in the head list
L = evenhead;
if (lasteven != NULL) // link the odd nodes to the even nodes
lasteven->next = oddhead;
if (lastodd != NULL) //end of list
lastodd->next = NULL;
return L;
}
void Print_List(Node * head)
{
while (head != NULL)
{
printf("%4d", head->data);
head = head->next;
}
}
int main()
{
Node * list = NULL; //empty linked list
srand(time(NULL));
int i, size = rand() % 10 + 1;
for (i = 0; i < size; i++)
list = create(list, rand() % 10 + 1);
printf("%d\n",size);
Print_List(list);
printf("\n");
Change_Even_Odd(list);
Print_List(list);
printf("\n");
}
Change_Even_Odd(list); should be list = Change_Even_Odd(list); (I already pointed out.)
– BLUEPIXY
I am trying to code very basic sorting method for linked lists. I am getting unhandled exception. What is the mistake i am making? Here is my code:-
struct LinkedNode// structure for linked list
{
int data;
struct LinkedNode *next;
}*start = NULL;
following function creates a linked list
void CreateLinkedList()
{
LinkedNode *newNode, *current;
printf("enter 5 numbers to create linked list\n");
for(int i=0; i<5; i++)
{
newNode = (struct LinkedNode *)malloc(sizeof(LinkedNode));
scanf("%d", &newNode->data);
newNode->next = NULL;
if(start == NULL)
{
start = newNode;
current = newNode;
}
else
{
current->next = newNode;
current = newNode;
}
}
}
following function is used for sorting the linked list nodes
void SortLinkedList()
{
struct LinkedNode *node=NULL, *temp = NULL;
int tempvar;//temp variable to store node data
node = start;
temp = node->next;//temp node to hold node data and next link
while(node != NULL && node->next != NULL)
{
for(int j=0; j<5; j++)//value 5 because I am taking only 5 nodes
{
if(node->data > temp->data)//swap node data
{
tempvar = node->data;
node->data = temp->data;
temp->data = tempvar;
}
temp = temp->next;
}
node = node->next;
}
}
Try This code
void SortLinkedList()
{
struct LinkedNode *node=NULL, *temp = NULL;
int tempvar;//temp variable to store node data
node = start;
//temp = node;//temp node to hold node data and next link
while(node != NULL)
{
temp=node;
while (temp->next !=NULL)//travel till the second last element
{
if(temp->data > temp->next->data)// compare the data of the nodes
{
tempvar = temp->data;
temp->data = temp->next->data;// swap the data
temp->next->data = tempvar;
}
temp = temp->next; // move to the next element
}
node = node->next; // move to the next node
}
}
1 - outer while loop is use for the total number of pass that will require to sort the linked list..
2- In second while loop we are actually comparing the data of the nodes that we want to sort
Instead of implementing your own sort, you can just use qsort. Of course, qsort requires an array, but that is easy enough to create.
In this case, you know that the list has 5 members. But, if you didn't know, you could just count them.
int size_of_list = 0;
struct LinkedNode *p;
for (p = start; p != NULL; p = p->next) ++size_of_list;
if (size_of_list == 0) {
// Nothing to do
return;
}
Now you can create your array;
struct LinkedNode *arr[size_of_list + 1], **arrp = arr;
for (p = start; p != NULL; p = p->next) *arrp++ = p;
*arrp = NULL;
Then, use qsort on arr. There are lots of examples, but the trick is writing an appropriate comparison function.
int cmp_LinkedNode(const void *a, const void *b) {
const struct LinkedNode * const *aa = a;
const struct LinkedNode * const *bb = b;
return ((*aa)->data > (*bb)->data) - ((*aa)->data < (*bb)->data);
}
//...
qsort(arr, size_of_list, sizeof(*arr), cmp_LinkedNode);
And then, rewire the list into the sorted order.
for (int i = 0; i < size_of_list; ++i) arr[i]->next = arr[i+1];
start = arr[0];
yeah sorting a linked list using nodes/links is a pretty hard job. Spend hours doing it myself but since i have done it why not help others..
What you need to do is simply find the minimum value in your list. Swap it with the head node and the recur for head->next.
The code for sort is only of 3 to 4 lines if you have FindMin() and Swap() functions made..
here is the complete code for sort(),swap()and findmin().
void sort(node **start)
{
if (((*start)->next == NULL) || (*start == NULL))
{
return;
}
node *min = findmin(*start);
swap(*start, min, start);
sort(&((*start)->next));
}
void swap(node *p1, node *p2, node **start)
{
node *p1pre = NULL;
node *p1curr = *start;
while (p1curr!=p1)
{
p1pre = p1curr;
p1curr = p1curr->next;
}
node *p2pre = NULL;
node *p2curr = *start;
while (p2curr != p2)
{
p2pre = p2curr;
p2curr = p2curr->next;
}
if (p1pre != NULL)
{
p1pre->next = p2curr;
}
else
{
*start = p2curr;
}
if (p2pre != NULL)
{
p2pre->next = p1curr;
}
else
{
*start = p1curr;
}
node *temp = p2curr->next;
p2curr->next = p1curr->next;
p1curr->next = temp;
}
node* findmin(node *start)
{
int flag = 0;
if (start == NULL)
{
cout << "list is empty" << endl;
}
else
{
node *curr = start->next;
node *min = start;
while (curr->next != NULL)
{
if (min->value > curr->value)
{
min = curr;
flag++;
}
curr = curr->next;
}
if ((curr->next == NULL) && (min->value > curr->value))
{
min = curr;
flag++;
}
if (flag > 0)
{
return min;
}
}
}
I have a problem. The code below creates a two-way looped list. When I want to delete an item of specyfic key value, everything goes right. The problem comes when I want to add an item after deleting another one. It just doesn't appear when I display the list. Do you have any ideas why?
#include <iostream>
#include <time.h>
#include <vector>
#include <stdlib.h>
struct List
{
int key;
double val1, val2, val3;
struct List *next, *prev;
}*element, *temp, *head;
bool ifrepeat = false,ifdelete;
void AddOne(struct List *&head1, int x)
{
List *tmp = head1;
if (head1 != NULL)
{
do
{
if (head1->key == x)
{
ifrepeat = true;
}
head1 = head1->next;
} while (head1 != tmp);
}
if (ifrepeat)
{
printf("Podana wartosc klucza juz istnieje!\n");
ifrepeat = false;
}
else
{
head1 = tmp;
if (head1 == NULL)
{
head1 = (struct List*)malloc(sizeof(struct List));
head1->key = x;
head1->val1 = 1 + (rand() % 1000);
head1->val2 = 1 + rand() % 1000;
head1->val3 = 1 + rand() % 1000;
head1->next = head1;
head1->prev = head1;
}
else
{
if (element == NULL)
{
element = (struct List*)malloc(sizeof(struct List));
element->key = x;
head->next = element;
element->prev = head1;
element->next = head1;
head1->prev = element;
temp = element;
}
else
{
element = (struct List*)malloc(sizeof(struct List));
element->key = x;
temp->next = element;
element->prev = temp;
element->next = head1;
head1->prev = element;
temp = element;
}
}
}
}
void ShowBegin(struct List *head)
{
if (head == NULL)
printf("Lista jest pusta!");
else
{
struct List *temphead;
temphead = head;
printf("%d ", head->key);
head = head->next;
while (head != temphead)
{
printf("%d ", head->key);
head = head->next;
}
printf("\n");
}
}
void AddMany(struct List *&head1, int x)
{
AddOne(head, 10+(rand()%1000)*(rand()%1000));
int tmpkey;
List *tmp = head1;
for (int i = 0; i < x; i++)
{
tmpkey = 10 + (rand() % 100)*(rand() % 1000);
while (head1 != tmp)
{
while (head->key == tmpkey)
{
tmpkey = 10 + (rand() % 100)*(rand() % 1000);
head1 = tmp;
}
head1 = head1->next;
}
AddOne(head, tmpkey);
head1 = tmp;
head1 = head1->next;
}
}
void Sort(struct List *&head1)
{
int max;
List *maxPos,*tmp;
maxPos = head1;
max = head1->key;
while (true)
{
head1 = head1->next;
if (head1->key > max)
{
tmp = head1;
head1 = maxPos;
maxPos = tmp;
max = maxPos->key;
head1 = head;
}
}
}
void CreateList()
{
head = NULL;
element = NULL;
temp = NULL;
}
void Delete(struct List *&head1, int x)
{
struct List *temphead;
temphead = head1;
if (head == NULL)
{
printf("Lista jest pusta!\n");
return;
}
else
{
head1 = head1->next;
if (head1 == temphead)
{
if (head1->key == x)
{
free(head1);
head1 = NULL;
ifdelete = true;
}
else
ifdelete = false;
}
else
{
while (head1 != temphead)
{
if (head1->key == x)
{
List *temp;
temp = head1;
head1->prev->next = head1->next;
head1->next->prev = head1->prev;
head1 = head1->next;
while (head1 != temphead)
{
}
free(temp);
ifdelete = true;
break;
}
else
ifdelete = false;
head1 = head1->next;
}
}
if (!ifdelete)
{
printf("Element o podanym kluczu nie istnieje!\n");
}
}
}
void ShowEnd(struct List *&head)
{
if (head == NULL)
printf("Lista jest pusta!");
else
{
struct List *temphead;
temphead = head;
head = head->prev;
while (head != temphead)
{
printf("%d ", head->key);
head = head->prev;
}
printf("%d", temphead->key);
printf("\n");
}
}
void DeleteAll(struct List *&head)
{
free(head);
head = NULL;
}
int main()
{
int X=1000, k1=5, k2=2, k3=10, k4=-1;
/*FILE* plik = fopen("inlab02.txt", "r");
if (plik == NULL)
return -257;
fscanf(plik, "%d %d %d %d %d", &X, &k1, &k2, &k3, &k4);
fclose(plik);*/
srand(time(NULL));
clock_t begin, end;
double time_spent;
begin = clock();
CreateList();
Delete(head, k1);
ShowBegin(head);
AddMany(head, 10);
AddOne(head, k2);
Delete(head, k2);
AddOne(head, k4);
//Delete(head, k4);
ShowBegin(head);
//ShowEnd(head);
//DeleteAll(head);
end = clock();
time_spent = (double)(end - begin) / CLOCKS_PER_SEC;
printf("Program wykonal obliczenia w %f", time_spent);
getchar();
return 0;
}