কেবলমাত্র দুটি পয়েন্টার ব্যবহার করে কীভাবে একটি একক সংযুক্ত তালিকার বিপরীত করবেন?


109

আমি ভাবছি যদি কেবলমাত্র দুটি পয়েন্টার ব্যবহার করে একক সংযুক্ত তালিকার বিপরীতে কিছু যুক্তি উপস্থিত থাকে।

নিম্নলিখিত যথা তিনটি পয়েন্টার ব্যবহার একক লিঙ্ক তালিকা বিপরীত করতে ব্যবহৃত হয় p, q, r:

struct node {
    int data;
    struct node *link;
};

void reverse() {
    struct node *p = first,
                *q = NULL,
                *r;

    while (p != NULL) {
        r = q;
        q = p;
        p = p->link;
        q->link = r;
    }
    first = q;
}

লিঙ্কযুক্ত তালিকার বিপরীতে বিকল্প কোনও আছে কি? সময়ের জটিলতার নিরিখে এককভাবে সংযুক্ত তালিকার বিপরীতে উত্সাহ দেওয়ার জন্য সর্বোত্তম যুক্তি কী হবে?


1
সম্ভাব্য প্রতিলিপির: stackoverflow.com/questions/818443/...
kajaco

3
আসলেই নয়, এটি দুটি পয়েন্টারের চেয়ে দুটি সারি।
প্যাক্সিডিয়াবলো

7
কারণ আপনি এখানে সাহায্যের জন্য এসেছেন, এবং কোনও গেম খেলবেন না?
GManNickG

1
জিমন: এটাই জিনিস, আমি নিশ্চিত না যে আমি কাউকে, এমনকি তাকে সহায়তা করছি, যদি সে তা অনুসরণ করতে না পারে।

1
আপনি আমাদের মধ্যে যারা প্রশ্নোত্তর থেকে কিছু পড়েন এবং কিছু পেয়ে থাকেন তাদের সহায়তা করছেন। আমি এটি অন্তর্দৃষ্টিপূর্ণ পেলাম।
অ্যান্ড্রু কুলসন

উত্তর:


133

কোন বিকল্প? না, এটি যতটা সহজ তত সহজ এবং এটি করার কোনও মৌলিক-ভিন্ন উপায় নেই। এই অ্যালগরিদম ইতিমধ্যে ও (এন) সময়, এবং আপনি যে কোনও নোড পরিবর্তন করতে হবে হিসাবে আপনি, এর চেয়ে দ্রুত আর পেতে পারে না।

দেখে মনে হচ্ছে আপনার কোডটি সঠিক পথে রয়েছে তবে এটি উপরের ফর্মটিতে বেশ কার্যকরভাবে কাজ করছে না। এখানে একটি কার্যকরী সংস্করণ:

#include <stdio.h>

typedef struct Node {
  char data;
  struct Node* next;
} Node;

void print_list(Node* root) {
  while (root) {
    printf("%c ", root->data);
    root = root->next;
  }
  printf("\n");
}

Node* reverse(Node* root) {
  Node* new_root = 0;
  while (root) {
    Node* next = root->next;
    root->next = new_root;
    new_root = root;
    root = next;
  }
  return new_root;
}

int main() {
  Node d = { 'd', 0 };
  Node c = { 'c', &d };
  Node b = { 'b', &c };
  Node a = { 'a', &b };

  Node* root = &a;
  print_list(root);
  root = reverse(root);
  print_list(root);

  return 0;
}

মূলটিতে 'সুস্পষ্ট ত্রুটি' সম্পর্কে আমি নিশ্চিত নই। নকশা অনুযায়ী, তালিকার শীর্ষে প্রবেশ না করা এবং নতুন মাথা না ফেরানো একটি খারাপ ধারণা। reverse()আমার বিশ্বাস, ফাংশনটির শেষ লাইনটি প্রথমে নির্ধারণ করা উচিত, তবে আমি বিশ্বাস করি। অন্যথায়, আপনার ঝরঝরে পরীক্ষার জোতাতে প্লাগ ইন করার সময় আসল কোডটি ঠিক আছে। তবুও আমার কাছ থেকে আপনি +1 পান - তবে আপনি 'স্পষ্টত ত্রুটিগুলি' কী বিবেচনা করেন তার একটি ব্যাখ্যা আপনার উত্তরকে উন্নত করবে।
জোনাথন লেফলার

2
উপরের কোডটিতে কোনও বাগ নেই? লুপের ভিতরে, আপনি প্রতিবার একটি নতুন 'পরবর্তী' পয়েন্টার তৈরি করছেন are সুতরাং লিঙ্কযুক্ত তালিকায় যদি এন নোড থাকে তবে আপনি এন নতুন পয়েন্টার তৈরি করছেন এবং আপনি সেগুলি মুক্ত বা মুছছেন না। আমি মনে করি যদি আপনি সময় লুপের আগে 'পরবর্তী' পয়েন্টার তৈরি করেন এবং কেবল লুপের ভিতরে 'Next = root-> next' অ্যাসাইনমেন্টটি তৈরি করেন তবে এটি সঠিক হবে।
aks

6
@ লাক্স: কোনও ফুটো নেই। Malloc / ইত্যাদি লক্ষ্য করুন। বলা হয় না তাই মুক্ত করার কোনও দরকার নেই। ভেরিয়েবল 'নেক্সট' লুপের জন্য স্কুপ করা হয় তবে এটি পুরোপুরি ঠিক okay

