Split Linked list - c

I'm new to C programming and I kinda need some help in the frontBackSplitLinkedList part,
For example, assume that given linked list is: 2 6 7 8 9
The resulting front and back are:
front: 2 6 7
back: 8 9
I've searched through some websites but most of the codings are using nodes instead of linked list.
Any idea how to do this? Thank you!

You do not actually have to count elements in list, as far as i see it, you store the number of elements in _linkedlist. You can always use that value to split however you like. I would strongly suggest to first simlify your List, so it can add elements only to the back or the front of the List, it will be easier to work with it, but won't really affect the principle of split function.

If I understand your question correcly then you want to split the list in the middle, where un uneven list will be split a frontlist that is one larger than the backlist.
First of all you must have a count of the list length. I propose that you walk the list, counting the number of list nodes.
Then you divide that number as follows:
count = (count+1)/2;
Now we need to know if you must create two new lists (so you have to make copies of all the list nodes), or whether the old list may be reused. Assume it may be reused, then you assign the old list to frontlist, walk count listnodes, asign that one to backlist and set the next member of the one before it to NULL.
You are done now, except that the caller may no longer use the original list (it has become equivalent, and actually is, frontlist).

Related

algorithm/data structure for this "enumerating all possibilities" task (combinatorial objects)

This is probably a common question that arises in search/store situations and there is a standard answer. I'm trying to do this from intuition and am somewhat out of my comfort zone.
I'm attempting to generate all of a certain kind of combinatorial object. Each object of size n can be generated from an object of size n-1, usually in multiple ways. From the single object of size 2, my search generates 6 objects of size 3, about 140 objects of size 4, and about 29,000 objects of size 5. As I generate the objects, I store them in a globally declared array. Before storing each object, I have to check all the previous ones stored for that size, to make sure I didn't generate it already from an earlier (n-1)-object. I currently do this in a naive way, which is just that I go through all the objects currently sitting in the array and compare them to the one currently being generated. Only if it's different from every single one there do I add it to the array and increment the number of objects currently in there. The new object is just added as the most recent object in the array, it is not sorted, and so this is obviously inefficient, and I can't hope to generate the objects of size 6 in this way.
(To give an idea of the problem of the growth of the array: the first couple of 4-objects, from among the 140 or so, give rise to over 2000 new 5-objects in a fraction of a second. By the time I've gotten to the last few 4-objects, with over 25,000 5-objects already stored, each 4-object generates only a handful of previously unseen 5-objects, but takes several seconds for the process for each 4-object. There is very little correlation between the order I generate new objects in, and their eventual position as a consequence of the comparison function I'm using.)
Obviously if I had a sorted array of objects, it would be much more efficient to find out whether I'm looking at a new object: using a binary midpoint search strategy I'd only have to look at roughly log_2(n) of the n objects currently stored, instead of all n of them. But placing the newly generated object at the right place in an array means moving half of the existing ones, on average, to make room for it. (I would implement this with an array of pointers pointing to the unsorted array of object structs, so that I only had to move pointers instead of moving data, but it still seems like a lot of pointers to have to repoint at each insert.)
The other option would be to place the objects in a linked list, as insertion is very cheap in that situation. But then I wouldn't have random access to the elements in the linked list--you can only find the right place to insert the newly generated object (if it's actually new) by traversing the list node by node and comparing. On average you'd have to traverse half the list before finding the right insertion point, which doesn't sound any better than repointing half the pointers.
Is there a third choice I'm missing? I could accomplish this very easily if I had both random access to stored elements so I could find the insertion point quickly (in log_2(n) steps), and I could insert new objects very cheaply, like in a linked list. Am I dreaming?
To summarise: I need to be able to determine whether an object is new or duplicates an existing one, and I need to be able to insert an object at the right place. I don't ever need to delete an object. Thank you.

What would be the optimal way to sort a long list of words in alphabetical order in C?

