Linked List
2017-01-11 20:48
127 查看
Introduction:
Like arrays, Linked List is a linear data structure.Unlike arrays, linked list elements are not stored at contiguous location; the elements are linked using pointers.
Why Linked List ?
The limitations of array:1) The size of the arrays is fixed: So we must know the upper limit on the number of elements in advance. Also, generally, the allocated memory is equal to the upper limit irrespective of the usage.
2) Inserting a new element in an array of elements is expensive, because room has to be created for the new elements and to create room existing elements have to shifted.
Deletion is also expensive with arrays until unless some special techniques are used.
Advantages over Linked List:
1) Dynamic size
2) Ease of insertion/deletion
Drawbacks:
1) Random access is not allowed. We have to access elements sequentially starting from the first node. So we cannot do binary search with linked lists.
2) Extra memory space for a pointer is required with each element of the list.
3) Arrays have better cache locality that can make a pretty big difference in performance.
Representation in C:
A linked list is represented by a pointer to the first node of the linked list. The first node is called head. If the linked list is empty, then value of head is NULL.
Each node in a list consists of at least two parts:
1) data
2) pointer to the next node
In C, we can represent a node using structures. Below is an example of a linked list node with an integer data.
In Java, LinkedList can be represented as a class and a Node as a separate class. The LinkedList class contains a reference of Node class type.
singly linked list
node
// A linked list node struct node { int data; struct node *next; };
traversal
// linked list traversal void printList(struct node *head) { while(head) { printf("%d ", head -> data); head = head -> next; } }
insert
at the frontafter the given node
at the end
// insert node // 1. at the front /* we need the pointer of pointer head for we have to change the head pointer's pointing object, * that is from prev_node to new_node; */ void push_front(struct node **head, int new_data) { // allocate node struct node *new_node = (struct node *)malloc(sizeof(struct node)); if (!new_node) return ; // put in the data new_node -> data = new_data; // if list is empty, head is new_node if(!*head) { *head = new_node; new_node -> next = NULL; return ; } // make next of new node as head new_node -> next = *head; // move the head to point to the new node *head = new_node; } // 2. after a given node /* we don't need the pointer of the pointer pre_node *for we don't have to change the pointer's pointing object; */ void push_mid(struct node *pre_node, int new_data) { // check if the given pre_node is NULL if(!pre_node) return ; // allocate node struct node *new_node = (struct node *)malloc(sizeof(struct node)); if(!new_node) return ; // put in the data new_node -> data = new_data; // make next of the new node as next of the prev_node new_node -> next = pre_node -> next; // move the next of the pre_node as new_node pre_node -> next = new_node; } // 3. at the end /* we need the pointer of the pointer head * for we may change it when the new_node is first node * This method can also be optimized to work in O(1) by keeping an extra pointer to tail of linked list/ */ void push_end(struct node **head, int new_data) { // allocate new node struct node *new_node = (struct node *)malloc(sizeof(struct node)); if(!new_node) return; // put in the data new_node -> data = new_data; // the new_node is the last node,so its next is NULL new_node -> next = NULL; // if the linked list is NULL, then the new node is the head node if (!*head) { *head = new_node; return ; } // find the tail node struct node *tail = *head; while(tail -> next != NULL) { tail = tail -> next; } // change the node of the last node tail -> next = new_node; return ; }
delete
delete a given nodedelete a given position
// delete node // delete a given key void pop_key(struct node **head, int key) { struct node *temp = *head, *prev; // if head itself is the key to be deleted, and then exit if(temp && temp -> data == key) { *head = temp -> next; free(temp); return ; } // search for the data to be deleted while(temp && temp -> data != key) { prev = temp; temp = temp -> next; } prev -> next = temp -> next; // If data was not present in the linked list if(temp == NULL) return ; free(temp); } // 2. delete a node at a given position // pos starts from 0 void pop_pos(struct node **head, int pos) { struct node *temp = *head; // if linked list is empty if(!*head) return ; // if head needs to be removed if(!pos) { *head = temp -> next; free(temp); return ; } //find previous node of the node to be deleted for (int i = 0; i < pos - 1 && temp != NULL ;i++) { temp = temp -> next; } // if position is more than numbers of nodes if(!temp || !temp -> next) return ; // node temp -> next is the node to be deleted // nextn is the next node of the node to be deleted struct node *nextn = temp -> next -> next; free(temp -> next); temp -> next = nextn; }
[b]Remove Linked List Elements(LeetCode)[/b]
Remove all elements from a linked list of integers that have value val.
/** * Definition for singly-linked list. * struct ListNode { * int val; * struct ListNode *next; * }; */ struct ListNode* removeElements(struct ListNode* head, int val) { int count = 0; struct ListNode *p = NULL, *temp = NULL, *prev; for (p = head; p != NULL; p = p -> next) { if(p -> val == val) { if(p == head) { temp = head; head = head -> next; } else { temp = p; prev -> next = p -> next; } free(temp); } else prev = p; } return head; }
search
// search an given element in a Linked LIst , return true if the element is present. // C90 does not support the boolean data type. // C99 does include it with this include: #include <stdbool.h> // or define ourselves : typedef enum { false, true } bool; bool search_it(struct node *head, int x) { while(head && head -> data != x) { head = head -> next; } return (head == NULL) ? false : true; } bool search_re(struct node *head, int x) { if(!head) return false; if(head -> data == x) return true; return search_re(head -> next, x); }
[b]Find n’th node from the end of a Linked List(geek)[/b]
1. 循环得到总结点数,再换成从前往后查找; /* struct Node { int data; Node* next; }; */ /* Should return data of n'th node from the end of linked list */ int getNthFromLast(Node *head, int n) { // Your code here int count = 0; struct Node *temp = head; while(temp) { count ++; temp = temp -> next; } temp = head; int n1 = count - n; if(n1 < 0) return -1; while(n1--) { temp = temp -> next; } return temp -> data; }
2. 两个指针,第一个指向第一个位置,第二个指向第n个位置,第一和第二个指针同步往前遍历,第二个指针到底时第一个指针即为所求; /* struct Node { int data; Node* next; }; */ /* Should return data of n'th node from the end of linked list */ int getNthFromLast(Node *head, int n) { // Your code here struct Node *first = head; struct Node *second = head; while(--n) { if(!second -> next) return -1; else second = second -> next; } while(second -> next) { second = second -> next; first = first -> next; } return first -> data; }
关于递归,如果是打印的话很简单,但是return的话不容易做;
swap
void swap(struct node **head, int x, int y) { // make sure x != y if(x == y) { printf("the two given numbers are the same"); return ; } // at least two distinct node if(!*head || !(*head) -> next) { printf("the list is empty, please use push_end to push some elements first"); return ; } // Search for X(keep track of prevX and currX) struct node *prevX = NULL, *currX = *head ; while(currX && currX -> data != x) { prevX = currX; currX = currX -> next; } // Search for Y(keep track of prevY and currY) struct node *prevY = NULL, *currY = *head; while(currY && currY -> data != y) { prevY = currY; currY = currY -> next; } // if X or Y is not present, return if(!currX || !currY) { printf("X or Y is not present"); return ; } // change the previous pointer of currX and currY if(prevX) prevX -> next = currY; else *head = currY; if(prevY) prevY -> next = currX; else *head = currX; // swap next pointer struct node *temp = currY -> next; currY -> next = currX -> next; currX -> next = temp; }
reverse
iterative :void reverse_it(struct node **head) { if(!*head) { printf("the list is empty"); return ; } struct node *curr = (*head) -> next, *prev = *head, *latter = curr; while(curr) { latter = curr -> next; curr -> next = prev; prev = curr; curr = latter; } (*head) -> next = NULL; *head = prev; }
recursive:
void reverse_re(struct node** head) { if(!head) return ; struct node *first = *head, *second = first -> next; if(!second) return ; reverse_re(&second); // second will change, so we can't use second -> next = first; first -> next -> next = first; first -> next = NULL; *head = second; } void reverse_re1(struct node *p, struct node **head) { if(!p -> next) { *head = p; return ; } reverse_re1(p -> next, head); struct node *q = p -> next; q -> next = p; p -> next = NULL; }
main for test
int main() { // start with the empty list struct node *head = NULL; push_front(&head, 1); push_end(&head, 3); push_mid(head, 2); printList(head); puts("\nNow delete data 1"); pop_key(&head, 1); printList(head); puts("\nNow delete position 1"); pop_pos(&head, 1); printList(head); return 0; }
Doubly Linked List
node
// A doubly list node struct node { int data; struct node *prev; struct node *next; };
insert
// add a node at the front void push_front(struct node **head, int new_data) { // allocate node struct node *new_node = malloc(sizeof(struct node)); if(!new_node) return ; // put in the data new_node -> data = new_data; // next to head, prev to NULL new_node -> next = *head; new_node -> prev = NULL; // head prev to new_node if(*head) (*head) -> prev = new_node; // head moves to new_node *head = new_node; } //insert after a given node void push_after(struct node *prev_node, int new_data) { // check if the given node is NULL if(!prev_node) return ; // allocate node struct node *new_node = malloc(sizeof(struct node)); if(!new_node) return ; // put in the data new_node -> data = new_data; new_node -> prev = prev_node; new_node -> next = prev_node -> next; prev_node -> next = new_node; if(new_node -> next) new_node -> next -> prev = new_node; } void push_end(struct node **head, int new_data) { struct node *new_node = malloc(sizeof(struct node)); if(!new_node) return ; new_node -> data = new_data; new_node -> next = NULL; if(!*head) { new_node -> prev = NULL; *head = new_node; return ; } while(*head -> next) { *head = (*head) -> next; } }
/* 未完待续 */
相关文章推荐
- [c/c++] C数据结构: 链表 Linked List
- [LeetCode]234.Palindrome Linked List
- LeetCode总结2-Linked List
- leetcode-234. Palindrome Linked List
- 234. Palindrome Linked List
- Linked List的基本操作(创建/删除/插入/查找)
- 234. Palindrome Linked List
- 234. Palindrome Linked List
- leetcode 234. Palindrome Linked List
- Linked List
- leetcode Ch5-Linked List
- 234. Palindrome Linked List
- 234. Palindrome Linked List
- Leetcode 234. Palindrome Linked List
- leetcode(65).234. Palindrome Linked List
- [leetcode]234. Palindrome Linked List
- 234. Palindrome Linked List
- leetcode 234. Palindrome Linked List
- Convert Binary Search Tree (BST) to Sorted Doubly-Linked List
- (easy)LeetCode 205.Reverse Linked List