1
এমনকি যদি কোনও ফাঁস না হয়, তবে প্রতিবারের মতো ঘোষণা করার দরকার কী, যেমন aks উল্লেখ করেছেন, "আপনি যখন লুপের আগে 'পরবর্তী' পয়েন্টার তৈরি করেন এবং কেবলমাত্র 'পরবর্তী = মূল-> পরবর্তীটি অ্যাসাইনমেন্টটি তৈরি করেন তবে এটি সঠিক হবে would 'যখন লুপের ভিতরে। ", তাই না?
গিকিজে

1
আমি আপনার লিঙ্ক তালিকার আক্ষরিক পছন্দ, এটি ঝরঝরে।

43

আমি খারাপ সংবাদের ধারক হতে ঘৃণা করি তবে আমি মনে করি না যে আপনার তিন-পয়েন্টার সমাধানটি আসলে কাজ করে। আমি যখন নিম্নলিখিত পরীক্ষার জোড়ায় এটি ব্যবহার করি, নীচের আউটপুট অনুযায়ী তালিকাটি একটি নোডে নামিয়ে আনা হয়েছিল:

==========
4
3
2
1
0
==========
4
==========

এটি আপনার সমাধানের চেয়ে ভাল সময়ের জটিলতা পাবেন না কারণ এটি ও (এন) এবং পয়েন্টারগুলি পরিবর্তন করতে আপনাকে প্রতিটি নোডে যেতে হবে, তবে নীচের কোডটিতে প্রদর্শিত হিসাবে আপনি কেবল দুটি অতিরিক্ত পয়েন্টার সহ একটি সমাধান করতে পারেন :

#include <stdio.h>

// The list element type and head.

struct node { 
    int data;
    struct node *link;
};
static struct node *first = NULL;

// A reverse function which uses only two extra pointers.

void reverse() {
    // curNode traverses the list, first is reset to empty list.
    struct node *curNode = first, *nxtNode;
    first = NULL;

    // Until no more in list, insert current before first and advance.
    while (curNode != NULL) {
        // Need to save next node since we're changing the current.
        nxtNode = curNode->link;

        // Insert at start of new list.
        curNode->link = first;
        first = curNode;

        // Advance to next.
        curNode = nxtNode;
    }
}

// Code to dump the current list.

static void dumpNodes() {
    struct node *curNode = first;
    printf ("==========\n");
    while (curNode != NULL) {
        printf ("%d\n", curNode->data);
        curNode = curNode->link;
    }
}

// Test harness main program.

int main (void) {
    int i;
    struct node *newnode;

    // Create list (using actually the same insert-before-first
    // that is used in reverse function.

    for (i = 0; i < 5; i++) {
        newnode = malloc (sizeof (struct node));
        newnode->data = i;
        newnode->link = first;
        first = newnode;
    }

    // Dump list, reverse it, then dump again.

    dumpNodes();
    reverse();
    dumpNodes();
    printf ("==========\n");

    return 0;
}

এই কোড আউটপুট:

==========
4
3
2
1
0
==========
0
1
2
3
4
==========

যা আমি মনে করি আপনি কি পরে ছিলেন। এটি প্রকৃতপক্ষে এটি করতে পারে, আপনি একবার firstতালিকাটিকে লক্ষ্য করে পয়েন্টারটি লোড করে ফেললে আপনি firstইচ্ছায় পুনরায় ব্যবহার করতে পারেন ।


2
খুবই ভদ্র. firstসংযুক্ত তালিকার মধ্যে পয়েন্টারটিকে পুনরায় ব্যবহার করা হলে সমাধানটি কেবলমাত্র 2 টি অতিরিক্ত পয়েন্টার ব্যবহারের অনুমতি দেয় , তবে 3 টি মোট পয়েন্টার এখনও এর জন্য প্রয়োজনীয়।
কেভিন কিবলার

আপনি এর জন্য প্রথম, কার্নোড এবং এনএসটিএনড ব্যবহার করছেন, মোট তিনটি পয়েন্টার। এটি কীভাবে একটি দুটি পয়েন্টার সমাধান?
ইয়াসসভী

@ যশ, আবার পড়ুন, উপরে দুটি অতিরিক্ত পয়েন্টার first। একই ভাবে ওপি তিন পয়েন্টার সমাধান ছিল first, p, qএবং r
paxdiablo

@ পাক্সদিবলো ওহ! আমার খারাপ দুঃখিত, আমি প্রশ্নটি ভুল বুঝেছি। ধন্যবাদ :)
ইয়াসসভী

25
#include <stddef.h>

typedef struct Node {
    struct Node *next;
    int data;
} Node;

Node * reverse(Node *cur) {
    Node *prev = NULL;
    while (cur) {
        Node *temp = cur;
        cur = cur->next; // advance cur
        temp->next = prev;
        prev = temp; // advance prev
    }
    return prev;
}

2
হ্যালো! আমি জানি এই প্রশ্নটি পুরানো, তবে এই ফাংশনটিতে কী ঘটে এবং কেন এটি কাজ করে তা বোঝাতে আপনি কি আপত্তি করতে চান? :) ধন্যবাদ!
MakeTheTrumpetsBlow

13

সি তে একক সংযুক্ত তালিকার বিপরীতে কোডটি এখানে ।

এবং এখানে এটি নীচে আটকানো হয়েছে:

// reverse.c

#include <stdio.h>
#include <assert.h>

typedef struct node Node;
struct node {
    int data;
    Node *next;
};

void spec_reverse();
Node *reverse(Node *head);

int main()
{
    spec_reverse();
    return 0;
}

void print(Node *head) {
    while (head) {
        printf("[%d]->", head->data);
        head = head->next;
    }
    printf("NULL\n");
}

void spec_reverse() {
    // Create a linked list.
    // [0]->[1]->[2]->NULL
    Node node2 = {2, NULL};
    Node node1 = {1, &node2};
    Node node0 = {0, &node1};
    Node *head = &node0;

    print(head);
    head = reverse(head);
    print(head);

    assert(head == &node2);
    assert(head->next == &node1);
    assert(head->next->next == &node0);

    printf("Passed!");
}