As the title indicates, I need to order quite a few (hundreds of thousands) strings in alphabetical order. I have several linked lists and each linked list contains words of a specific length. That is, I have a 6 letter strings list, 7 letter strings list, ... , 10 letter strings list.
I was thinking of using radix sort, but I wanted to see if there were better options out there since I can't find anything specific when it comes to alphabetizing a list where all the words are the same length.
EDIT:
I have an extremely long list of words, raging in size. I'm currently walking through the list and arranging the words into size categories. That is, when I encounter a word of length 6 it goes into the "6-length" list. As I'm doing this for each word, I am actually creating a new word object that contains the original word and its alphabetized version (e.g. stack, ackst). I want to alphabetize each "length" list such that I could easily find and group anagrams.
I don't think the fact that the lengths are the same matters to sorting, does it? You don't explain how you think that would affect sorting.
My recommended approach for sorting a linked list: don't. :) Sort an array instead, and convert to/from the linked list as needed. It will very likely be much faster and easier.
Basically:
Walk the list to figure out the length.
Allocate an array of value pointers (in your case, "value" means string).
Walk the list again, setting the i:th array element to point to the i:th list item's data.
Sort the array with qsort().
Walk the list a third time, overwriting the i:th item's data with the i:th array element
Done.
You can do this for each linked list separately, of course.

Writing top 10 scores to file

I'm writing a blackjack program and would like to be able to write the top scores to a file. Obviously the first few times the program is run it will populate the high score list with every score, after which I'd like only scores that are greater than the number 10 score to be added, and the initial number 10 score (now number 11) to be deleted. I've been thinking of using a linked list like this:
struct highScore
{
char name;
int score;
highScore *next;
};
My knowledge of linked lists is pretty basic so I intend on doing my research before I can actually code it.
I'm wondering if I'm overcomplicating this and if there's a simpler way to get the job done, or am I on the right track here?
I do not think that linked list is best approach. Do not take me wrong, but linked list is used to add and to remove at random position, most commonly at beginning or end. Problem whit linked list is that it has same inefficiency to find element as ordinary array, becuase it has to check each element until it finds one.
I think that using array will make your program having same efficiency and less complicated code.
Comparing both data structures (linked list and array):
Finding element is in both case proportional to length in average.
Inserting element at end is constant in both structures.
Linked lists are efficient to add element at any position, but position has to be found, so this compensates whit problem that array has, where you have to move right elements by one position on right.
I think that something like
typedef struct
{
int score;
char name[51]; //name should hold 50 chars and null
} highScore;
highScore scores[10]; // voilla 10 scores
//or if you need little bit of complications
//and more speed when moving array during insertion
highScore * scorespointer[10]; //array of 10 pointers on score
Will make simple solution whit same efficiency as linked list.
If you implement your structure as linked list you will not be able to serialize this directly in file, because you can store only name and score, but not pointer on next highScore. Pointers can not be stored in file, because they are dynamical allocated and are valid only during program lifetime.
If you are disappointed whit this solution, you can check heap and tree for ultimate efficency for more than few (like in your case) scores.
I think your approach looks good. Using a linked list for this makes sense, or even a queue (which can be implemented using a linked list).
A linked list is certainly a good way to do this. It keeps the data related to a score together and with some basic bookkeeping you can keep it up to date. When you keep it sorted, you can easily insert new scores at the right place and remove too low scores from the linked list.
An alternative is to maintain two arrays with 10 elements each, one for the names and one for the scores but this has several drawbacks:
If you're going to add more information later, you'll need another array and more importantly,
Any operation that you do on one array also needs to be done on the other which can cause trouble later on (bugs).
So, in short, your solution looks good.
Just to understand your requirement:
the program runs and a score is obtained
you read the scores file into a list and check the new score against the old top scores
you modify the list and write it back to the file
program exits.
If this is correct, then a linked list seems like overkill. An array would do the job fine. Read each entry from the file into the array, inserting the new score as you go. You could forego the array altogether and just write out to a file each score you read in, again inserting the new score as you go. Then rename the files (scores.txt becomes scores.bak, scores.new becomes scores.txt) - this way you get a backup of the scores file too. Note that your file is best written as text (ie. not binary).
As has been stated, your structure will not compile as pure C code. If you want to write in C as opposed to C++, you should make your compiler reject C++. How you do that depends upon your platform, but it might just be a matter of naming the file scores.c instead of scores.cpp.

