The fast ordering and sequencing of single linked lists are the same as the basic idea of fast sorting, which is also based on division, but there is a big difference: a single linked list does not support access based on subscript. In fancier, the sorted list is split into 2 sub lists. For simplicity, select the first node of the list as the benchmark, and then compare it to the sub list on the left, which is larger than the datum, and put it on the right sub-list. After scanning the sorted list, the node value of the left sub list is less than the datum, the value of the right sub list is greater than the datum, and then the datum is inserted into the list and used as a bridge to connect two sub lists. Then, the left and right two sub lists are sorted recursively and quickly to improve performance.
However, because a single linked list cannot be stored as randomly as an array, and the fast ordering of arrays is compared, there are some details to note:
1, the choice of fulcrum, because can not randomly access the k element, so each select fulcrum can be sorted that part of the list of the head pointer.
2, traversing the scale method, because it can not be traversed from the end of a single linked list, so use two pointers to traverse forward backwards the strategy of effectiveness,
In fact, you can use a traversal to put smaller elements on the left side of a single linked list. The specific methods are:
1) Define two pointer Pslow,pfast, in which the Pslow point to the first node of the single linked list, and Pfast point to the next node of the single Chain header node;
2 use Pfast to traverse a single linked list, each encounter a smaller than the fulcrum element, make Pslow=pslow->next, and then and Pslow data exchange.
3, the exchange of data methods, direct exchange of the link table data pointer to the part, do not have to exchange the linked list node itself.
Based on the above thought of the single linked list of fast sorting implementation is as follows:
Copy Code code as follows:
/**
* * Quick ordering of single linked lists
* * Author:liuzhiwei
* * date:2011-08-07
**/
#include <iostream>
#include <ctime>
using namespace Std;
Single linked table node
struct Slist
{
int data;
struct slist* next;
};
void Bulid_slist (slist** phead, int n)//pointer to pointer
{
int i;
slist* ptr = *phead;
for (i = 0; i < n; ++i)
{
slist* temp = new Slist;
Temp->data = rand ()% n; Produces a random number within n n
Temp->next = NULL;
if (ptr = NULL)
{
*phead = temp;
ptr = temp;
}
Else
{
Ptr->next = temp;
PTR = ptr->next;
}
}
}
void Print_slist (slist* phead)//Output list
{
Slist *ptr = Phead;
while (PTR)
{
printf ("%d", ptr->data);
PTR = ptr->next;
}
printf ("\ n");
}
void My_swap (int *a,int *b)
{
int temp;
Temp=*a;
*a=*b;
*b=temp;
}
void Sort_slist (slist* phead, slist* pend)//The head pointer is phead and the tail pointer is sorted for the Pend list
{
if (Phead = NULL)
return;
if (Phead = = pend)
return;
Slist *pslow = Phead;
Slist *pfast = phead->next;
Slist *ptemp = Phead;
while (Pfast!= pend)
{
if (Pfast->data < Phead->data)///each time the header node of the sorted list is selected as the basis for partitioning
{
Ptemp = Pslow; Ptemp is always the precursor node of Pslow
Pslow = pslow->next;
My_swap (&pslow->data, &pfast->data); A linked list of nodes with a pslow pointer pointing to a smaller point than the Datum
}
Pfast = pfast->next;
}
My_swap (&pslow->data, &phead->data); At this point the Pslow pointer points to the last node of the linked list of nodes that are smaller than the datum, that is, the position of the datum, so it is exchanged with the Datum (Head node).
Sort_slist (Phead, Pslow); Ptemp is the previous node of the left and right two-part split Point (Datum)
Sort_slist (Pslow->next, NULL); The right part is a list of nodes that are larger than the datum.
}
void Destroy_slist (slist* phead)
{
slist* ptr = phead;
while (PTR)
{
slist* temp = ptr;
PTR = ptr->next;
Delete temp;
}
}
int main (void)
{
Srand (Time (NULL));
printf ("Before sort single list\n");
slist* phead = NULL;
Bulid_slist (&phead, 100);
Print_slist (Phead);
printf ("After sort single list\n");
Sort_slist (Phead, NULL);
Print_slist (Phead);
Destroy_slist (Phead);
System ("pause");
return 0;
}
The second method:
Select the first node of the list as the benchmark, and then compare it to the sub list on the left, which is larger than the datum, and put it on the right sub-list. After scanning the sorted list, the node value of the left face list is less than the value of the datum, the value of the right sub-list is greater than the datum, and then the datum is inserted into the list and used as a bridge to connect two sub lists. Then, according to the number of nodes in the left and right sub lists, the smaller ones are sorted by recursion, and the number is iterated.
The variables used in the sort function are as follows:
Copy Code code as follows:
struct node *right; The first node of the Right child link table
struct node **left_walk, **right_walk; As a pointer, the node to which it points is added to the corresponding sub-list
struct node *pivot, *old; Pivot as the base, and the old is a circular pointer to the entire sorted list.
The core code is as follows:
for (old = (*head)->next; old!= end; old = Old->next) {
if (Old->data < Pivot->data) {//Less than datum, add to left sub-list, continue to compare
++left_count;
*left_walk = old; Add the node to the list on the left,
Left_walk = & (Old->next);
else {//greater than datum, add to right sub-list, continue to compare
++right_count;
*right_walk = old;
Right_walk = & (Old->next);
}
}
Head for struct node * * Type, point to the header of the list, end point to the tail of the list, nullable, this program is focused on the use of the pointer pointer, *left_walk as a pointer to node nodes, said clearly *left_ The walk value is the node's memory address, and in fact there is also a place with node's address, which is to point to node nodes of the next domain, so we can simply think of *left_walk = An old is the address of the node that points to node is changed to node old, which can cause two kinds of situations: one is that *left_walk originally pointed to the old node, so there is no change, the other is to change the *right_ Walk points to the next field in the previous node of the node, so that it points to the back node. There are several nodes skipped in the middle, but doing so does not cause any problems because the nodes in the list are either added to the left side of the list or joined to the right of the sub-list, without the loss of the node.
The following is illustrated with a diagram below:
This assumes that the value of the linked list is 5, 2, 4, 6, and 1 at a time. According to the program first head = Left_walk point to 5 node, the old point to 2 node, 2 less than 5, so add 2 to the left of the sub-list, *left_walk=old, we know, *left_walk Point is the first node, This changes the head pointer value so that it points to the second node, and then Left_walk, the old moves back, 4 is also less than 5, so continue the above operation, but this is *left_walk and old point is the same node, did not cause any changes, Left_ Walk and old after the move, 6 is greater than 5, at this time the difference appears, to add it to the right of the sub-list, it is *right_walk = old, in fact, Right_walk Initial to &right, this sentence is equivalent right = old, Even the node that is currently pointing to is the first node in the right sub-list, and later the node that is larger than the datum is added to the node and always joins the tail. At this time Right_walk, and old after moving, 1 less than 5 should be added to the left of the sub-list, *left_walk = old, at this point, *left_walk point to 6, so the function of the statement is to change the node 4 next value, changed it to 1 of the address, So 6 from the original list of decoupling, continue to left_walk and old moved to 9 nodes, should be added to the right of the sub-list, at this point, *right_walk point 1, so the 9 nodes added to 6 nodes behind.
This is the basic sort of process, but there is a problem to be understood, such as nodes struct node *a, *b, *c,node **p, p = &b, if at this point the *p = C, the actual effect is A->next = C; We know that this is equivalent to the N of a The value of the Ext field. And P is just a pointer to a pointer to the address of the node that B points to, so when we change the value of the *p, how do we get to the next of a? (this can be written to verify that this is true)? In fact, we look at the program carefully, left_walk initialized to head, then the first execution *left_walk is to point the head to the starting node of the left list, and then Left_walk is assigned to & (Old->next), This sentence is interesting, we look at the following in the implementation of *left_walk=old, you can simply to an equivalent substitution, *left_walk = old is also equivalent to *& (old->next) = old, that is, Old->nex = old , but the old here is not necessarily the node that Old->next points to, and the Left_walk and Right_walk point to their old nodes, but they are different.
The algorithm is not finished here, this is only a one-time division, the benchmark into the correct position, but also to continue, but the following is relatively simple, is the number of recursive sorting small sub-linked list, iterative processing of the number of nodes larger than the sub-linked table.
The complete code is as follows:
Copy Code code as follows:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
Linked list node
struct node
{
int data;
struct node *next;
};
Quick sort function of linked list
void Qlistsort (struct node **head,struct node *h);
Print linked list
void Print_list (struct node *head)
{
struct node *p;
for (p = head; p!= NULL; p = p->next)
{
printf ("%d", p->data);
}
printf ("\ n");
}
int main (void)
{
struct node *head = NULL;
struct node *p;
int i;
/**
* Initialize the linked list
*/
Srand ((unsigned) time (NULL));
for (i = 1; i < ++i)
{
p = (struct node*) malloc (sizeof (struct node));
P->data = rand ()% 100 + 1;
if (head = = NULL)
{
head = p;
Head->next = NULL;
}
Else
{
P->next = head->next;
Head->next = p;
}
}
Print_list (head);
printf ("---------------------------------\ n");
Qlistsort (&head,null);
Print_list (head);
System ("pause");
return 0;
}
void Qlistsort (struct node **head, struct node *end)
{
struct node *right;
struct node **left_walk, **right_walk;
struct node *pivot, *old;
int count, Left_count, Right_count;
if (*head = end)
Return
do {
Pivot = *head;
Left_walk = head;
Right_walk = &right;
Left_count = Right_count = 0;
Take the first node as the benchmark for comparison, less than the datum in the left of the sub-list,
is greater than the datum in the right sub-list
for (old = (*head)->next; old!= end; old = Old->next)
{
if (Old->data < Pivot->data)
{///less than datum, add to left sub-list, continue to compare
++left_count;
*left_walk = old; Add the node to the list on the left,
Left_walk = & (Old->next);
}
Else
{///greater than datum, add to right sub-list, continue to compare
++right_count;
*right_walk = old;
Right_walk = & (Old->next);
}
}
Merge linked list
*right_walk = end; End Right Linked list
*left_walk = pivot; Put the benchmark in the right place
Pivot->next = right; Merge the linked list
The smaller sub linked list is sorted quickly, and the larger sub list is sorted iteratively.
if (Left_walk > Right_walk)
{
Qlistsort (& (Pivot->next), end);
end = pivot;
Count = Left_count;
}
Else
{
Qlistsort (head, pivot);
Head = & (Pivot->next);
Count = Right_count;
}
}
while (Count > 1);
}