// Step 1:
//
// prev head  next
//   |    |    |
//   v    v    v
// NULL  [0]->[1]->[2]->NULL
//
// Step 2:
//
//      prev head  next
//        |    |    |
//        v    v    v
// NULL<-[0]  [1]->[2]->NULL
//
Node *reverse(Node *head)
{
    Node *prev = NULL;
    Node *next;

    while (head) {
        next = head->next;
        head->next = prev;
        prev = head;
        head = next;
    }

    return prev;
}

4
ব্যাখ্যার জন্য দুর্দান্ত ASCII শিল্পের জন্য ধন্যবাদ :)
achedeuzot

3

হ্যাঁ. আমি নিশ্চিত যে আপনি তৃতীয়টি ব্যবহার না করেই দুটি সংখ্যা স্যুপ করতে পারেন ঠিক একইভাবে আপনি এটি করতে পারেন । কেবলমাত্র পয়েন্টারগুলিকে একটি দীর্ঘ / দীর্ঘতে কাস্ট করুন এবং কয়েকবার এক্সওআর অপারেশন করুন। এটি সেই সি ট্রিকগুলির মধ্যে একটি যা মজাদার প্রশ্ন তৈরি করে, তবে এর কোনও ব্যবহারিক মান নেই।

আপনি ও (এন) জটিলতা হ্রাস করতে পারেন? না সত্যিই না. আপনি যদি মনে করেন যে আপনার বিপরীত ক্রমের প্রয়োজন হয় তবে কেবল একটি দ্বিগুণ লিঙ্কযুক্ত তালিকা ব্যবহার করুন।


… এবং যদি আপনি যত্নবান না হন তবে একটি নতুন 64-বিট সামঞ্জস্যতার সমস্যাটি জন্মগ্রহণ করবে। আপনি এইভাবে কোনও কার্যকারিতা কেনার সম্ভাবনা রাখেন না।
LnxPrgr3

2
এটি সময়ের জটিলতায় প্রভাব ফেলবে না - এটি লিনিয়ার সময়ের চেয়ে সমাধানটিকে আরও ভাল করে তুলবে না । মানে, আপনি মেমরির 4 বা 8 বাইট সঞ্চয় করতে পারেন, তবে এটি অ্যালগরিদমের সামগ্রিক জটিলতা পরিবর্তন করবে না।
পাউন্ডিফ

@ রাশার, সময়ের জটিলতা ছিল প্রশ্নের দ্বিতীয় অংশ। প্রথম অংশে প্রয়োজনীয় পয়েন্টারের সংখ্যা হ্রাস করা উচিত।
paxdiablo

2
আমি মনে করি মূল পোস্টারটি একটি সস্তা সি ট্রিক খুঁজছিল। আমার অভিজ্ঞতায় - এবং আমি এটি প্রোফাইল করেছি :) - সাধারণ এড়ানো মধ্যস্থতাকারী কৌশলগুলি কেবলমাত্র কোনও মধ্যস্থতাকারী ব্যবহারের চেয়ে ধীর হয়।
উইল

লিঙ্কটি নষ্ট হয়ে গেছে, তবে আমি নিশ্চিত যে এক্সওআর ব্যবহার করে 2 নম্বরটি অদলবদল পুরানো-স্কুল :)
ডেন

3

রবার্ট সেডজউইক, " সি এ্যালগরিদম ", অ্যাডিসন-ওয়েসলি, তৃতীয় সংস্করণ, ১৯৯ [, [বিভাগ ৩.৪]

যদি এটি একটি চক্রীয় তালিকা না হয়, সুতরাং NUL শেষ লিঙ্ক।

typedef struct node* link;

struct node{ int item; link next; };

/* you send the existing list to reverse() and returns the reversed one */

link reverse(link x){ link t, y = x, r = NULL; while(y != NULL){ t = y->next; y-> next = r; r = y; y = t; } return r; }


3

কেবল মজাদার জন্য (যদিও লেজ পুনরাবৃত্তি অপ্টিমাইজেশান এটি সমস্ত স্ট্যাক খাওয়া বন্ধ করা উচিত):


Node* reverse (Node *root, Node *end) {

    Node *next = root->next;
    root->next = end;

    return (next ? reverse(next, root) : root);
}

root = reverse(root, NULL);

2
আমি মনে করি "উচিত" মামলাটিকে কিছুটা বাড়িয়ে তুলছে। আপনার সি সংকলক একটি "টেল-কল অপ্টিমাইজেশান" করতে পারে এবং প্রদত্ত সংকলক / বিকল্পগুলি তা করে কিনা তা পরীক্ষা করে দেখার পক্ষে যথেষ্ট সহজ: বিচ্ছিন্নতার দিকে তাকান। অথবা এটি কয়েক মিলিয়ন নোড দিন এবং দেখুন এটি ক্র্যাশ করেছে কিনা ;-)
স্টিভ জেসোপ

3

অস্থায়ী ভেরিয়েবল ব্যবহার না করে দুটি ভেরিয়েবল অদলবদল করতে,

a = a xor b
b = a xor b
a = a xor b

দ্রুততম উপায় হচ্ছে এটি একটি লাইনে লেখা write

a = a ^ b ^ (b=a)

একইভাবে,

দুটি অদলবদল ব্যবহার করে

swap(a,b)
swap(b,c)

xor ব্যবহার করে সমাধান

a = a^b^c
b = a^b^c
c = a^b^c
a = a^b^c

এক লাইনে সমাধান