Adding Elements Of Two Linked List To Form Third Linked List

I need a little help with my new assignment.
Problem:
Given Two Linked List representation of a decimal numbers(238 & 35):- 2->3->8 and, 3->5
Add elements so that your Final Linked List must be 2->7->3.
What could be the best approach to solve this problem.
Without doing your homework for you - I think the best general approach would be to break it into three steps.
Reverse both the lists.
Add the elements pairwise, carrying a one where necessary.
Reverse the resulting list.
Since step 1 and step 3 are kind of the same, you probably want to write a separate function for this.
Give it a try, and post again if you need more help.

Sorting a linked list and returning to original unsorted order

I have an unsorted linked list. I need to sort it by a certain field then return the linked list to its previous unsorted condition. How can I do this without making a copy of the list?
When you say "return the linked list to its previous unsorted condition", do you mean the list needs to be placed into a random order or to the exact same order that you started with?
In any case, don't forget that a list can be linked into more than one list at a time. If you have two sets of "next"/"previous" pointers, then you can effectively have the same set of items sorted two different ways at the same time.
To do this you will need to either sort and then restore the list or create and sort references to the list.
To sort the list directly Merge Sort is most likely the best thing you could use for the initial sort, but returning them to their original state is tricky unless you either record your moves so you can reverse them or store their original position and resort them using that as the key.
If you would rather sort the references to the list instead you will need to allocate enough space to hold pointers to each node and sort that. If you use a flat array to store the pointers then you could use the standard C qsort to do this.
If this is an assignment and you must implement your own sort then if you don't already know the length of the list you could take advantage of having to traverse it to count its length to also choose a good initial pivot point for quicksort or if you choose not to use quicksort you can let your imagination go wild with all kinds of optimizations.
Taking your points in reverse order, to support returning to original order, you can add an extra int field to each list node. Set those values based on the original order, and when you need to return it to the original order, just sort on that field.
As far as the sorting in general goes, you probably want to use something like a merge-sort or possibly a Quick-sort.
You can make that data structure somewhat like this.
struct Elem {
Elem* _next;
Elem* _nextSorted;
...
}
Then you can use any algo for sorting the list (maybe merge sort)
If you want to keep your linked list untouched, you should add information to store the ordered list of elements.
To do so, you can either create a new linked list where each element points to one element of your original linked list. Or you can add one more field in the element of your list like sorted_next.
In any case, you should use a sequential algorithm like mergesort to sort a linked list.
Here is a C source code of mergesort for linked lists that you could reuse for your project.
I guess most of the answers have already covered the usual techniques one could use. As far as figuring out the solution to the problem goes, a trick is to look at the problem and think if the human mind can do it.
Figuring out the original random sequence from a sorted sequence is theoretically impossible unless you use some other means. This can be done by
a)modifying the linked list structure (as mentioned above, you simply add a pointer for the sorted sequence separately). This would work and maybe technically you are not creating a separate linked list, but it is as good as a new linked list - one made of pointers.
b)the other way is to log each transition of the sorting algo in a stack. This allows you to not be dependent on the sorting algorithm you use. For example when say node 1 is shifted to the 3rd position, you could have something like 1:3 pushed to the stack. The notation, of course, may vary. Once you push all the transitions, you can simply pop the stack to give take it back to the original pattern / any point in between. This is more like
If you're interested in learning more about the design for loggers, I suggest you read about the Command Pattern

Resources