I have a requirement where I have to create a new by processing the given dynamic array. I have no idea what my new array size would be. but the max size is 2x size of old array.
Background: Inside the function, it should iterate over each element in the array and based on the number it will add/delete either one or two elements into the new array.
Implementation: How I implemented the above requirement was, I create a linked list and add one or two new nodes according the check condition.
pseudocode:
node_t *createNode() {
node_t *temp;
temp = malloc(sizeof(node_t));
if (temp == NULL) {
fputs("Error: Failed to allocate memory for temp.\n", stderr);
exit(1);
}
temp->next = NULL;
return temp;
}
/*
* Function: addNode
* -----------------
* add node to a existing linked list at end
*
* head: original linked list to add additional node at end
* newVal: value of the additional node
*
* return: new linked list that have an additional node
*/
node_t *addNode(node_t *head, double newVal) {
node_t *temp;
node_t *p;
// create additional node
temp = createNode();
temp->val = newVal;
if (head == NULL) {
head = temp;
} else {
p = head;
while (p->next != NULL) {
p = p->next;
}
p->next = temp;
}
return head;
}
/*
* Function: lastNodeDeletion
* --------------------------
* delete last node of the linked list
*
* head: linked list
*/
void lastNodeDeletion(node_t *head) {
node_t *toDelLast;
node_t *preNode;
if (head == NULL) {
printf("There is no element in the list.");
} else {
toDelLast = head;
preNode = head;
/* Traverse to the last node of the list */
while (toDelLast->next != NULL) {
preNode = toDelLast;
toDelLast = toDelLast->next;
}
if (toDelLast == head) {
/* If there is only one item in the list, remove it */
head = NULL;
} else {
/* Disconnects the link of second last node with last node */
preNode->next = NULL;
}
/* Delete the last node */
free(toDelLast);
}
}
/*
* Function: calculateLower
* ------------------------
* find the data set of lower tube curve
*
* reference: reference data curve
* tubeSize: data array specifying tube size that includes:
* tubeSize[0], x -- half width of rectangle
* tubeSize[1], y -- half height of rectangle
* tubeSize[2], baseX -- base of relative value is x direction
* tubeSize[3], baseY -- base of relative value is y direction
* tubeSize[4], ratio -- ratio y / x
*
* return : data set defining lower curve of the tube
*/
struct data calculateLower(struct data reference, double *tubeSize) {
int i;
struct data ref_norm;
/*
struct data contains two pointers double *x, double *y, int n;
*/
struct data lower;
node_t *lx = NULL;
node_t *ly = NULL;
// ===== 1. add corner points of the rectangle =====
double m0, m1; // slopes before and after point i of reference curve
double s0, s1; // sign of slopes of reference curve: 1 - increasing, 0 - constant, -1 - decreasing
double mx, my;
int b;
double xLen;
double yLen;
// Normalize data.
mx = fabs(mean(reference.x, reference.n));
my = fabs(mean(reference.y, reference.n));
ref_norm = normalizeData(reference, mx, my);
if equ(mx, 0.0) {
xLen = tubeSize[0];
} else {
xLen = tubeSize[0] / mx;
}
if equ(my, 0.0) {
yLen = tubeSize[1];
} else {
yLen = tubeSize[1] / my;
}
// ----- 1.1 Start: rectangle with center (x,y) = (reference.x[0], reference.y[0]) -----
// ignore identical point at the beginning
b = 0;
while ((b+1 < ref_norm.n) && equ(ref_norm.x[b], ref_norm.x[b+1]) && (equ(ref_norm.y[b], ref_norm.y[b+1])))
b = b+1;
// add down left point
lx = addNode(lx, (ref_norm.x[b] - xLen));
ly = addNode(ly, (ref_norm.y[b] - yLen));
if (b+1 < ref_norm.n) {
// slopes of reference curve (initialization)
s0 = sign(ref_norm.y[b+1] - ref_norm.y[b]);
if (!equ(ref_norm.x[b+1], ref_norm.x[b])) {
m0 = (ref_norm.y[b+1] - ref_norm.y[b]) / (ref_norm.x[b+1] - ref_norm.x[b]);
} else {
m0 = (s0 > 0) ? 1e+15 : -1e+15;
}
if equ(s0, 1) {
// add down right point
lx = addNode(lx, (ref_norm.x[b] + xLen));
ly = addNode(ly, (ref_norm.y[b] - yLen));
}
// ----- 1.2 Iteration: rectangle with center (x,y) = (reference.x[i], reference.y[i]) -----
for (i = b+1; i < ref_norm.n-1; i++) {
// ignore identical points
if (equ(ref_norm.x[i], ref_norm.x[i+1]) && equ(ref_norm.y[i], ref_norm.y[i+1]))
continue;
// slopes of reference curve
s1 = sign(ref_norm.y[i+1] - ref_norm.y[i]);
if (!equ(ref_norm.x[i+1], ref_norm.x[i])) {
m1 = (ref_norm.y[i+1] - ref_norm.y[i]) / (ref_norm.x[i+1] - ref_norm.x[i]);
} else {
m1 = (s1 > 0) ? (1e+15) : (-1e+15);
}
// add no point for equal slopes of reference curve
if (!equ(m0, m1)) {
if (!equ(s0, -1) && !equ(s1, -1)) {
// add down right point
lx = addNode(lx, (ref_norm.x[i] + xLen));
ly = addNode(ly, (ref_norm.y[i] - yLen));
} else if (!equ(s0, 1) && !equ(s1, 1)) {
// add down left point
lx = addNode(lx, (ref_norm.x[i] - xLen));
ly = addNode(ly, (ref_norm.y[i] - yLen));
} else if (equ(s0, -1) && equ(s1, 1)) {
// add down left point
lx = addNode(lx, (ref_norm.x[i] - xLen));
ly = addNode(ly, (ref_norm.y[i] - yLen));
// add down right point
lx = addNode(lx, (ref_norm.x[i] + xLen));
ly = addNode(ly, (ref_norm.y[i] - yLen));
} else if (equ(s0, 1) && equ(s1, -1)) {
// add down right point
lx = addNode(lx, (ref_norm.x[i] + xLen));
ly = addNode(ly, (ref_norm.y[i] - yLen));
// add down left point
lx = addNode(lx, (ref_norm.x[i] - xLen));
ly = addNode(ly, (ref_norm.y[i] - yLen));
}
int len = listLen(ly);
double lastY = getNth(ly, len-1);
// remove the last added points in case of zero slope of tube curve
if equ((ref_norm.y[i+1] - yLen), lastY) {
if (equ(s0 * s1, -1) && equ(getNth(ly, len-3), lastY)) {
// remove two points, if two points were added at last
// ((len-1) - 2 >= 0, because start point + two added points)
lastNodeDeletion(lx);
lastNodeDeletion(ly);
lastNodeDeletion(lx);
lastNodeDeletion(ly);
} else if (!equ(s0 * s1, -1) && equ(getNth(ly, len-2), lastY)) {
// remove one point, if one point was added at last
// ((len-1) - 1 >= 0, because start point + one added point)
lastNodeDeletion(lx);
lastNodeDeletion(ly);
}
}
}
s0 = s1;
m0 = m1;
}
// ----- 1.3. End: Rectangle with center (x,y) = (reference.x[reference.n - 1], reference.y[reference.n - 1]) -----
if equ(s0, -1) {
// add down left point
lx = addNode(lx, (ref_norm.x[ref_norm.n-1] - xLen));
ly = addNode(ly, (ref_norm.y[ref_norm.n-1] - yLen));
}
}
// add down right point
lx = addNode(lx, (ref_norm.x[ref_norm.n-1] + xLen));
ly = addNode(ly, (ref_norm.y[ref_norm.n-1] - yLen));
// ===== 2. Remove points and add intersection points in case of backward order =====
int lisLen = listLen(ly);
double *tempLX = malloc(lisLen * sizeof(double));
if (tempLX == NULL) {
fputs("Error: Failed to allocate memory for tempLX.\n", stderr);
exit(1);
}
double *tempLY = malloc(lisLen * sizeof(double));
if (tempLY == NULL) {
fputs("Error: Failed to allocate memory for tempLY.\n", stderr);
exit(1);
}
tempLX = getListValues(lx);
tempLY = getListValues(ly);
lower = removeLoop(tempLX, tempLY, lisLen, -1);
return denormalizeData(lower, mx, my);
}
It worked well for small examples. But when an array with 0.5 million values is passed as input to this function, the performance decreased drastically.
Perfomance decrease when the pointers belongs to an array of 0.5 million data points.
is there any alternative solution for the above problem or is there any other modification that needs to done to improve performance?
Thanks