c = a ^ b ^ c ^ (a=b) ^ (b=c)
b = a ^ b ^ c ^ (c=a) ^ (a=b)
a = a ^ b ^ c ^ (b=c) ^ (c=a)

লিঙ্কযুক্ত তালিকার বিপরীতে একই যুক্তি ব্যবহার করা হয়।

typedef struct List
{
 int info;
 struct List *next;
}List;


List* reverseList(List *head)
{
 p=head;
 q=p->next;
 p->next=NULL;
 while(q)
 {
    q = (List*) ((int)p ^ (int)q ^ (int)q->next ^ (int)(q->next=p) ^ (int)(p=q));
 }
 head = p;
 return head;
}  

1
এটি ধরে নিয়েছে যে কোনও ইনট একটি পয়েন্টার হিসাবে একই আকার, এটি এমডি 64 সিস্টেমে কাজ করবে না (আপনি ব্যবহার করতে পারেন intptr_t)। আকর্ষণীয় হলেও - এই পদ্ধতিতে অদলবদল করা আধুনিক সিস্টেমে উপ-অনুকূল।
ধারণাগুলি 42

3

আপনার একটি ট্র্যাক পয়েন্টার দরকার যা তালিকাটি ট্র্যাক করবে।

আপনার দুটি পয়েন্টার দরকার:

প্রথম নোড বাছাই করার জন্য প্রথম পয়েন্টারদ্বিতীয় পয়েন্টার দ্বিতীয় নোড বাছাই।

প্রক্রিয়াজাতকরণ:

ট্র্যাক পয়েন্টার সরান

প্রথম নোড থেকে দ্বিতীয় নোড পয়েন্ট

একটিকে দ্বিতীয় পয়েন্টার বরাদ্দ করে প্রথম পয়েন্টারটিকে এক ধাপে সরান

দ্বিতীয় পয়েন্টারটি এক ধাপে সরান, দ্বিতীয় স্থানে ট্র্যাক পয়েন্টার বরাদ্দ করে

Node* reverselist( )
{
   Node *first = NULL;  // To keep first node
   Node *second = head; // To keep second node
   Node *track =  head; // Track the list

    while(track!=NULL)
    {
      track = track->next; // track point to next node;
      second->next = first; // second node point to first
      first = second; // move first node to next
      second = track; // move second node to next
    }

    track = first;

    return track;

}


2

কীভাবে আরও পাঠযোগ্য:


Node *pop (Node **root)
{
    Node *popped = *root;

    if (*root) {
        *root = (*root)->next;
    }

    return (popped);
}

void push (Node **root, Node *new_node)
{
    new_node->next = *root;
    *root = new_node;
}


Node *reverse (Node *root)
{
    Node *new_root = NULL;
    Node *next;

    while ((next = pop(&root))) {
        push (&new_root, next);
    }

    return (new_root);
}

2

জাভাতে এখানে একটি সহজ সংস্করণ। এটি কেবলমাত্র দুটি পয়েন্টার ব্যবহার করে curr&prev

public void reverse(Node head) {
    Node curr = head, prev = null;

    while (head.next != null) {
        head = head.next; // move the head to next node
        curr.next = prev; //break the link to the next node and assign it to previous
        prev = curr;      // we are done with previous, move it to next node
        curr = head;      // current moves along with head
    }

    head.next = prev;     //for last node
}

প্রশ্নটি জাভাতে নয়, সি-সলিউশনের সন্ধান করছে
ডিগাস্টাফ

1
প্রশ্নটি কেবল দুটি অতিরিক্ত পয়েন্টার (বা রেফারেন্স) দিয়ে বিপরীত অপারেশন করার বিষয়ে more এর সি বা জাভা যুক্তি এক হোক।
আর্নেস্তো

1

আপনি এখন যে অ্যালগরিদম ব্যবহার করছেন তার সময়ের জটিলতাটি কার্যকর করুন এবং এটি সুস্পষ্ট হওয়া উচিত যে এটি উন্নত করা যায় না।


1

কেন আমরা মাথা ফেরানোর দরকার আছে তা আমরা বুঝতে পারছি না কারণ আমরা এটিকে তর্ক হিসাবে পাস করছি। আমরা লিঙ্ক তালিকার শীর্ষে যাচ্ছি তখন আমরা আপডেটও করতে পারি। নীচে সহজ সমাধান।

#include<stdio.h>
#include<conio.h>

struct NODE
{
    struct NODE *next;
    int value;
};

typedef struct NODE node;

void reverse(node **head);
void add_end(node **head,int val);
void alloc(node **p);
void print_all(node *head);

void main()
{
    node *head;
    clrscr();
    head = NULL;
    add_end( &head, 1 );
    add_end( &head, 2 );
    add_end( &head, 3 );
    print_all( head );
    reverse( &head );
    print_all( head );
    getch();
}
void alloc(node **p)
{
    node *temp;
    temp = (node *) malloc( sizeof(node *) );
    temp->next = NULL;
    *p = temp;
}
void add_end(node **head,int val)
{
    node *temp,*new_node;
    alloc(&new_node);
    new_node->value = val;
    if( *head == NULL )
    {
        *head = new_node;
        return;
    }
    for(temp = *head;temp->next!=NULL;temp=temp->next);
    temp->next = new_node;
}
void print_all(node *head)
{
    node *temp;
    int index=0;
    printf ("\n\n");
    if (head == NULL)
    {
        printf (" List is Empty \n");
        return;
    }
    for (temp=head; temp != NULL; temp=temp->next,index++)
        printf (" %d ==> %d \n",index,temp->value);
}
void reverse(node **head)
{
    node *next,*new_head;
    new_head=NULL;
    while(*head != NULL)
    {
        next = (*head)->next;
        (*head)->next = new_head;
        new_head = (*head);
        (*head) = next;
    }
    (*head)=new_head;
}

