Is it possible to have a linked list of different data types?

后端 未结 11 2066
独厮守ぢ
独厮守ぢ 2020-12-13 22:22

This is just another interview question.

Can we have a linked list of different data types, i.e. each element in a linked list can have different structure or union

相关标签:
11条回答
  • 2020-12-13 22:55

    Just an FYI, In C# you can use Object as your data member.

    class Node
    {
         Node next;
         Object Data;
    }
    

    User can then use something like this to find out which Object the Node stores:

    if (obj.GetType() == this.GetType()) //
    {
    
    }
    
    0 讨论(0)
  • 2020-12-13 23:03

    Yes,Sure You can insert any data type values in the linked list I've designed and its very simple to do so.I have used different constructors of node and boolean variables to check that which type value is inserted and then I do operation and command according to that value in my program.

    //IMPLEMENTATION OF SINGLY LINKED LISTS
    #include"iostream"
    #include"conio.h"
    #include <typeinfo>
    using namespace  std;
    
    
    
    class node //struct
    {
    public:
        node* nextptr;
        int data;
        ////////////////////////////////just to asure that user can insert any data type value in the linked list
        string ss;
        char cc;
        double dd;
        bool stringTrue=0;
        bool intTrue = 0;
        bool charTrue = 0;
        bool doubleTrue = 0;
        ////////////////////////////////just to asure that user can insert any data type value in the linked list
        node()
        {
            nextptr = NULL;
        }
        node(int d)
        {
            data = d;
            nextptr = NULL;
            intTrue = 1;
        }
        ////////////////////////////////just to asure that user can insert any data type value in the linked list
        node(string s)
        {
            stringTrue = 1;
            ss = s;
            nextptr = NULL;
        }
        node(char c)
        {
            charTrue = 1;
            cc = c;
            nextptr = NULL;
        }
        node(double d)
        {
            doubleTrue = 1;
            dd = d;
            nextptr = NULL;
        }
        ////////////////////////////////just to asure that user can insert any data type value in the linked list
        //TO Get the data
        int getintData()
        {
            return data;
        }
        string getstringData()
        {
            return ss;
        }
        double getdoubleData()
        {
            return dd;
        }
        char getcharData()
        {
            return cc;
        }
        //TO Set the data
        void setintData(int d)
        {
            data = d;
        }
        void setstringData(string s)
        {
            ss = s;
        }
        void setdoubleData(double d)
        {
            dd = d;
        }
        void setcharData(char c)
        {
            cc = c;
        }
        char checkWhichInput()
        {
            if (intTrue == 1)
            {
                return 'i';
            }
            else if (stringTrue == 1)
            {
                return 's';
            }
            else if (doubleTrue == 1)
            {
                return 'd';
            }
            else if (charTrue == 1)
            {
                return 'c';
            }
        }
        //////////////////////////////Just for the sake of implementing for any data type//////////////////////////////
        node* getNextptr()
        {
            return nextptr;
        }
        void setnextptr(node* nptr)
        {
            nextptr = nptr;
        }
    };
    
    
    class linkedlist
    {
        node* headptr;
        node* addnodeatspecificpoition;
        
    public:
        linkedlist()
        {
            headptr = NULL;
        }
        void insertionAtTail(node* n)
        {
            if (headptr == NULL)
            {
                headptr = n;
            }
            else
            {
                node* rptr = headptr;
                while (rptr->getNextptr() != NULL)
                {
                    rptr = rptr->getNextptr();
                }
                rptr->setnextptr(n);
            }
        }
    
        void insertionAtHead(node *n)
        {
            node* tmp = n;
            tmp->setnextptr(headptr);
            headptr = tmp;
        }
    
        int sizeOfLinkedList()
        {
            int i = 1;
            node* ptr = headptr;
            while (ptr->getNextptr() != NULL)
            {
                ++i;
                ptr = ptr->getNextptr();
            }
            return i;
        }
    
        bool isListEmpty() {
            if (sizeOfLinkedList() <= 1)
            {
                return true;
            }
            else 
            {
                false;
            }
        }
    
        void insertionAtAnyPoint(node* n, int position)
        {
            if (position > sizeOfLinkedList() || position < 1) {
                cout << "\n\nInvalid insertion at index :" << position;
                cout <<".There is no index " << position << " in the linked list.ERROR.\n\n";
                return;
            }
    
            addnodeatspecificpoition = new node;
            addnodeatspecificpoition = n;
            addnodeatspecificpoition->setnextptr(NULL);
    
            
    
            if (headptr == NULL)
            {
                headptr = addnodeatspecificpoition;
            }
            else if (position == 0)
            {
                addnodeatspecificpoition->setnextptr(headptr);
                headptr = addnodeatspecificpoition;
            }
            else
            {
                node* current = headptr;
                int i = 1;
                for (i = 1; current != NULL; i++)
                {
                    if (i == position)
                    {
                        addnodeatspecificpoition->setnextptr(current->getNextptr());
                        current->setnextptr(addnodeatspecificpoition);
                        break;
                    }
                    current = current->getNextptr();
                }
            }
        }
    
     
        friend ostream& operator<<(ostream& output,const linkedlist& L)
        {
            char checkWhatInput;
            int i = 1;
            node* ptr = L.headptr;
            while (ptr->getNextptr() != NULL)
            {
                ++i;
                checkWhatInput = ptr->checkWhichInput();
                /// <summary>
                switch (checkWhatInput)
                {
                case 'i':output <<ptr->getintData()<<endl;
                    break;
                case 's':output << ptr->getstringData()<<endl;
                    break;
                case 'd':output << ptr->getdoubleData() << endl;
                    break;
                case 'c':output << ptr->getcharData() << endl;
                    break;
                default:
                    break;
                }
                /// </summary>
                /// <param name="output"></param>
                /// <param name="L"></param>
                /// <returns></returns>
                
                ptr = ptr->getNextptr();
            }
    
            /// <summary>
            switch (checkWhatInput)
            {
            case 'i':output << ptr->getintData() << endl;
                break;
            case 's':output << ptr->getstringData() << endl;
                break;
            case 'd':output << ptr->getdoubleData() << endl;
                break;
            case 'c':output << ptr->getcharData() << endl;
                break;
            default:
                break;
            }
            /// </summary>
            /// <param name="output"></param>
            /// <param name="L"></param>
            /// <returns></returns>
    
            if (ptr->getNextptr() == NULL)
            {
                output << "\nNULL (There is no pointer left)\n";
            }
            return output;
        }
        ~linkedlist() {
            delete addnodeatspecificpoition;
        }
    };
    
    
    
    int main()
    {
    
        linkedlist L1;
    
    
        //Insertion at tail
        L1.insertionAtTail(new node("dsaf"));
        L1.insertionAtTail(new node("sadf"));
        L1.insertionAtTail(new node("sfa"));
        L1.insertionAtTail(new node(12));
        L1.insertionAtTail(new node(67));
        L1.insertionAtTail(new node(23));
        L1.insertionAtTail(new node(45.677));
        L1.insertionAtTail(new node(12.43556));
    
    
        //Inserting a node at head
        L1.insertionAtHead(new node(1));
        //Inserting a node at any given point
        L1.insertionAtAnyPoint(new node(999), 3);
    
        cout << L1;
    
        cout << "\nThe size of linked list after insertion of elements is : " << L1.sizeOfLinkedList();    
    }
    
    

    The output is
    1
    dsaf
    sadf
    999
    sfa
    12
    67
    23
    45.677
    12.4356
    Thats what you can use to create a linked list without worrying of data type

    0 讨论(0)
  • 2020-12-13 23:04

    Well in a linked list you don't HAVE to link like for like structs together. As long as they have the appropriate forward and/or backwards pointers you are fine. For example:

    struct BaseLink
    {
       BaseLink* pNext;
       BaseLink* pPrev;
       int       typeId;
    };
    
    struct StringLink
    {
        BaseLink baseLink;
        char* pString;
    };
    
    struct IntLink
    {
        BaseLink baseLink;
        int   nInt;
    };
    

    This way you'd have a linked list that goes from BaseLink to BaseLink. The extra data is not a problem. You want to see it as a StringLink? Then cast the BaseLink to a StringLink.

    Just remember that you need some form of typeid in there so you know what to cast it to when you arrive at it.

    0 讨论(0)
  • 2020-12-13 23:07

    Actually, you don't have to put the pointer first in the structure, you can put it anywhere and then find the beginning fo the struct with a containerof() macro. The linux kernel does this with its linked lists.

    http://isis.poly.edu/kulesh/stuff/src/klist/

    0 讨论(0)
  • 2020-12-13 23:09

    Use union to create the datatype

    union u_tag{
        char ch;
        int d;
        double dl;
    };
    
    struct node {
        char type;
        union u_tag u;
        struct node *next;
    };
    

    Use struct node to create linked list. type decides what is the datatype of the data.

    Harsha T, Bangalore

    0 讨论(0)
  • 2020-12-13 23:11

    You can use a union type:

    enum type_tag {INT_TYPE, DOUBLE_TYPE, STRING_TYPE, R1_TYPE, R2_TYPE, ...};
    struct node {
      union {
        int ival;
        double dval;
        char *sval;
        struct recordType1 r1val;
        struct recordType2 r2val;
        ...
      } data;
      enum type_tag dataType;
      struct node *prev;
      struct node *next;
    };
    

    Another method I've explored is to use a void* for the data and attach pointers to functions that handle the type-aware stuff:

    /**
     * Define a key type for indexing and searching
     */
    typedef ... key_t;                 
    
    /**
     * Define the list node type
     */
    struct node {
      void *data;
      struct node *prev;
      struct node *next;
      void *(*cpy)(void *);            // make a deep copy of the data
      void (*del)(void *);             // delete the data
      char *(*dpy)(void *);            // format the data for display as a string
      int (*match)(void *, key_t);     // match against a key value
    };
    
    /**
     * Define functions for handling a specific data type
     */
    void *copyARecordType(void *data)
    {
      struct aRecordType v = *(struct aRecordType *) data;
      struct aRecordType *new = malloc(sizeof *new);
      if (new)
      {
        // copy elements of v to new
      }
      return new;
    }
    
    void deleteARecordType(void *data) {...}
    char *displayARecordType(void *data) {...}
    int matchARecordType(void *data, key_t key) {...}
    
    /**
     * Define functions for handling a different type
     */
    void *copyADifferentRecordType(void *data) {...}
    void deleteADifferentRecordType(void *data) {...}
    char *displayADifferentRecordType(void *data) {...}
    int matchADifferentRecordType(void *data, key_t key) {...}
    
    /**
     * Function for creating new list nodes
     */
    struct node *createNode(void *data, void *(*cpy)(void *), void (*del)(void *), 
        char *(*dpy)(void *), int (*match)(void *, key_t))
    {
      struct node *new = malloc(sizeof *new);
      if (new)
      {
        new->cpy = cpy;
        new->del = del;
        new->dpy = dpy;
        new->match = match;
        new->data = new->cpy(data);
        new->prev = new->next = NULL;
      }
      return new;
    }
    
    /**
     * Function for deleting list nodes
     */
    void deleteNode(struct node *p)
    {
      if (p)
        p->del(p->data);
      free(p);
    }
    
    /**
     * Add new node to the list; for this example, we just add to the end
     * as in a FIFO queue.  
     */
    void addNode(struct node *head, void *data, void *(*cpy)(void*), 
      void (*del)(void *), char *(*dpy)(void *), int (*match)(void*, key_t))
    {
      struct node *new = createNode(data, cpy, del, dpy, match);
      if (!head->next)
        head->next = new;
      else
      {
        struct node *cur = head->next;
        while (cur->next != NULL)
          cur = cur->next;
        cur->next = new;
        new->prev = cur;
      }
    }
    
    /**
     * Examples of how all of this would be used.
     */
    int main(void)
    {
      struct aRecordType r1 = {...};
      struct aDifferentRecordType r2 = {...};
    
      struct node list, *p;
      addNode(&list, &r1, copyARecordType, deleteARecordType, displayARecordType,
        matchARecordType);
      addNode(&list, &r2, copyADifferentRecordType, deleteADifferentRecordType,
        displayADifferentRecordType, matchADifferentRecordType);
      p = list.next;
      while (p)
      {
        printf("Data at node %p: %s\n", (void*) p, p->dpy(p->data));
        p = p->next;
      }
      return 0;
    }
    

    Obviously, I've left out some error checking and handling code from this example, and I don't doubt there are a host of problems with it, but it should be illustrative.

    0 讨论(0)
提交回复
热议问题