Consider a linked list whose nodes are chars, so the list represents a string. How do you write a recursive routine to check whether the string is a palindrome such that
the the said function starts unwinding the stack when it processes the character(s) at the middle of the string?
For example, suppose that my string is "madam". My recursive function looks something like:
bool isPalin(const node *startnode, const node *currentnode, const node *midpoint, ...);
When currentnode->data == 'd', the stack has to unwind.
I was asked this question for an interview; at the moment I can't think of any use for this question except as a very hard puzzle.
First thoughts: A very obvious (if inelegant) way is to:
Compute the midpoint of the list first.
If currentnode is "before" midpoint , push former into a stack manually. This can be decided by maintaining a counter.
Otherwise, unwind the manually maintained stack at every step of the recursion, and compare with the current character.
Any better ideas or fresh insights?
By "linked list", do you mean std::list?
template <typename BiDiIterator>
bool isPalindrome(BiDiIterator first, BiDiIterator last) {
if (first == last) return true;
--last;
if (first == last) return true;
if (*first != *last) return false;
return isPalindrome(++first, last); // tail recursion FTW
}
isPalindrome(mylist.begin(), mylist.end());
I've used the fact that it's possible to iterate back from the end as well as forward from the start. It is not clear whether this is given by the question.
With a singly linked list you can run two iterators, one fast and one slow. On each call, increment the fast one twice and the slow one once. When the fast one reaches the end of the list, the slow one is at the midpoint (um, +/- 1 and taking account of odd-length and even-length lists). At that point, back out of your recursion comparing character values. Θ(n) complexity for runtime and memory use (not tail recursive).
I'd write the code, but it's time for bed here in the UK.
[Edit: morning all
template <typename FwdIterator>
std::pair<FwdIterator, bool> isPalindrome(FwdIterator slow, FwdIterator fast, FwdIterator last) {
if (fast == last) return std::make_pair(slow, true);
++fast;
if (fast == last) return std::make_pair(++slow, true);
++fast;
FwdIterator next = slow;
std::pair<FwdIterator, bool> result = isPalindrome(++next, fast, last);
if (result.second == false) return result;
if (*slow != *(result.first)) return std::make_pair(slow, false);
++(result.first);
return result;
}
...
isPalindrome(mylist.begin(), mylist.begin(), mylist.end()).second;
If, for some bizarre reason, your linked list doesn't provide an iterator, then hopefully the equivalent code with if (fast->next == 0), fast = fast->next, etc, is obvious. And of course you can tidy up the user interface with a wrapper.
I think you can avoid the additional storage if you're allowed to temporarily modify the list, by reversing the list up to "slow" as you descend, then reversing it again as you ascend. That way you don't need to store a copy of slow across the recursive call: instead you can return an extra pointer for the caller to follow. I'm not going to bother, though.
]
Modulo thorny details this one's easy.
First, find the midpoint by calling recursively moving one pointer just one step but other two steps. When two-step pointer reaches end one-step pointer is at middle. Thorny thing: even versus odd length list.
Then back up (returning from the recursive calls), and while backing move midpointer one step forward for each return. Just compare that node's contents with contents available as routine argument during descent.
Cheers & hth.,
If you do feel like using a stack, this is a common exercise in computation theory using nondeterministic pushdown automata. The idea is to push every char onto the stack and at each char, branch off, with one branch skipping a char (in case it's an odd palindrome) and popping each char off the stack while comparing it to one in the remainder of the list, another branch doing the same without skipping that initial char (in case it's an even palindrome), and the third continuing to add elements to the stack (and recursively beginning the branching again with the next char). These three branches could be represented by passing the current state of the stack into each one recursively.
In pseudocode:
function isPalin(* start, * end, stack){
if checkPalin(start, end, stack):
return true;
stack.push(*start);
if checkPalin(start, end, stack):
return true;
if (start == end)
return false;
return isPalin(start.next, end, stack);
}
function checkPalin(* start, * end, stack){
while (stack is not empty && start != end){
start = start.next;
if (*start != stack.pop())
return false;
}
return (stack is empty && start == end);
}
Is the list doubly linked? Then it's a matter of passing in the start and end nodes, compare what they point to. If they're different, return false. If they're the same, call yourself recursively with start+1 and end-1, until start > end.
this is what the asked I think
bool isPalindrom(node* head)
{
if(!head) return true;
node* left = head;
node* mid = head;
return cmp(left, mid, head);
}
bool cmp(node*& left, node*& mid, node* n)
{
node* next = n->next;
if(next == 0)
{
node* lprev = left;
left = left->next;
return lprev->data == n->data;
}
mid = mid->next;
if(next->next == 0)
{
node* lprev = left;
left = left->next->next;
return lprev->data == next->data && lprev->next->data == n->data;
}
if(!cmp(left, mid, next->next)) return false;
if(left == mid) return true;
if(left->data != next->data) return false;
left = left->next;
if(left == mid) return true;
if(left->data != n->data) return false;
left = left->next;
return true;
}
In Java, this solution will compare the string already read against the string that comes recursively. It's not the best solution as even when it's O(n) it's S(n^2) and it should (at least) use StringBuffer to reduce all the concatenations.
It makes use of a wrapper class to pass back the right side of the string along with the boolean.
pros:
only one pass to the list, from head to end.
it doesn't need to know in advance the list length
no extra data structures needed
cons:
uses loads of memory S(n^2)
concatenates strings in an inefficient way
recursive solution, slow.
Code:
boolean palindrome(Node n){
RightSide v = palindromeRec(“”, n);
return v.palindrome;
}
class RightSide{
boolean palindrome;
String right;
}
private RightSide palindromeRec(String read, Node n){
RightSide v = new RightSide();
if(n == null){
v.palindrome = false;
v.right = “”;
return v;
}
v = palindromeRec(n.value + read, n.next);
if(v.palindrome)
return v;
else if(read.equals(v.right) || (n.value+read).equals(v.right)){
v.palindrome = true;
return v;
}
v.right = n.value + v.right;
v.palindrome = false;
return v;
}
Find the length of the total string
Get the node that has the mid (middle) position
Break the List at that node
Reverse the first half
Now do string compare
include "stdafx.h"
include "LinkedList.h"
LinkedList::LinkedList()
{
head = nullptr;
count = 0;
}
void LinkedList::AddItem(char* data)
{
Node node = new Node;
node->Data = (void) malloc(strlen(data) + 1);
strcpy((char*)node->Data, data);
node->Data = data;
node->Next = nullptr;
count++;
if(head == nullptr)
{
head = node;
head->Next = nullptr;
return;
}
Node *temp = head;
while(temp->Next!=nullptr)
{
temp = temp->Next;
}
temp->Next = node;
}
void LinkedList::TraverseList()
{
Node *temp = head;
while(temp !=nullptr)
{
printf("%s \n", temp->Data);
temp = temp->Next;
}
}
Node* LinkedList::Reverse()
{
if(!head || !(head->Next))
{
return head;
}
Node* temp = head;
Node* tempN = head->Next;
Node* prev = nullptr;
while(tempN)
{
temp->Next = prev;
prev= temp;
temp = tempN;
tempN = temp->Next;
}
temp->Next = prev;
head = temp;
return temp;
}
bool LinkedList::IsPalindrome()
{
int len = 0;
Node* temp = head;
while(temp)
{
len = len + strlen((char*)temp->Data);
temp = temp->Next;
}
printf("total string length is %d \n", len);
int i =0;
int mid1 = 0;
temp = head;
while (i < len/2)
{
int templen = strlen((char*)temp->Data);
if(i + strlen((char*)temp->Data) < (len /2))
{
i = i + strlen((char*)temp->Data);
temp = temp->Next;
}
else
{
while(i < len/2)
{
mid1++;
i++;
}
break;
}
}
printf("len:%d, i:%d, mid1:%d mid2:%d \n",len, i, mid1, len-mid1);
Node* secondHalf = temp->Next;
temp->Next = nullptr;
Node *firstHalf = Reverse();
char* str1 = (char*)malloc(sizeof(char) * mid1 + 1);
char* str2 = (char*)malloc(sizeof(char) * mid1 + 1);
memcpy(str1, (char*)firstHalf->Data, mid1);
str1[mid1] = '\0';
int slen = strlen((char*)temp->Data);
if(slen > mid1)
{
memcpy(str2, (char*)firstHalf->Data + mid1, slen-mid1);
str2[slen-mid1] = '\0';
}
else
{
str2[0] = '\0';
}
printf("%s, %s", str1, str2);
str1 = strrev(str1);
if(!*str2)
{
str2 = (char*)secondHalf->Data;
secondHalf = secondHalf->Next;
}
if(*str2 && len%2 == 1)
{
str2++;
if(!*str2)
{
str2 = (char*)secondHalf->Data;
secondHalf = secondHalf->Next;
}
}
while(*str1 && *str2)
{
if(*str1 != *str2)
{
return false;
}
str1++;
str2++;
if(!*str1)
{
retry:
firstHalf = firstHalf->Next;
if(firstHalf)
{
str1 = (char*) malloc(strlen((char*)firstHalf->Data) + 1);
strcpy(str1,(char*)firstHalf->Data);
str1 = strrev(str1);
}
if(!*str1 && firstHalf)
{
goto retry;
}
}
if(!*str2)
{
retrySecondHalf:
temp = secondHalf;
if(temp)
{
str2 = (char*)temp->Data;
secondHalf = secondHalf->Next;
}
if(!*str2 && secondHalf)
{
goto retrySecondHalf;
}
}
}
if(*str1 || *str2)
{
return false;
}
return true;
}
int _tmain(int argc, _TCHAR* argv[])
{
LinkedList* list = new LinkedList();
list->AddItem("01234");
list->AddItem("");
list->AddItem("56");
list->AddItem("789");
list->AddItem("1");
list->AddItem("9");
list->AddItem("");
list->AddItem("876543210");
printf("Is pallindrome: %d \n", list->IsPalindrome());
return 0;
}
To begin, iterate to the end of the list and store a pointer to the last node as end. Then store a pointer to the first node as start.
Then, call a function and supply these values. The function will:
Test if start == end (they point to the same link). If so, it will return true immediately. (An odd number of items in the list and the middle item is the only one left.)
Then it will look at the values represented by start and end. If they are not equal, it will return false immediately. (Not a palindrome.)
Otherwise, it will alter start to point to the next link (presumably start = start->next).
If start == end, return true immediately (handles the case for an even number of links in the list).
Find the link prior to end and set end to it: link i = start; while (i->next != end) i = i->next; end = i;.
Recurse, supplying the new values for start and end.
Following is recursion code, where node has data as integer, just replace it with char. It runns in O(n) time, uses constant space other than implicitly using stack of size O(n). where, n is number of nodes in linkedlist..
package linkedList;
class LinkedList {
class LinkedListNode {
public int data;
public LinkedListNode next;
public LinkedListNode (int d) {
data = d;
next = null;
}
}
class PalinResult {
public boolean done;
public LinkedListNode forward;
public PalinResult (LinkedListNode n) {
forward = n;
done = false;
}
}
LinkedListNode root;
public LinkedList () {
root = null;
}
public LinkedListNode getRoot(){
return root;
}
public boolean add(int d) {
LinkedListNode t = new LinkedListNode (d);
if (root == null) {
root = t;
return true;
}
LinkedListNode curr = root;
while (curr.next != null) {
curr = curr.next;
}
curr.next = t;
return true;
}
/*
* Takes O(n time)
*/
public boolean checkPalindrome() {
PalinResult res = new PalinResult (root);
return checkPalindromeRecur(root, res);
}
private boolean checkPalindromeRecur(LinkedListNode curr, PalinResult res) {
if (curr == null)
return true;
else {
boolean ret = checkPalindromeRecur(curr.next, res);
if (!ret || (res.done))
return ret;
if (curr == res.forward)
res.done = true;
if (curr.data == res.forward.data)
ret = true;
else
ret = false;
res.forward = res.forward.next;
return ret;
}
}
public static void main(String args[]){
LinkedList l = new LinkedList();
l.add(1);
l.add(4);
l.add(1);
System.out.println(l.checkPalindrome());
}
}
So ( My rough idea- please let me know)
We could also
1) Calculate length of LL;
2) Appropriately determine the midpoint
// (for a length 5 the mid point is 3 but for length 4 the midpoint is 2).
3) When at Midpoint- reverse the LL from mid point to the end of the LL;
4)Compare head data with the new mid point data until the head ref iterates to mid and the new mid ref iterates to NULL.
Related
Not sure if there is a simple and better way to implement this function?
void insert(Node* &head, int element, int position) {
Node* current = new Node;
current->data = element;
current->next = NULL;
if (position == 1) {
current->next = head;
head = current;
return;
}
else {
Node * current2 = head;
for (int i = 0; i < position - 2; i++) {
current2 = current2->next;
}
current2->next = current2->next;
current2->next = current;
}
}
A better way would be to make this function without null pointer access. You are missing all the necessary error checking.
But if you have to use this function you are already doing something wrong. The operation takes O(n) time. And if you build your list using only this function then you already have O(n^2) time. Using a balanced tree or heap would give you O(n * log n) time which makes a huge difference even for relatively small n. So think again why you need to insert at a given position and think about more suitable data structures.
A simpler implementation, and actually used in real code a lot, is to implement insert_before(before, data) or insert_after(after, data) with a doubly linked list. Both of which would get an item in the list and a new item to insert and place the new item before or after the old one on O(1) time.
Some boundary check is needed (please find the comments inline):
int listLen(Node *head)
{
int len = 0;
while (head != nullptr)
{
len++;
head = head->next;
}
return len;
}
void insert(Node* &head, int element, int position)
{
if (head == nullptr) // do nothing if head is nullptr
return;
if (position < 0) // insert to the begin if position is negative
position = 0;
else
{
int len = listLen(head);
if (len < position) // position is out of range, insert to the end
{
position = len;
}
}
if (position == 0)
{
Node *next = head;
head = new Node(element);
head->next = next;
}
else
{
int curPos = 0;
Node *curNode = head;
while (curPos < position - 1) // move to position
{
curNode = curNode->next;
curPos++;
}
Node *next = curNode->next; // do insertion
curNode->next = new Node(element);
curNode->next->next = next;
}
}
The user inputs values of int age, and the function is supposed to accept parameters from a pointer to the head of the list,
and go through the linked list nodes and return the highest value of int age.
Heres my function; I keep getting random numbers as the output:
int findLargest (StudentCard *p) {
int current = p->age;
int next;
StudentCard *temp = p;
while(temp != NULL){
if (p->age == NULL) {
//The value at this node is obviously larger than a non-existent value
return current;
} else {
//Recur to find the highest value from the rest of the LinkedList
next = findLargest(p->next);
}
//Return the highest value between this node and the end of the list
if (current > next) {
return current;
} else {
return next;
}
temp=temp->next;
}
}
You're mixing iteration with recursion, which is usually not a good idea.
(Your compiler should have warned about possibly not returning a value from the function. )
You're also possibly dereferencing a null pointer here:
int current = p->age;
and comparing the wrong thing here:
if (p->age == NULL)
(The fact that the program doesn't crash makes me suspect that you have an object with zero age somewhere, causing you to return that zero instead of recursing.)
If you read the loop carefully, you'll notice that it always returns a value on the first iteration, so temp is never advanced, and the while could be replaced with if.
You should rewrite the function to be either iterative or recursive.
An iterative solution would look like this:
int findLargest (StudentCard *p)
{
int current = std::numeric_limits<int>::min();
while (p != NULL){
if (p->age > current) {
current = p->age;
}
p = p->next;
}
return current;
}
and a recursive solution would look like this:
int findLargest (StudentCard *p)
{
if (p == NULL) {
return std::numeric_limits<int>::min();
}
return std::max(p->age, findLargest(p->next));
}
First of all, you should return -1 at the end of your function to inform that nothing was found.
Then secondly, you are sending the p->next as the parameter of findLargest function without checking NULL in following code:
//Recur to find the highest value from the rest of the LinkedList
next = findLargest(p->next);
And also, when you are using recursion function call, you don't need the while(temp != NULL) loop at all. You could replace the while with a if and remove the temp = temp->next; statement. Either recursion or iteration is enough for solving your problem.
Your findLargest function should be as following code:
int findLargest (StudentCard *p)
{
if (p != NULL)
{
int current = p->age;
int next = findLargest(p->next);
if (current > next) {
return current;
}
else {
return next;
}
}
return -1;
}
For getting the oldest student node pointer, use following definition:
StudentCard * findLargestNode(StudentCard *p)
{
if (p != NULL)
{
int curAge = p->age;
StudentCard *next = findLargestNode(p->next);
if (next && (next->age > curAge)) {
return next;
}
else {
return p;
}
}
return NULL;
}
And for printing the oldest student ID, use the function as following
{
StudentCard *pOld = findLargestNode(listHead); // `listHead` is HEAD node of your link-list
if ( pOld )
cout << pOld->id << endl;
}
So I have this recursive solution to print the nth element from the end of the list:
void print_nth_from_last_rec(Node* node, int n) {
static int count { 0 };
if (!node) return;
print_nth_from_last_rec(node->next, n);
if (++count == n)
cout << node->data;
}
But I can't figure out how to return that element using recursion. Is it possible?
Attempts:
I can do it if I have a static Node* that will be assigned to when (++count == n):
Node* get_nth_from_last_rec(Node* node, int n) {
static int count { 0 };
static Node* ret{ nullptr };
if (node) {
get_nth_from_last_rec(node->next, n);
if (++count == n)
ret = node;
}
return ret;
}
It is also possible to pass in a reference to the out Node and assign the nth element to it.
But is there a better way? These statics don't look very clean to me.
Node* get_nth_from_last_rec(Node* node, int& n)
{
if (node)
{
Node* result = get_nth_from_last_rec(node->next, n);
if (result)
return result;
else if (! n--)
return node;
}
return nullptr;
}
Here's how I'd do it (I hope it's obvious from context what advance does):
Node* get_nth_from_last(Node* node, int n, Node *ahead = 0) {
if (ahead == 0) {
// might like to check for size < n at the same time
// and return something to indicate error in that case
ahead = advance(node, n);
}
if (ahead->next == 0) return node; // or whatever the end condition is
return get_nth_from_last(node->next, n, ahead->next);
}
If you want to hide that default parameter away from the caller, then use a helper function. It's only needed for efficiency anyway, if you want really slow code then do without it and call advance at every recursive step.
You should pretty much never need static variables just to make your recursion work. You can always add parameters with default values, or else write a helper function with extra parameters and call that to do all the work. Aside from any confusion they might cause the reader, they make the function non-thread-safe, and non-reentrant from signal handlers.
My code does 2 * len - n node advances, and yours only does len (plus n pieces of work coming back out of the recursion). If you want to stick with your performance characteristics but sacrifice tail recursion, then something like this (I'm either out-by-one on this, or on my first answer, depending on the meaning of n...):
Node* get_nth_from_last_helper(Node* node, int &depth) {
if (node == 0) return 0;
Node *n = get_nth_from_last_helper(node->next, depth);
--depth;
return (depth == 0) ? node : n;
}
Node *get_nth_from_last(Node *node, int n) {
return get_nth_from_last_helper(Node *node, n);
}
Personally I would use the nth from front function count down to 0
Node* get_nth_from_first_rec(Node* node, int n) {
if (!node || n == 0) {
return node;
}
return get_nth_from_last_rec(node->next, n - 1);
}
And count the number of elements in the list (recursively if you want)
int get_list_length(Node* node) {
if (!node) {
return 0;
}
return 1 + get_list_length(node->next);
}
So then I could compute the index as an nth from first index
Node* get_nth_from_last_rec(Node* node, int n) {
int count = get_list_length(node);
return get_nth_from_first_rec(node, n - count);
}
Here I believe I have a neat tail recursion way of solving it in Java.
public static LinkedListNode findnthToLastRecursionHelper(LinkedListNode node, LinkedListNode last,int pos){
if(node==null) return null;
if(pos<1)
{
pos=1; //We have reached the nth iteration for last, now time to increment node and last together.
node = node.next;
if(last==null) return node;
}
else if(last==null) return null;
return findnthToLastRecursionHelper(node,last.next,--pos);
}
This is the main tail recursion chunk that cares of moving the last pointer to the nth position, and once position is reached it moves node & last pointer together.
public static LinkedListNode findnthToLastRecursion(LinkedListNode head,int pos){
return findnthToLastRecursionHelper(head,head.next,pos);
}
This is the caller function in order to maintain the aesthetics.
I am trying to implement one bool function that receives List and Int as arguments and should insert int and return true if the int does not exist in the list, or false if it is already there, i have been working for several hours with this function, and the if-else statements can insert sorted int, the problem (and crash) is how to check if the value already exist and return false, here is my function:
declaration of struct
typedef struct E_Type * List;
struct E_Type
{
int data;
List next = 0;
};
and function
bool insert(List & l, int data)
{
List current = l;
do{//check if the int is already in the list
current->data;
current = current->next;
//return false;
}while (current->data == data);
if (l == 0 || l->data > data){
List new_list = new E_Type;
new_list->data = data;
new_list->next = l;
l = new_list;
return true;
}
else if(l->data < data){
insert(l->next, data);
return true;
}
}
do{
//this line doesn't really do anything...
current->data;
//moving current forward, good.
current = current->next;
//If current->data is less than data in the list, it will exit the loop here anyway.
}while (current->data == data);
You also aren't checking whether you have reached the end of the list. Perhaps what you are attempting to do is something like this:
//This is correct for for iterative approach, but I don't think this is really what you need, either...
while(current != null) {
if (current->data == data)
return false;
current = current->next;
}
However, you probably don't want to use iteration like this to make this check in a recursive function, so instead, simply replace that whole bit with:
if (current->data == data)
return false;
And to return the correct value through the recursive calls, you'll want to change:
else if(l->data < data){
insert(l->next, data); //Recursive call
return true; //you don't want to just return true, return what the recursive call returns!
}
To:
else if(l->data < data){
return insert(l->next, data);
}
Let's say we are given the function definition
bool sameValsOrder(node *p , node *q)
We have to write a function to compare the 2 linked list if they have the same order it returns true else false
[77777] and [77] -> true
[1234567] and [1234555567] -> true
bool sameValsOrder (node *p , node *q)
{
if ( q==NULL && p==NULL)
return true;
else if ((q=NULL && p != NULL)|| (p=NULL && q!= NULL))
return false;
else if ( q != NULL && p != NULL)
while ( q != 0 && p != 0)
{
if (p->data != q->data)
{
return false;
break;
}
else
{
p= p-> next ;
q= q-> next;
}
}
return true;
}
The above code is my answer but I realized something. Do I need to add more if statement inside the while loop such that a link list of [77777] and [7] should return true since its the same order just less.
According to what you have written you don't actually care about the values but you want to return true if the list is ordered? It seems like you just need to go through each value in the list. As long as the NEXT value is NOT LESS than the PREVIOUS value keep going through the list. If you reach the end, then return true because the list is in order. If, at any point you come across a value that is less than any previous value then just return false right there.
#include <iostream>
using namespace std;
class node{
public:
node(){next = NULL;}
int data;
node * next;
};
class myList{
public:
myList(){pRoot = NULL;}
void add(int data);
node * pRoot;
};
bool sameValsOrder (node *p , node *q)
{
if ( q==NULL && p==NULL) // If both lists are empty
return true;
else if ((q==NULL && p != NULL)|| (p==NULL && q!= NULL)) // One list is empty and the other is not
return false;
else if ( q != NULL && p != NULL) //Both lists contain values we must check
{
int temp; //I am going to assume a singly linked list (no access to previous value), need this to hold previous value
temp = p->data;
while (p->next != NULL) //The list still contains elements
{
if (p->next->data < temp) //The value in the current node is LESS than our temp, then list is out of order so return false
return false;
else { //Otherwise move to the next node
temp = p->data;
p = p->next;
}
}
temp = q->data; //Reset temp for q
//Do the same thing for q
while (q->next != NULL) //The list still contains elements
{
if (q->next->data < temp) //The value in the current node is LESS than our temp, then list is out of order so return false
return false;
else { //Otherwise move to the next node
temp = q->data;
q = q->next;
}
}
}
return true; //If we are this are then both lists should be ordered
}
int main()
{
myList * p = new myList();
myList * q = new myList();
p->add(7);
p->add(6);
p->add(5);
p->add(4);
p->add(3);
p->add(2);
p->add(1);
q->add(7);
q->add(6);
q->add(5);
q->add(5);
q->add(5);
q->add(5);
q->add(4);
q->add(3);
q->add(2);
q->add(1);
cout << sameValsOrder (p->pRoot, q->pRoot) << endl;
return 0;
}
void myList::add(int data)
{
node * nodeToAdd = new node();
nodeToAdd->data = data;
if(pRoot == NULL) //List is empty
{
pRoot = nodeToAdd;
pRoot->next = NULL;
}
else //List not empty insert new node at beginning
{
nodeToAdd->next = pRoot;
pRoot = nodeToAdd;
}
}
while ( q != 0 && p != 0)
{
if (p->data != q->data)
return false;
break;
else
p= p-> next ;
q= q-> next;
}
this is wrong you are returning false when it is not same but as the size of p and q can be different
[1112] [12] will return false which it shouldnt
while(q!=NULL || p!=NULL)
{
if(q->data==p->data)
{
p=p->next;
break;
}
else(q->data < p->data)
q=q->next;
}
Basically you should move forward in the first linked list only when the values don't match other wise traverse the second list till it matches.
The OP has indicated in comments that he wants to consider 'runs' of nodes with the same data as being matched even if those runs have a difference length in the 2 lists. That simplifies to when (q->data == p->data) then skip nodes that comprise a run.
Here's some pseudocode; a C implementation is really not any more complex (though it might be several more lines):
bool sameValsOrder (node *p , node *q)
{
while not at the end of either list, and the current nodes are the same {
skip run in q, taking care to deal with the NULL at the end of the list
skip run in p, taking care to deal with the NULL at the end of the list
}
if we've reached the end of both lists, they are equivalent
}
C Implementation:
bool sameValsOrder (node *p , node *q)
{
while (q && p && (q->data == p->data)) {
/* find next different node in each list (ie., skip runs) */
int tmp = q->data; /* or whatever type `data` is */
while (q && (q->data == tmp)) {
q = q->next;
}
while (p && (p->data == tmp)) {
p = p->next;
}
}
/*
* we've either reached the end of one or both lists,
* or have found a `data` difference
*/
if (p == q) {
/* should happen only when `q` and `p` are NULL */
assert(q == NULL);
assert(p == NULL);
/* we've reached the end of both lists, so they're 'equivalent' */
return true;
}
return false;
}