1
#include <stdio.h>
#include <malloc.h>

tydef struct node
{
    int info;
    struct node *link;
} *start;

void main()
{
    rev();
}

void rev()
{
    struct node *p = start, *q = NULL, *r;
    while (p != NULL)
    {
        r = q;
        q = p;
        p = p->link;
        q->link = r;
    }

    start = q;
}

0

না, বর্তমান ও (এন) এর চেয়ে দ্রুত কিছুই করা যায় না। আপনাকে প্রতিটি নোড পরিবর্তন করতে হবে, তাই সময় যাইহোক উপাদানগুলির সংখ্যার সাথে সমানুপাতিক হবে এবং এটি ইতিমধ্যে আপনার (ও) আছে।


0

ও (এন) এর সময়ের জটিলতা বজায় রাখার সময় দুটি পয়েন্টার ব্যবহার করা, দ্রুত অর্জনযোগ্য, কেবলমাত্র পয়েন্টারগুলির সংখ্যা কাস্টিং এবং তাদের মানগুলি অদলবদলের মাধ্যমেই সম্ভব হতে পারে। এখানে একটি বাস্তবায়ন:

#include <stdio.h>

typedef struct node
{
    int num;
    struct node* next;
}node;

void reverse(node* head)
{
   node* ptr;
   if(!head || !head->next || !head->next->next) return;
   ptr = head->next->next;
   head->next->next = NULL;
   while(ptr)
   {
     /* Swap head->next and ptr. */
     head->next = (unsigned)(ptr =\
     (unsigned)ptr ^ (unsigned)(head->next =\
     (unsigned)head->next ^ (unsigned)ptr)) ^ (unsigned)head->next;

     /* Swap head->next->next and ptr. */
     head->next->next = (unsigned)(ptr =\
     (unsigned)ptr ^ (unsigned)(head->next->next =\
     (unsigned)head->next->next ^ (unsigned)ptr)) ^ (unsigned)head->next->next;
   }
}

void add_end(node* ptr, int n)
{
    while(ptr->next) ptr = ptr->next;
    ptr->next = malloc(sizeof(node));
    ptr->next->num = n;
    ptr->next->next = NULL;
}

void print(node* ptr)
{
    while(ptr = ptr->next) printf("%d ", ptr->num);
    putchar('\n');
}

void erase(node* ptr)
{
    node *end;
    while(ptr->next)
    {
        if(ptr->next->next) ptr = ptr->next;
        else
        {
            end = ptr->next;
            ptr->next = NULL;
            free(end);
        }
    }
}

void main()
{
    int i, n = 5;
    node* dummy_head;
    dummy_head->next = NULL;
    for(i = 1; i <= n ; ++i) add_end(dummy_head, i);
    print(dummy_head);
    reverse(dummy_head);
    print(dummy_head);
    erase(dummy_head);
}

0

আমার কিছুটা ভিন্ন পন্থা আছে। আমি তালিকাটি উল্টানোর জন্য বিদ্যমান ফাংশনগুলি (insert_at (সূচক), মুছে ফেলা_ফ্রম (সূচক)) ব্যবহার করতে চেয়েছিলাম (ডান শিফট অপারেশনের মতো কিছু)। জটিলতা এখনও ও (এন) তবে সুবিধাটি পুনরায় ব্যবহৃত কোড is অন্য_আপনার () পদ্ধতিটি দেখুন এবং আপনারা কী ভাবছেন তা আমাকে জানান।

#include <stdio.h>
#include <stdlib.h>

struct node {
    int data;
    struct node* next;
};

struct node* head = NULL;

void printList(char* msg) {
    struct node* current = head;

    printf("\n%s\n", msg);

    while (current != NULL) {
        printf("%d ", current->data);
        current = current->next;
    }
}

void insert_beginning(int data) {
    struct node* newNode = (struct node*) malloc(sizeof(struct node));

    newNode->data = data;
    newNode->next = NULL;

    if (head == NULL)
    {
        head = newNode;
    } else {
        newNode->next = head;
        head = newNode;
    }
}

void insert_at(int data, int location) {

    struct node* newNode = (struct node*) malloc(sizeof(struct node));

    newNode->data = data;
    newNode->next = NULL;

    if (head == NULL)
    {
        head = newNode;
    }

    else {
        struct node* currentNode = head;
        int index = 0;

        while (currentNode != NULL && index < (location - 1)) {
            currentNode = currentNode->next;
            index++;
        }

        if (currentNode != NULL)
        {
            if (location == 0) {
                newNode->next = currentNode;
                head = newNode;
            } else {
                newNode->next = currentNode->next;
                currentNode->next = newNode;
            }
        }
    }
}


int delete_from(int location) {

    int retValue = -1;

    if (location < 0 || head == NULL)
    {
        printf("\nList is empty or invalid index");
        return -1;
    } else {

        struct node* currentNode = head;
        int index = 0;

        while (currentNode != NULL && index < (location - 1)) {
            currentNode = currentNode->next;
            index++;
        }

        if (currentNode != NULL)
        {
            // we've reached the node just one prior to the one we want to delete

            if (location == 0) {

                if (currentNode->next == NULL)
                {
                    // this is the only node in the list
                    retValue = currentNode->data;
                    free(currentNode);
                    head = NULL;
                } else {

                    // the next node should take its place
                    struct node* nextNode = currentNode->next;
                    head = nextNode;
                    retValue = currentNode->data;
                    free(currentNode);
                }
            } // if (location == 0)
            else {
                // the next node should take its place
                struct node* nextNode = currentNode->next;
                currentNode->next = nextNode->next;

                if (nextNode != NULL
                ) {
                    retValue = nextNode->data;
                    free(nextNode);
                }
            }

        } else {
            printf("\nInvalid index");
            return -1;
        }
    }

    return retValue;
}

