Let's say I have a Polynomial with 3 variables (x, y, z) that is not necessarily in canonical order and I want it to be in standard form where the leftmost term has the greatest exponent and the rightmost term has the least exponent. For example case:
Original Polynomial:
-7xy⁶ + 9xz - 8y⁷ +x⁷ + 4x⁵y⁴z² + 4xy²z³ + 3xy³
Standard Form:
x⁷ + 4x⁵y³z² - 7xy⁶ + 3xy³ + 4xy²z³ + 9xz - 8y⁷
This can be easily done in Python, but I am in C and I have no idea how it should be done. Here is a sample code where I implement polynomials with struct. To make it look less confusing, I am not displaying the variables. Instead, my format is: x exponent y exponent z exponent coefficient. Example: 4(x^5)(y^3)(z^2) is 5 3 2 4.
#include<stdio.h>
#include<stdlib.h>
struct Node
{
int coeff;
int powX;
int powY;
int powZ;
struct Node* next;
};
void readPolynomial(struct Node** poly) /* ACCEPTS A POLYNOMIAL WITH N TERMS */
{
struct Node* temp = (struct Node*)malloc(sizeof(struct Node));
*poly = temp;
int terms;
scanf("%d\n", &terms);
for(int i = 0; i < terms; i++)
{
char entry[200];
fgets(entry, sizeof(entry), stdin);;
char * splitter;
splitter = strtok(entry," ");
temp->powX = atoi(splitter);
splitter = strtok(NULL, " ");
temp->powY = atoi(splitter);
splitter = strtok(NULL, " ");
temp->powZ = atoi(splitter);
splitter = strtok(NULL, " ");
temp->coeff = atoi(splitter);
temp->next = NULL;
if(i != terms-1)
{
temp->next = (struct Node*)malloc(sizeof(struct Node));
temp = temp->next;
temp->next = NULL;
}
}
}
void canonicalPolynomial(struct Node* poly)
{
while(poly != NULL)
{
printf("%d %d %d %d\n", poly->powX, poly->powY, poly->powZ, poly->coeff);
poly = poly->next;
}
}
int main()
{
struct Node* result = NULL;
readPolynomial(&result);
canonicalPolynomial(result);
return 0;
}
Right now, canonicalPolynomial just prints it in the said format, but not yet in canonical order.
Input:
7
1 6 0 -7
1 0 1 9
0 7 0 -8
7 0 0 1
5 3 2 4
1 2 3 4
1 3 0 3
Expected Output:
7 0 0 1
5 3 2 4
1 6 0 -7
1 3 0 3
1 2 3 4
1 0 1 9
0 7 0 -8
UPDATE: Here's my latest code. I get the given test code right, but I miss the hidden ones in our compiler. So far, my code knows when a term has the coefficient 0, it does not print it. What else could I be missing?
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<string.h>
struct Node
{
float coeff;
int powX;
int powY;
int powZ;
struct Node* next;
};
void readPolynomial(struct Node** poly)
{
struct Node* temp = (struct Node*)malloc(sizeof(struct Node));
*poly = temp;
int terms;
fscanf(stdin, "%d", &terms);
getchar();
char entry[999999];
char *splitter;
for(int i = 0; i < terms; i++)
{
fgets(entry, sizeof(entry), stdin);
splitter = strtok(entry," ");
temp->powX = atoi(splitter);
splitter = strtok(NULL, " ");
temp->powY = atoi(splitter);
splitter = strtok(NULL, " ");
temp->powZ = atoi(splitter);
splitter = strtok(NULL, " ");
temp->coeff = atof(splitter);
temp->next = NULL;
if(i != terms-1)
{
temp->next = (struct Node*)malloc(sizeof(struct Node));
temp = temp->next;
temp->next = NULL;
}
}
}
int compareTerms(const struct Node *a, const struct Node *b)
{
int cmp;
cmp = (a->powX > b->powX) - (a->powX < b->powX);
if (cmp != 0) {
return cmp;
}
cmp = (a->powY > b->powY) - (a->powY < b->powY);
if (cmp != 0) {
return cmp;
}
cmp = (a->powZ > b->powZ) - (a->powZ < b->powZ);
return cmp;
}
void sortPolynomialTerms(struct Node **poly)
{
struct Node *head;
unsigned int sublen;
head = *poly;
if (!head) {
return;
}
sublen = 1;
while (1) {
struct Node *tail;
struct Node *p;
struct Node *q;
struct Node *e;
unsigned int plen;
unsigned int qlen;
unsigned int merges;
unsigned int i;
p = head;
head = NULL;
tail = NULL;
merges = 0;
while (p) {
merges++;
q = p;
plen = 0;
for (i = 0; i < sublen; i++) {
plen++;
q = q->next;
if (!q) {
break;
}
}
qlen = plen;
while (plen || (qlen && q)) {
if (!plen || (qlen && q && compareTerms(p, q) < 0)) {
e = q;
q = q->next;
qlen--;
} else {
e = p;
p = p->next;
plen--;
}
if (tail) {
tail->next = e;
} else {
head = e;
}
tail = e;
}
p = q;
}
tail->next = NULL;
if (merges <= 1) {
break;
}
sublen *= 2;
}
*poly = head;
}
void printPolynomial(const struct Node *poly)
{
while (poly)
{
if(poly->coeff != 0)
{
printf("%d %d %d %.3f\n", poly->powX, poly->powY, poly->powZ, poly->coeff);
}
poly = poly->next;
}
}
void canonicalPolynomial(struct Node **poly)
{
sortPolynomialTerms(poly);
printPolynomial(*poly);
}
void addPolynomials(struct Node** result, struct Node* first, struct Node* second)
{
struct Node* temp = (struct Node*)malloc(sizeof(struct Node));
temp->next = NULL;
*result = temp;
while(first && second)
{
if(compareTerms(first, second) < 0)
{
temp->coeff = second->coeff;
temp->powX = second->powX;
temp->powY = second->powY;
temp->powZ = second->powZ;
second = second->next;
}
else if(compareTerms(first, second) > 0)
{
temp->coeff = first->coeff;
temp->powX = first->powX;
temp->powY = first->powY;
temp->powZ = first->powZ;
first = first->next;
}
else
{
temp->coeff = first->coeff + second->coeff;
temp->powX = first->powX;
temp->powY = first->powY;
temp->powZ = first->powZ;
first = first->next;
second = second->next;
}
if(first && second)
{
temp->next = (struct Node*)malloc(sizeof(struct Node));
temp = temp->next;
temp->next = NULL;
}
}
while(first || second)
{
temp->next = (struct Node*)malloc(sizeof(struct Node));
temp = temp->next;
temp->next = NULL;
if(second)
{
temp->coeff = second->coeff;
temp->powX = second->powX;
temp->powY = second->powY;
temp->powZ = second->powZ;
second = second->next;
}
else if(first)
{
temp->coeff = first->coeff;
temp->powX = first->powX;
temp->powY = first->powY;
temp->powZ = first->powZ;
first = first->next;
}
}
}
int main()
{
struct Node* first = NULL;
struct Node* second = NULL;
struct Node* result = NULL;
readPolynomial(&first);
readPolynomial(&second);
addPolynomials(&result, first, second);
canonicalPolynomial(&result);
return 0;
}
The problem boils down to sorting a linked list, for which you need a suitable comparison function to determine the sort order for two terms on the list:
int compareTerms(const struct Node *a, const struct Node *b)
{
int cmp;
/* Compare X exponents. */
cmp = (a->powX > b->powX) - (a->powX < b->powX);
if (cmp != 0) {
return cmp;
}
/* Compare Y exponents. */
cmp = (a->powY > b->powY) - (a->powY < b->powY);
if (cmp != 0) {
return cmp;
}
/* Compare Z exponents. */
cmp = (a->powZ > b->powZ) - (a->powZ < b->powZ);
#if 0
if (cmp != 0) {
return cmp;
}
/* Compare coefficients (why not?). */
cmp = (a->coeff > b->coeff) - (a->coeff < b->coeff);
#endif
return cmp;
}
(Change the #if 0 to #if 1 to compare the coefficients if all the exponents are equal.)
The function returns -1 if the first term has lower order than the second, 1 if the first term has higher order than the second, or 0 if they are of equal order.
The comparison function can be used by a function to sort the list of terms. For simplicity, an exchange sort is shown below:
void sortPolynomialTerms(struct Node **poly)
{
while (*poly) {
struct Node **next = &(*poly)->next;
while (*next) {
struct Node *n = *next;
if (compareTerms(*poly, n) < 0) {
*next = n->next;
n->next = *poly;
*poly = n;
} else {
next = &n->next;
}
}
poly = &(*poly)->next;
}
}
The sort function can be used as follows:
void printPolynomial(const struct Node *poly)
{
while (poly)
{
printf("%d %d %d %.3f\n", poly->powX, poly->powY, poly->powZ, poly->coeff);
poly = poly->next;
}
}
void canonicalPolynomial(struct Node **poly)
{
sortPolynomialTerms(poly);
printPolynomial(*poly);
}
The parameter of sortPolynomialTerms and canonicalPolynomial is struct Node **poly because they may modify the pointer to the initial term *poly to point to a different initial term.
BONUS CONTENT
It is probably not worth it for short polynomials, but for polynomials containing many terms to be sorted, a merge sort will be more efficient than the exchange sort implemented above. Based on the sample code "listsort.c" for the page "Mergesort For Linked Lists" by Simon Tatham, the following version of sortPolynomialTerms uses a bottom-up merge sort:
void sortPolynomialTerms(struct Node **poly)
{
/*
* Bottom-up merge sort, based on:
*
* <https://www.chiark.greenend.org.uk/~sgtatham/algorithms/listsort.c>
*
* Original copyright notice for linked source:
*
* This file is copyright 2001 Simon Tatham.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL SIMON TATHAM BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
struct Node *head; /* head of merged list */
unsigned int sublen; /* maximum length of sub-list */
head = *poly;
if (!head) {
/* The list is empty, so does not need sorting. */
return;
}
/* Start with sub-lists of maximum length 1. */
sublen = 1;
while (1) {
struct Node *tail; /* tail of merged list */
struct Node *p; /* pointer to node in first sub-list */
struct Node *q; /* pointer to node in second sub-list */
struct Node *e; /* pointer to node to add to merged list */
unsigned int plen; /* length of first sub-list */
unsigned int qlen; /* maximum length of second sub-list */
unsigned int merges; /* number of sub-list merges done */
unsigned int i;
/*
* Construct a new merge list by merging one or more pairs
* of sorted sub-lists of length up to `sublen`.
*/
p = head;
head = NULL;
tail = NULL;
merges = 0;
while (p) {
merges++;
/* Step up to `sublen` places along from `p`. */
q = p;
plen = 0;
for (i = 0; i < sublen; i++) {
plen++;
q = q->next;
if (!q) {
break;
}
}
qlen = plen; /* upper bound on length of second sub-list */
/*
* Merge the two sub-lists onto the end of the new merge list.
*/
while (plen || (qlen && q)) {
/* Decide where the next element to merge comes from. */
if (!plen || (qlen && q && compareTerms(p, q) < 0)) {
/* Take next element from second list `q`. */
e = q;
q = q->next;
qlen--;
} else {
/* Take next element from first list `p`. */
e = p;
p = p->next;
plen--;
}
/* Add next element to the merged list. */
if (tail) {
tail->next = e;
} else {
head = e;
}
tail = e;
}
/* Advance to the next pair of sub-lists. */
p = q;
}
/* Terminate the new merge list. */
tail->next = NULL;
/* Finish when no more than one pair of sub-lists needed merging. */
if (merges <= 1) {
break;
}
/* Double the maximum length of the sub-lists for the next merge. */
sublen *= 2;
}
/* Update the link to the first node of the list. */
*poly = head;
}
The absolute simplest way of sorting a linked list is to convert it to a regular list, use qsort and then convert back. Something like this:
// Converts a linked list to array
//
// Assumes that memory is already allocated for dest and that src is a proper
// linked list where the last element has NULL assigned to ->next
void linkedListToArray(struct Node *dest, struct Node *src) {
while(src) {
*dest = src;
dest++;
src = src->next;
}
}
You should redesign your code to be more modular. You should study implementations of linked lists in general, but you should really write a function similar to this:
void append(struct Node **list, int coeff, int px, int py, int pz) {
struct Node *node = malloc(sizeof *node);
*node = (struct Node) {.coeff = coeff, .powX = px, .powY = py, .powZ = pz };
if(*list == NULL) {
*list = node;
} else {
while((*list)->next) (*list) = (*list)->next;
(*list)->next = node;
}
}
You should use it in readPolynomial but also in the function converting an array to a linked list.
void arrayToLinkedList(struct Node **list, struct Node *arr, size_t size) {
for(size_t i = 0; i < size; i++)
append(list, &arr[i]);
}
When you have the above, you just need to write the compare function for quicksort. Read the documentation about how that is done. And then you can do this:
struct Node *pol;
// Init code
struct Node *arr = malloc(sizeof *arr * size); // Calculate size before somehow
linkedListToArray(arr, pol);
qsort(arr, size, sizeof *arr, cmp);
struct Node *newPol;
arrayToLinkedList(&newPol, arr);
Note that I have skipped all error checking to keep the code short.
Old answer. I misread the question, but OP mentioned they liked the answer in comments. The below says it is how to make a polynomial to standard form, but the question I'm really answering is how to normalize a polynomial.
To convert it to standard normalized form, you basically need to do two things
Find the term with highest degree
Divide all terms with the coefficient of the term with highest degree.
Determining the term with highest degree is ambiguous when dealing with more than one variable, since the degree simply is Node::powX + Node::powY + Node::powZ. But in any case, you would need to define a function that takes a whole polynomial and returns the node with highest degree according to some definition. Here is ONE way to do it:
int degree(struct Node *term) {
return term->powX + term->powY + term->powZ;
}
struct Node *getTermWithHighestDegree(struct Node *pol) {
struct Node *ret = pol;
while(pol) {
if(degree(pol) > degree(ret)) ret = pol;
pol = pol->next;
}
}
Then simply do:
void convertToNormalizedForm(struct Node *pol) {
struct Node *term = getTermWithHighestDegree(pol);
int coeff = term->coeff;
while(pol) {
pol->coeff /= coeff;
pol = pol->next;
}
}
Do however note that you might run into several issues because you're storing the coefficients as integers. You might want to change to a float type.
Related
I'm performing binary tree deletion in c.I was trying out few methods interestingly this weird situation came.
void Delete(){
struct BinaryTree* ptr = root;
int element;
printf("Enter element to delete : ");
scanf("%d",&element);
while(ptr){
if(element>ptr->data)
ptr = ptr->right;
else if(element<ptr->data)
ptr = ptr->left;
else
break;
}
if(ptr->left && ptr->right){
struct BinaryTree **smallest = &(ptr);
smallest = &((*smallest)->right);
while((*smallest)->left){
smallest = &((*smallest)->left);
}
ptr->data = (*smallest)->data;
free(*smallest);
*smallest = NULL;
} else if(ptr->left){
/*rest cases*/
}
}
The above code works and it sets the the NODE to NULL.
But when i do this procedure in this way it doesn't set to NULL.
if(ptr->left && ptr->right){
struct BinaryTree *smallest = ptr;
smallest = smallest->right;
while(smallest->left){
smallest = smallest->left;
}
ptr->data = smallest->data;
struct BinaryTree **refsmall = &smallest;
free(*refsmall);
*refsmall = NULL;
}
Aren't these two methods are same? If not can someone explain me how they are different?Why the first method work and second didn't?
You should avoid using global variables in your code. If you really want to use globals the first version of delete should look like this:
void Delete(){
/* at some point you will need to change the 'real' root, not the copy of it */
struct BinaryTree **ptr = &root;
int element;
printf("Enter element to delete : ");
scanf("%d",&element);
while(*ptr){
if(element > (*ptr)->data)
ptr = &(*ptr)->right;
else if(element < (*ptr)->data)
ptr = &(*ptr)->left;
else
break;
}
if((*ptr)->left && (*ptr)->right){
struct BinaryTree **smallest = ptr;
smallest = &(*smallest)->right;
while((*smallest)->left){
smallest = &(*smallest)->left;
}
(*ptr)->data = (*smallest)->data;
free(*smallest);
*smallest = NULL;
} else if((*ptr)->left){
/*rest cases*/
}
}
In the first version you would not be able to delete the root.
struct node {
struct node *l,*r;
int data;
};
void delnode(struct node **pp, int data)
{
struct node *del, *l,*r;
// Walk the tree
while(*pp) {
if ((*pp)->data < data) {pp = &(*pp)->l; continue;}
if ((*pp)->data > data) {pp = &(*pp)->r; continue;}
break; // found it!
}
if (!*pp) return; // not found
del = *pp;
l = del->l;
r = del->r;
// If only one child it wil take del's place.
if (!r) *pp = l;
else if (!l) *pp = r;
// del has two children.
// pick one (R) child, and append the (L) other onto its (Leftmost) shoulder
else {
*pp = r;
for (pp= &del->r; *pp; pp=&(*pp)->l) {;} // find Leftmost NULL pointer in the R tree
*pp = l;
}
free(del);
}
I am trying to create a linked list and sort it by Bubble Sort. I succeeded to create the linked list, but when I am trying to Bubble Sort it, some accidents occur and I do not know the problem. What is the problem?
#include <stdio.h>
#include <stdlib.h>
//the struct of LinkedList
typedef struct Node
{
int data;
struct Node * pNext;
}NODE,*PNODE;
PNODE createList();//Creat one LinkedList
int lengthList(PNODE pHead);//get the length of LinkedList
void sortList(PNODE);//bubble sort
int main()
{
int length;
PNODE pHead=NULL;
pHead=createList();
sortList(pHead);
return 0;
}
//Create LinkedList
PNODE createList()
{
int i,n;
int val;
PNODE pHead=(PNODE)malloc(sizeof(NODE));
if(pHead==NULL)
{
printf("failed to create!\n");
exit(-1);
}
pHead->pNext=NULL;
PNODE pTail=pHead;
printf("please input the length of the LinkedList:");
scanf("%d",&n);
for(i=0;i<n;i++)
{
printf("number %d is:\n",i+1);
scanf("%d",&val);
PNODE pNew=(PNODE)malloc(sizeof(NODE));
if(pNew==NULL)
{
printf("failed to create\n");
exit(-1);
}
pNew->data=val;
pTail->pNext=pNew;
pNew->pNext=NULL;
pTail=pNew;
}
return pHead;
}
//get the length of LinkedList
int lengthList(PNODE pHead)
{
int i=0;
PNODE p=pHead->pNext;
while(p!=NULL)
{
i++;
p=p->pNext;
}
return i;
}
//bubble sort
void sortList(PNODE pHead)
{
int i,j,t,len;
PNODE p,q;
len=lengthList(pHead);
p=pHead->pNext;
for(i=0;i<len-1;i++)
{
for(j=0;j<len-i;j++)
{
q=p->pNext;
if( p->data > q->data)
{
t=p->data;
p->data=q->data;
q->data=t;
}
p=q;//here may be the error
}
}
return;
}
You are running off the end of your list in sortList
p=pHead->pNext;
for(i=0;i<len-1;i++)
{
for(j=0;j<len-i;j++)
{
q=p->pNext;
....
p=q;//here may be the error
}
}
Bug 1) Your list is only len long but you are attempting to advance p to p->pNext far more then len times.
Bug 2) pHead does not need to be a full NODE - it's just a PNODE pointer. You never use its data field. You should have pHead point to the first node in the list, and then start your iteration at pHead rather than pHead->pNext.
Bug 3) You never clean up your memory allocations.
As #Airsource pointed out the bugs, keep in mind most of them are caused because of poor designing choice of your program. Try to do it like below & you will run into less errors
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
typedef struct _Node{
int data;
struct _Node* next;
}Node;
typedef struct {
Node* headPtr;
Node* tailPtr;
unsigned size;
}List;
static void create_node(List* list, int element) {
if (list->headPtr == NULL) {
// List is empty
list->headPtr = (Node* )malloc(sizeof(Node));
list->headPtr->data = element;
list->headPtr->next = 0;
list->tailPtr = list->headPtr;
list->size++;
}else{
// List was already populated
Node* temp = (Node* )malloc(sizeof(Node));
temp->data = element;
temp->next = 0;
list->tailPtr->next = temp;
list->tailPtr = temp;
list->size++;
}
}
void create_list(List* list, int length){
int ele;
int i;
list->headPtr = list->tailPtr = 0;
list->size = 0;
for (i = 0; i < length; i++) {
scanf("%d", &ele);
create_node(list, ele);
}
}
void print_list(List* list){
Node* loop = list->headPtr;
while(loop){
printf("%d ", loop->data);
loop = loop->next;
}
printf("\n");
}
int main(){
List* list;
int n;
printf("Enter the length of the list: ");
scanf("%d", &n);
create_list(list, n);
print_list(list);
bubble_sort(list);
print_list(list);
if (cleanup(list))
printf("Memory rescued!!\n");
else
printf("OOPS!! Error\n");
return 0;
}
Moreover, you can get the size anytime just by list->size. No need for separate function to do that.
Finally to sort it using bubble sort you could do something like this below
void bubble_sort(List* list) {
int i, j;
Node* first, *second;
int temp;
first = list->headPtr;
second = list->headPtr->next;
for (i = 0; i < list->size - 1; i++) {
for (j = 0; j < list->size - i - 1; j++) {
if (first->data > second->data){
temp = first->data;
first->data = second->data;
second->data = temp;
}
first = second;
second = second->next;
}
first = list->headPtr;
second = list->headPtr->next;
}
}
and for cleanup you do this
bool cleanup(List* list) {
Node* curr = list->headPtr;
Node* nxt = list->headPtr->next;
while(nxt){
free(curr);
curr = nxt;
nxt = curr->next;
}
list->headPtr = list->tailPtr = 0;
list->size = 0;
return !nxt ? true: false;
}
There are couple of bugs in your program. I will address them one by one:
Line 28 PNODE pHead=(PNODE)malloc(sizeof(NODE));
Here you are allocating a memory and creating a node before checking if n>0 or not.
Line 36 printf("please input the length of the LinkedList:");
Now up to this point you have created a one node, head node which has no value in it (so contains garbage)
In effect your createList() creates a linked list with n+1 nodes instead of n and the head->value contains garbage.
Solution:
printf("please input the length of the LinkedList:");
scanf("%d", &n);
for(i=0; i<n; i++)
{
PNODE pNew = (PNODE)malloc(sizeof(NODE));
if(pNew == NULL)
{
printf("failed to create!\n");
exit(-1);
}
scanf("%d", &val);
pNew->data = val;
pNew->pNext = NULL;
if (!i)
pHead = pNew;
else
pTail->pNext = pNew;
pTail = pNew;
}
return pHead;
Line 59 PNODE p=pHead->pNext;
Here you are counting nodes starting from the second node (leaving out head). No wonder you will get length as n as you have created a linked list of length n+1 in your createList()
Imagine what if n = 0 and thus pHead = NULL?
Then this line will result in SegFault.
Solution:
change PNODE p=pHead->pNext; to PNODE p = pHead;
Line 73 p=pHead->pNext;
Here you will start sorting excluding the first node, head node.
Also this should be inside the outter for and outside of the inner for to reset the p to first node for each pass.
Line 76 for(j=0;j<len-i;j++)
Here j must be less than len - 1 - i as in pass 1 (i = 0) in the worst case j will be equal to len-1 for j < len-i, where p will point to the last node of linked list and q will be NULL as q = p -> pNext. Which will make q->data to result in SegFault.
To summarise, your sort routine is producing SegFault in the very first Pass and even if it didn't (by properly adjusting the loop-terminating expression in inner for) the outer for loop is contributing nothing towards the sorting except increasing the time complexity.
Solution:
for(i = 0; i < len - 1; i++)
{
p = pHead;
for(j = 0; j < len - 1 - i; j++)
{
q = p -> pNext;
if(p->data > q->data)
{
t = p -> data;
p -> data = q -> data;
q -> data = t;
}
p = q;
}
}
A question:
How are you checking whether element have been sorted or not?
A printList() routine would have been helpful in spotting the above bugs.
"Always verify whether you correctly stored the input or not by explicitly printing the same before processing it!"
Write a function that rearranges a linked list to put the nodes in even positions after the nodes in odd positions in the list, preserving the relative order of both the evens and the odds.
I found this problem in the book Algorithm in c writtern by Sedgewick. I have tried but failed. I trid to put all nodes in even positions on another linked list. It's grateful for you to help me. A good idea is enough. Thanks :).
This is my Code in C.
/*
* File: rearranges.c <Exercise 3.36>
* Note: Write a function that rearranges a linked list to put the nodes in even
* positions after the nodes in odd positions in the list, preserving the
* relative order of both the evens and the odds.
* NOTICE: I think it's necessary to use linked list with a dummy head.
* Time: 2013-10-26 10:58
*/
#include <stdio.h>
#include <stdlib.h>
#define LEN 11
typedef struct node *link;
struct node {
int item;
link next;
};
/* Traverse a linked list with a dummy head. */
void traverse(link t) {
link x = t->next;
while (x != NULL) {
printf("%d ", x->item);
x = x->next;
}
putchar('\n');
}
/* Detach even positon nodes from a linked list. */
link detach(link t) {
link u = malloc(sizeof(*u));
link x = t, y = u;
/* x is odd position node. We should ensure that there's still one even
* position node after x. */
while (x != NULL && x->next != NULL) {
y->next = x->next;
x->next = x->next->next;
x = x->next;
y = y->next;
y->next = NULL;
}
return u;
}
/* Combine two linked list */
link combine(link u, link t) {
link x = u;
link y = t->next;
while (y != NULL) {
link n = y->next;
y->next = x->next;
x->next = y;
x = x->next->next;
y = n;
}
return u;
}
/* The function exchanges the position of the nodes in the list. */
link rearranges(link t) {
link u = detach(t);
link v = combine(u, t);
return v;
}
int main(int argc, char *argv[]) {
int i;
link t = malloc(sizeof(*t));
link x = t;
for (i = 0; i < LEN; i++) {
x->next = malloc(sizeof(*x));
x = x->next;
x->item = i;
x->next = NULL;
}
traverse(t);
traverse(rearranges(t));
return 0;
}
curr=head;
end=lastOfList;//last node if size of list is odd or last-1 node
for(int i=1;i<=listSize()/2;i++)
{
end->next=curr->next;
end=end->next;
end->next=null;
if(curr->next!=null)
if((curr->next)->next!=null)
curr->next=(curr->next)->next;
curr=curr->next;
}
You can implement a recursive solution where each call returns an updated node that will serve as the new next reference for the upper caller. We just have to go down the list until we find the last element, and then move every even node to the end of the list, and update the reference to the last element. Here's my solution (please try to do it yourself before looking at my and other solutions):
struct node {
int val;
struct node *next;
};
struct node *reorder_aux(struct node *l, int count, struct node **last);
struct node *reorder(struct node *l) {
struct node *x;
if (l == NULL)
return NULL;
return reorder_aux(l, 1, &x);
}
struct node *reorder_aux(struct node *l, int count, struct node **last) {
struct node *n;
if (l->next == NULL) {
*last = l;
return l;
}
n = reorder_aux(l->next, count+1, last);
if (count & 1) {
l->next = n;
return l;
}
else {
(*last)->next = l;
l->next = NULL;
*last = l;
return n;
}
}
At each step, if the current node l is an even node (as determined by count), then we append this node to the end, and tell the upper caller that its next pointer shall be updated to our next (because our next will be an odd node). In case we're an odd node, we just have to update our next pointer to whatever the recursive call returned (which will be a pointer to an odd node), and return the current node, since we will not move ourselves to the end of the list.
It's a nice exercise!
#include <stdio.h>
struct list {
struct list *next;
int ch;
};
void swap_odd_even (struct list **pp)
{
struct list *one, *two ;
for( ; (one = *pp) ; pp = &one->next) {
two = one->next;
if (!two) break;
*pp = two;
one->next = two->next;
two->next = one;
}
}
struct list arr[] =
{ {arr+1, 'A'} , {arr+2, 'B'} , {arr+3, 'C'} , {arr+4, 'D'}
, {arr+5, 'E'} , {arr+6, 'F'} , {arr+7, 'G'} , {arr+8, 'H'}
, {arr+9, 'I'} , {arr+10, 'J'} , {arr+11, 'K'} , {arr+12, 'L'}
, {arr+13, 'M'} , {arr+14, 'N'}, {arr+15, 'O'} , {arr+16, 'P'}
, {arr+17, 'Q'} , {arr+18, 'R'} , {arr+19, 'S'} , {arr+20, 'T'}
, {arr+21, 'U'} , {arr+22, 'V'}, {arr+23, 'W'} , {arr+24, 'X'}
, {arr+25, 'Y'} , {NULL, 'Z'} };
int main (void) {
struct list *root , *ptr;
root = arr;
for (ptr=root ; ptr; ptr = ptr->next ) {
printf( "-> %c" , ptr->ch );
}
printf( "\n" );
printf( "Swap\n" );
swap_odd_even ( &root);
for (ptr=root ; ptr; ptr = ptr->next ) {
printf( "-> %c" , ptr->ch );
}
printf( "\n" );
return 0;
}
In the following, every time swap_nodes is called another odd sinks to the last sunk odd. The evens are grouped together on each iteration and they bubble up to the end of the list. Here is an example:
/*
[0]-1-2-3-4-5
1-[0-2]-3-4-5
1-3-[0-2-4]-5
1-3-5-[0-2-4]
*/
#include <stdio.h>
#include <stdlib.h>
#define LIST_LENGTH 10
struct node{
int id;
struct node *next;
};
void print_list(struct node *current)
{
while(NULL != current){
printf("node id = %d\n",current->id);
current = current->next;
}
printf("Done\n");
}
struct node *swap_nodes(struct node *head_even, struct node *tail_even, struct node *next_odd)
{
tail_even->next = next_odd->next;
next_odd->next = head_even;
return next_odd;
}
struct node *reorder_list(struct node *head)
{
struct node *head_even;
struct node *tail_even;
struct node *next_odd;
struct node *last_odd;
if(NULL == head->next){
return head;
}
head_even = head;
tail_even = head;
next_odd = head->next;
last_odd = head->next;
head = swap_nodes(head_even, tail_even, next_odd);
if(NULL != tail_even->next){
tail_even = tail_even->next;
}
while (NULL != tail_even->next) {
next_odd = tail_even->next;
last_odd->next = swap_nodes(head_even, tail_even, next_odd);
last_odd = last_odd->next;
if(NULL != tail_even->next){
tail_even = tail_even->next;
}
}
return head;
}
int main(void)
{
int i;
struct node *head = (struct node *) malloc(LIST_LENGTH*sizeof(struct node));
struct node *mem = head;
if(NULL == head){
return -1;
}
struct node *current = head;
for(i=0;i<LIST_LENGTH-1;i++){
current->next = current + 1;
current->id = i;
current = current->next;
}
current->next = NULL;
current->id = i;
head = reorder_list(head);
print_list(head);
free(mem);
return 0;
}
I am writing a C program to represent polynomial in linked list. Here is what I have done so far.
# include <stdio.h>
# include <stdlib.h>
struct poly
{
float coef;
int exp;
struct poly* next;
};
void make(struct poly**, float, int);
void display(struct poly*);
void add(struct poly*, struct poly*, struct poly**);
int main()
{
struct poly *first, *second, *final;
int expa, expb, i;
float data;
first = second = final = NULL;
printf("Enter maximum exponent for polynomial A ");
scanf("%d", &expa);
printf("Enter data for polynomial A\n");
for(i=0;i<=expa;i++)
{
printf("Enter coefficient for exponent %d ", expa - i);
scanf("%f", &data);
make(&first, data, expa - i);
}
printf("Displaying polynomial A ");
display(first);
printf("Enter maximum exponent for polynomial B ");
scanf("%d", &expb);
printf("Enter data for polynomial B\n");
for(i=0;i<=expb;i++)
{
printf("Enter coefficient for exponent %d ", expb - i);
scanf("%f", &data);
make(&second, data, expb - i);
}
printf("Displaying polynomial B ");
display(second);
printf("Now adding polynomials A and B \n");
add(first, second, &final);
display(final);
return 1;
}
void make(struct poly**head, float coef, int exp)
{
struct poly *new, *temp;
new = (struct poly*)malloc(sizeof(struct poly));
new->coef = coef;
new->exp = exp;
new->next = NULL;
temp = *head;
if(temp == NULL)
{
*head = new;
return;
}
while(temp->next)
temp = temp->next;
temp->next = new;
}
void display(struct poly*head)
{
struct poly*temp = head;
while(temp)
{
printf("%.1fx^%d ", temp->coef, temp->exp);
temp = temp->next;
}
printf("\nExiting display\n");
}
void add(struct poly*first, struct poly*second, struct poly**sum)
{
struct poly* new;
printf("Currently in add");
if(first == NULL && second == NULL)
return;
while(first&&second)
{
if((*sum)==NULL)
{
new = (struct poly*)malloc(sizeof(struct poly));
*sum = new;
}
else
{
new->next = (struct poly*)malloc(sizeof(struct poly));
new = new->next;
}
if(first->exp == second->exp)
{
new->exp = first->exp;
new->coef = first->coef + second->coef;
first = first->next;
second = second ->next;
}
if(first->exp > second->exp)
{
new->exp = first->exp;
new->coef = first->coef;
first = first->next;
}
if(first->exp < second->exp)
{
new->exp = second->exp;
new->coef = second->coef;
second = second->next;
}
new->next = NULL;
}
while(first)
{
new->next = (struct poly*)malloc(sizeof(struct poly));
new->coef = first->coef;
new->exp = first->exp;
new->next = NULL;
first = first->next;
}
while(second)
{
new->next = (struct poly*)malloc(sizeof(struct poly));
new->coef = second->coef;
new->exp = second->exp;
new->next = NULL;
second= second->next;
}
}
I am receiving output:
./PolynomialAdditionLinkedList.out
Enter maximum exponent for polynomial A 2
Enter data for polynomial A
Enter coefficient for exponent 2 1
Enter coefficient for exponent 1 2
Enter coefficient for exponent 0 1
Displaying polynomial A 1.0x^2 2.0x^1 1.0x^0
Exiting display
Enter maximum exponent for polynomial B 2
Enter data for polynomial B
Enter coefficient for exponent 2 1
Enter coefficient for exponent 1 6
Enter coefficient for exponent 0 9
Displaying polynomial B 1.0x^2 6.0x^1 9.0x^0
Exiting display
Now adding polynomials A and B
Segmentation fault (core dumped)
From the output, it looks like I have error in following line.
add(first, second, &final);
As the output doesn't printsCurrently in add`, error occurs before it. I believe I haven't modified values of either first or second in any illegal way ?
Where am I making a mistake ?
In the add function you have this code:
if(first->exp == second->exp)
{
new->exp = first->exp;
new->coef = first->coef + second->coef;
first = first->next;
second = second ->next;
}
if(first->exp > second->exp)
{
new->exp = first->exp;
new->coef = first->coef;
first = first->next;
}
if(first->exp < second->exp)
{
new->exp = second->exp;
new->coef = second->coef;
second = second->next;
}
Now think for a second what happens when, in the first if statement, you are at the last node of one of the lists. That means that you will set first or second to NULL. Then what happens with the other if statements? You will dereference a NULL pointer!
What you want is an if-else if chain instead.
You can simplify the add() function a lot by removing repetition, merging common cases. The below function uses goto which is not as harmful as you might think:
struct poly *merge(struct poly *one, struct poly *two)
{
struct poly *new,*result, **pp;
fprintf(stderr, "Currently in merge\n");
result=NULL;
for(pp= &result; one || two; pp = &(*pp)->next ) {
*pp = new = malloc (sizeof *new);
new->next = NULL;
if (!one) goto use_two;
if (!two) goto use_one;
/* when we get here, one and two are both non-null */
if (one->exp > two->exp) goto use_one;
if (one->exp < two->exp) goto use_two;
if (one->exp == two->exp) goto use_both;
use_both: /* useless label for clarity */
new->coef = one->coef + two->coef;
new->exp = two->exp;
two = two->next;
one = one->next;
continue;
use_two:
new->coef = two->coef;
new->exp = two->exp;
two = two->next;
continue;
use_one:
new->coef = one->coef;
new->exp = one->exp;
one = one->next;
continue;
}
return result;
}
this should be called from main as:
...
printf("Now adding polynomials A and B \n");
// add(first, second, &final);
final = merge (first, second);
display(final);
return 0; // <<-- main() should return 0 or EXIT_SUCCESS
}
A few notes:
I changed the function's signature, it now returns the created linked list of terms, instead of assigning it to a pointer-to-pointer passed as an argument
You could try to replace the gotos and the three labels by a switch, or by inlined functions, or macros. The result will be a lot messier, and at least less compact.
the special cases where one of the one or two lists are exhausted are now in the main loop. There are no special cases.
thse special case where the first result node is assigned to *head is merged with the normal case (where *head is not NULL) just by moving *pp to the next place for insertion. Again: there are no special cases.
Segmentation fault (core dumped)
Since it has segfaulted and generated a core file, you could fire up gdb or your debugger of choice and see exactly where it crashed.
If you post that, it might help.
as Alter Mann pointed out, you use new uninitialised in add:
else
{
new->next = (struct poly*)malloc(sizeof(struct poly));
if SUM is non -null, you go into this case, and on the first iteration new has not been allocated, and so you are dereferencing some random pointer. Which isnt NULL, since you dont initialise it, and so even if you did check new for NULL, it would likely still segfault.
void add(struct poly*first, struct poly*second, struct poly**sum)
{
struct poly* new;
should be:
void add(struct poly*first, struct poly*second, struct poly**sum)
{
struct poly* new=NULL;
This line does not check new, it checks sum.
if((*sum)==NULL)
{
EDIT: One last thought. You don't actually check that malloc succeded anywhere.
I am supposed to do a program which can do polynomial addition/subtraction/multiplication/evaluation using circular linked list.
My multiplication code is going in infinite loop, and I have marked a comment where it is happening (detected with printf statements, removed).
list* poly_mul(list *p1, list *p2) {
term tmp;
list *result = malloc(sizeof(list));
memcpy(result, p1, sizeof(list));
node *b = p2->head;
node *r = result->head;
do {
do {
tmp.exp = r->data.exp + b->data.exp;
tmp.coeff = r->data.coeff * b->data.coeff;
unsigned int add_term = 1;
node *c = result->head;
do {
if(c->data.exp == tmp.exp) {
c->data.coeff += tmp.coeff;
add_term = 0;
break;
}
c = c->next;
//Here it goes in infinite loop
} while(c != result->head);
if(add_term)
node_add(result, &tmp);
b = b->next;
} while(b != p2->head);
r = r->next;
} while(r != result->head);
return result;
}
The structures used are here:
typedef struct {
int exp;
int coeff;
} term;
typedef struct node {
term data;
struct node *next;
} node;
typedef struct {
node *head;
node *tail;
unsigned int count;
} list;
And this is the code in main:
void main() {
list p1, p2, *p3;
p1.count = p2.count = 0;
poly_create(&p1);
p3 = poly_mul(&p1, &p2);
poly_print(p3);
}
void poly_create(list *l) {
int i, n;
printf("\nEnter number of terms in the polynomial: ");
scanf("%d", &n);
for(i = 1; i <= n; i++) {
printf("\nEnter details for term %d: ", i);
term_append(l);
}
void node_add(list *l, term *t) {
node *tmp = malloc(sizeof(node));
memcpy(&tmp->data, t, sizeof(term));
if(l->count == 0) {
l->head = tmp;
l->tail = tmp;
tmp->next = tmp;
}
else {
l->tail->next = tmp;
tmp->next = l->head;
l->tail = tmp;
}
l->count++;
}
void term_append(list *l) {
term t;
enter:
printf("\nEnter term as <coefficient>,<exponent>: ");
scanf("%d,%d", &t.coeff, &t.exp);
if(!t.coeff) {
printf("\nCoefficient is zero, reenter term");
goto enter;
}
if(l->count >= 1) {
node *i = l->head;
do {
if(i->data.exp == t.exp) {
printf("\nExponent %d was already entered, reenter term", t.exp);
goto enter;
}
i = i->next;
} while(i != l->head);
node_add(l, &t);
}
else
node_add(l, &t);
}
Please get me a solution for this problem, I've been trying to solve this for the past three hours.
Why is it going into an infinite loop? You can find out by using a debugger and stepping through the code. Just put a breakpoint at the appropriate place and you should be able to find it yourself. In all likelihood, you have a loop in your linked list.
You can check for loops in your linked list with two pointers. The first one (tail) point to the start of your list. The second (head) points to the second element of your list. Loop till head is past the last element (I have those pointed to NULL, not head) by incrementing both head and tail by one. If at any point tail > head, you have a loop.
What happens if you printf("%d",(int) c); at each iteration? I suspect that result->head is pointing to a node which is pointing to a member of the linked list, but is not in the linked list itself.
Potential test: Add a int seen to each member of the list and increment it on each member as you loop for a given number of nodes (something excessively high such as INT_MAX) and, when the loop stops, see if result->head->seen > 0:
typedef struct node {
term data;
struct node *next;
// to be removed later
int seen;
} node;
// place this before you get the infinite loop
unsigned int i = 1;
c->seen = 0;
do
{
c = c->next;
c->seen = i;
// replace INT_MAX with some number which is greater than the maximum list length
} while(++i <= INT_MAX);
// this should be roughly equal to i (might be off by 1).
// I'll bet it isn't though!
printf("result->head->seen = %d", result->head->seen);
One possible cause: you're never creating p2. Are you missing a line like this in your main function:
poly_create(&p2);
?