void another_reverse() {
    if (head == NULL)
    {
        printf("\nList is empty\n");
        return;
    } else {
        // get the tail pointer

        struct node* tailNode = head;
        int index = 0, counter = 0;

        while (tailNode->next != NULL) {
            tailNode = tailNode->next;
            index++;
        }

        // now tailNode points to the last node
        while (counter != index) {
            int data = delete_from(index);
            insert_at(data, counter);
            counter++;
        }
    }
}

int main(int argc, char** argv) {

    insert_beginning(4);
    insert_beginning(3);
    insert_beginning(2);
    insert_beginning(1);
    insert_beginning(0);

    /*  insert_at(5, 0);
     insert_at(4, 1);
     insert_at(3, 2);
     insert_at(1, 1);*/

    printList("Original List\0");

    //reverse_list();
    another_reverse();

    printList("Reversed List\0");

    /*  delete_from(2);
     delete_from(2);*/

    //printList();
    return 0;
}

0
using 2-pointers....bit large but simple and efficient

void reverse()

{

int n=0;

node *temp,*temp1;

temp=strptr;

while(temp->next!=NULL)

{

n++;      //counting no. of nodes

temp=temp->next;

}
// we will exchange ist by last.....2nd by 2nd last so.on....
int i=n/2;  

temp=strptr;

for(int j=1;j<=(n-i+1);j++)

temp=temp->next;
//  i started exchanging from in between ....so we do no have to traverse list so far //again and again for exchanging

while(i>0)

{

temp1=strptr;

for(int j=1;j<=i;j++)//this loop for traversing nodes before n/2

temp1=temp1->next;

int t;

t=temp1->info;

temp1->info=temp->info;

temp->info=t;

i--;

temp=temp->next; 

//at the end after exchanging say 2 and 4 in a 5 node list....temp will be at 5 and we will traverse temp1 to ist node and exchange ....

}

}

0
#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
struct node
{
int data;
struct node *link;
};
struct node *first=NULL,*last=NULL,*next,*pre,*cur,*temp;
void create()
{
cur=(struct node*) malloc(sizeof(struct node));
printf("enter first data to insert");
scanf("%d",&cur->data);
first=last=cur;
first->link=NULL;
}
void insert()
{
int pos,c;
cur=(struct node*) malloc(sizeof(struct node));
printf("enter data to insert and also its position");
scanf("%d%d",&cur->data,&pos);
if(pos==1)
{
cur->link=first;
first=cur;
}
else
{
c=1;
    next=first;
    while(c<pos)
    {
        pre=next;
        next=next->link;
        c++;
    }
        if(pre==NULL)
        {
            printf("Invalid position");
        }
        else
        {
        cur->link=pre->link;
        pre->link=cur;
        }
}
}
void display()
{
cur=first;
while(cur!=NULL)
{
printf("data= %d\t address= %u\n",cur->data,cur);
cur=cur->link;
}
printf("\n");
}
void rev()
{
pre=NULL;
cur=first;
while(cur!=NULL)
{
next=cur->link;
cur->link=pre;
pre=cur;
cur=next;
}
first=pre;
}
void main()
{
int choice;
clrscr();
do
{
printf("Options are: -\n1:Create\n2:Insert\n3:Display\n4:Reverse\n0:Exit\n");
printf("Enter your choice: - ");
scanf("%d",&choice);
switch(choice)
{
case 1:
create();
break;
case 2:
insert();
break;
case 3:
display();
break;
case 4:
rev();
break;
case 0:
exit(0);
default:
printf("wrong choice");
}
}
while(1);
}

যে কোনও সমস্যার সি প্রয়োগের জন্য আমার সাথে যোগাযোগ করুন।
মিঃ অমিত কুমার

0

হ্যাঁ মাত্র দুটি পয়েন্টার ব্যবহারের একটি উপায় রয়েছে। এটি নতুন লিঙ্কযুক্ত তালিকা তৈরি করে যেখানে প্রথম নোড প্রদত্ত তালিকার প্রথম নোড এবং প্রথম তালিকার দ্বিতীয় নোড নতুন তালিকার শুরুতে যুক্ত হয় এবং আরও কিছু হয়।


0

আমার সংস্করণটি এখানে:

void reverse(ListElem *&head)
{
    ListElem* temp;
    ListElem* elem = head->next();
    ListElem* prev = head;
    head->next(0);

    while(temp = elem->next())
    {
        elem->next(prev);
        prev = elem;
        elem = temp;
    }
    elem->next(prev);
    head = elem;
}

কোথায়

class ListElem{
public:
    ListElem(int val): _val(val){}
    ListElem *next() const { return _next; }
    void next(ListElem *elem) { _next = elem; }
    void val(int val){ _val = val; }
    int val() const { return _val;}
private:
    ListElem *_next;
    int _val;
};

0

আমি এটি বাস্তবায়নের জন্য জাভা ব্যবহার করছি এবং পদ্ধতির পরীক্ষা চালিত বিকাশ তাই পরীক্ষার কেসগুলিও সংযুক্ত রয়েছে।

নোড শ্রেণি যা একক নোডকে উপস্থাপন করে -

package com.adnan.linkedlist;

/**
 * User  : Adnan
 * Email : sendtoadnan@gmail.com
 * Date  : 9/21/13
 * Time  : 12:02 PM
 */
public class Node {

    public Node(int value, Node node){
        this.value = value;
        this.node = node;
    }
    private int value;
    private Node node;

    public int getValue() {
        return value;
    }

    public Node getNode() {
        return node;
    }

    public void setNode(Node node){
        this.node = node;
    }
}

পরিষেবা শ্রেণি যা ইনপুট হিসাবে শুরু নোড নেয় এবং অতিরিক্ত স্থান ব্যবহার না করে এটি সংরক্ষণ করে।

package com.adnan.linkedlist;

/**
 * User  : Adnan
 * Email : sendtoadnan@gmail.com
 * Date  : 9/21/13
 * Time  : 11:54 AM
 */
public class SinglyLinkedListReversal {

    private static final SinglyLinkedListReversal service 
= new SinglyLinkedListReversal();
    public static SinglyLinkedListReversal getService(){
        return service;
    }



    public Node reverse(Node start){
        if (hasOnlyNodeInLinkedList(start)){
            return start;
        }
        Node firstNode, secondNode, thirdNode;
        firstNode = start;
        secondNode = firstNode.getNode();
        while (secondNode != null ){
            thirdNode = secondNode.getNode();
            secondNode.setNode(firstNode);
            firstNode = secondNode;
            secondNode = thirdNode;
        }
        start.setNode(null);
        return firstNode;
    }

    private boolean hasOnlyNodeInLinkedList(Node start) {
        return start.getNode() == null;
    }


}

এবং টেস্ট কেস যা উপরিউক্ত চিত্রের উপরে। দয়া করে নোট করুন যে আপনার জুনিট জারগুলি প্রয়োজন। আমি টেস্টএন.জার ব্যবহার করছি; আপনি যা খুশি তা ব্যবহার করতে পারেন ..

package com.adnan.linkedlist;

import org.testng.annotations.Test;

import static org.testng.AssertJUnit.assertTrue;

/**
 * User  : Adnan
 * Email : sendtoadnan@gmail.com
 * Date  : 9/21/13
 * Time  : 12:11 PM
 */
public class SinglyLinkedListReversalTest {

    private SinglyLinkedListReversal reversalService = 
SinglyLinkedListReversal.getService();

    @Test
    public void test_reverseSingleElement() throws Exception {
        Node node = new Node(1, null);
        reversalService.reverse(node);
        assertTrue(node.getNode() == null);
        assertTrue(node.getValue() == 1);
    }


    //original - Node1(1) -> Node2(2) -> Node3(3)
    //reverse - Node3(3) -> Node2(2) -> Node1(1)
    @Test
    public void test_reverseThreeElement() throws Exception {
        Node node3 = new Node(3, null);
        Node node2 = new Node(2, node3);
        Node start = new Node(1, node2);


        start = reversalService.reverse(start);
        Node test = start;
        for (int i = 3; i >=1 ; i -- ){
          assertTrue(test.getValue() == i);
            test = test.getNode();
        }


    }

    @Test
    public void test_reverseFourElement() throws Exception {
        Node node4 = new Node(4, null);
        Node node3 = new Node(3, node4);
        Node node2 = new Node(2, node3);
        Node start = new Node(1, node2);


        start = reversalService.reverse(start);
        Node test = start;
        for (int i = 4; i >=1 ; i -- ){
            assertTrue(test.getValue() == i);
            test = test.getNode();
        }
    }

        @Test
        public void test_reverse10Element() throws Exception {
            Node node10 = new Node(10, null);
            Node node9 = new Node(9, node10);
            Node node8 = new Node(8, node9);
            Node node7 = new Node(7, node8);
            Node node6 = new Node(6, node7);
            Node node5 = new Node(5, node6);
            Node node4 = new Node(4, node5);
            Node node3 = new Node(3, node4);
            Node node2 = new Node(2, node3);
            Node start = new Node(1, node2);


            start = reversalService.reverse(start);
            Node test = start;
            for (int i = 10; i >=1 ; i -- ){
                assertTrue(test.getValue() == i);
                test = test.getNode();
            }


    }

    @Test
    public void test_reverseTwoElement() throws Exception {
        Node node2 = new Node(2, null);
        Node start = new Node(1, node2);


        start = reversalService.reverse(start);
        Node test = start;
        for (int i = 2; i >=1 ; i -- ){
            assertTrue(test.getValue() == i);
            test = test.getNode();
        }


    }
}

0

যদি আপনি লিঙ্কযুক্ত তালিকাটিকে স্ট্যাক কাঠামো হিসাবে ব্যবহার করেন তবে একটি সাধারণ অ্যালগরিদম:

 #include <stdio.h>
#include <stdlib.h>

typedef struct list {
    int key;
    char value;
    struct list* next;
} list;
void print(list*);
void add(list**, int, char);
void reverse(list**);
void deleteList(list*);

int main(void) {
    list* head = NULL;
    int i=0;
    while ( i++ < 26 ) add(&head, i, i+'a');
    printf("Before reverse: \n");
    print(head);
    printf("After reverse: \n");
    reverse(&head);
    print(head);
    deleteList(head);

}
void deleteList(list* l) {

    list* t = l;    
    while ( t != NULL ) {
        list* tmp = t;
        t = t->next;
        free(tmp);
    }

}
void print(list* l) {
    list* t = l;
    while ( t != NULL) {
        printf("%d:%c\n", t->key, t->value);
        t = t->next;
    }
}

void reverse(list** head) {
    list* tmp = *head;
    list* reversed = NULL;
    while ( tmp != NULL ) {
        add(&reversed, tmp->key, tmp->value);
        tmp = tmp->next;
    }
    deleteList(*head);
    *head = reversed;
}

void add(list** head, int k, char v) {

    list* t = calloc(1, sizeof(list));
    t->key = k; t->value = v;
    t->next = *head;
    *head = t;

}

অ্যাড এবং ম্যালোকের অতিরিক্ত ফাংশন কল করার কারণে কার্য সম্পাদন প্রভাবিত হতে পারে তাই অ্যাড্রেস অদলবদলের অ্যালগরিদমগুলি আরও ভাল তবে এটি একটি নতুন তালিকা তৈরি করে যাতে আপনি অতিরিক্ত বিকল্পগুলি ব্যবহার করতে পারেন যেমন আইটেমগুলি সরিয়ে বা আইটেমগুলি সরাতে যদি আপনি প্যারামিটার হিসাবে কলব্যাক ফাংশন যুক্ত করেন তবে বিপরীত।


0

সি ++ 11 এ এখানে কিছুটা আলাদা, তবে সহজ পদ্ধতির:

#include <iostream>

struct Node{
    Node(): next(NULL){}
    Node *next;
    std::string data;
};

void printlist(Node* l){
    while(l){
        std::cout<<l->data<<std::endl;
        l = l->next;
    }
    std::cout<<"----"<<std::endl;
}

void reverse(Node*& l)
{
    Node* prev = NULL;
    while(l){
        auto next = l->next;
        l->next = prev;
        prev=l;
        l=next;
    }
    l = prev;
}

int main() {
    Node s,t,u,v;
    s.data = "1";
    t.data = "2";
    u.data = "3";
    v.data = "4";
    s.next = &t;
    t.next = &u;
    u.next = &v;
    Node* ptr = &s;
    printlist(ptr);
    reverse(ptr);
    printlist(ptr);
    return 0;
}

এখানে আউটপুট


0

নীচে 2 পয়েন্টার (মাথা এবং র) ব্যবহার করে একটি প্রয়োগ করা হচ্ছে

ListNode * reverse(ListNode* head) {

    ListNode *r = NULL;

    if(head) {
        r = head->next;
        head->next = NULL;
    }

    while(r) {
        head = reinterpret_cast<ListNode*>(size_t(head) ^ size_t(r->next));
        r->next = reinterpret_cast<ListNode*>(size_t(r->next) ^ size_t(head));
        head = reinterpret_cast<ListNode*>(size_t(head) ^ size_t(r->next));

        head = reinterpret_cast<ListNode*>(size_t(head) ^ size_t(r));
        r = reinterpret_cast<ListNode*>(size_t(r) ^ size_t(head));
        head = reinterpret_cast<ListNode*>(size_t(head) ^ size_t(r));
    }
    return head;
}

যতটা চালাক এবং অনির্বচনীয় তা হতে পারে, আপনি যদি sizeof(size_t) < sizeof(ListNode*)... ব্যবহার করা উচিত তবে আপনি সমস্যায় পড়েন std::uintptr_t
কোয়ান্টিন

0

এখানে একটি সামান্য সহজ সমাধান ...

void reverse()
{
    node * pointer1 = head->next;
    if(pointer1 != NULL)
    {
        node *pointer2 = pointer1->next;
        pointer1->next = head;
        head->next = NULL;
        head = pointer1;

        if(pointer2 != NULL)
        {

            while(pointer2 != NULL)
            {
                pointer1 = pointer2;
                pointer2 = pointer2->next;
                pointer1->next = head;
                head = pointer1;
            }

            pointer1->next = head;
            head = pointer1;
        }       
   }
 }

0

আপনার কেবলমাত্র একটি অতিরিক্ত পয়েন্টারের সাহায্যে এই সমস্যার সমাধান হতে পারে, এটি বিপরীত ফাংশনটির জন্য স্থির থাকতে হবে। এটি ও (এন) জটিলতায় রয়েছে।

#include<stdio.h>
#include<stdlib.h>

typedef struct List* List;
struct List {
   int val;
   List next;
};

List reverse(List list) { /* with recursion and one static variable*/
    static List tail;
    if(!list || !list->next) {
        tail = list;

        return tail;
    } else {
        reverse1(list->next);
        list->next->next = list;
        list->next = NULL;

        return tail;
    }
}

0

বিকল্প হিসাবে, আপনি পুনরাবৃত্তি- ব্যবহার করতে পারেন

struct node* reverseList(struct node *head)
{
    if(head == NULL) return NULL;
    if(head->next == NULL) return head;

    struct node* second = head->next;       
    head->next = NULL;

    struct node* remaining = reverseList(second);
    second->next = head;

    return remaining;
}

এই কিভাবে সঠিক। আপনি দু'বারের বেশি পয়েন্টার ব্যবহার করছেন, এটি প্রতিবার কোনও ফাংশন কল করার সময় এটি স্ট্যাকের উপরে লুকানো রয়েছে।
মাইক জি


0
class Node {
    Node next;
    int data;

    Node(int item) {
        data = item;
        next = null;
    }
}

public class LinkedList {

    static Node head;

    //Print LinkedList
    public static void printList(Node node){

        while(node!=null){
            System.out.print(node.data+" ");
            node = node.next;
        }
        System.out.println();
    }

    //Reverse the LinkedList Utility
    public static Node reverse(Node node){

        Node new_node = null;

        while(node!=null){

            Node next = node.next;
            node.next = new_node;
            new_node = node;
            node = next;

        }
        return new_node;
    }

    public static void main(String[] args) {

        //Creating LinkedList
        LinkedList.head = new Node(1);
        LinkedList.head.next = new Node(2);
        LinkedList.head.next.next = new Node(3);
        LinkedList.head.next.next.next = new Node(4);

        LinkedList.printList(LinkedList.head);

        Node node = LinkedList.reverse(LinkedList.head);

        LinkedList.printList(node);

    }


}

নোড একটি পয়েন্টার নয়, আমরা কেবল নোড হিসাবে মাথা পেরিয়েছি। আপনার আরও
স্পেসিফিকেশন
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.