單鏈表排序
初始化:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
//節點結構
struct node
{
int val;
struct node * next;
};
typedef struct node node, * list;
//打印函數
void printList(list mylist);
//排序函數
//插入排序
void insertSort(list mylist);
//冒泡排序
void bubbleSort(list mylist);
//簡單選擇
void selectSort(list mylist);
//快速排序
void quickSort(list mylist);
int main(void)
{
int arr[] = {5, 1, 7, 4, 2, 9, 6, 3, 8};
//程序都是針對有頭結點的單向鏈表
list mylist = (list)malloc(sizeof(node));
mylist -> val = 0;
mylist -> next = NULL;
int len = sizeof(arr) / sizeof(arr[0]);
int i = 0;
node * cur = mylist;
while(i < len)
{
node * newNode = (node *)malloc(sizeof(node));
newNode -> val = arr[i];
newNode -> next = NULL;
cur -> next = newNode;
cur = cur -> next;
i ++;
}
//insertSort(mylist);
//bubbleSort(mylist);
//selectSort(mylist);
quickSort(mylist);
printList(mylist);
return 0;
}
void printList(list mylist)
{
node * cur = mylist -> next;
while(cur != NULL)
{
printf("%d ", cur -> val);
cur = cur -> next;
}
printf("\n");
}
---------------------
一、交換節點的單鏈表排序:
交換節點的情況比較複雜,所以我只是寫了比較簡單的三個。
1 、插入排序:
//=============插入排序====================
void insertSort(list mylist)
{
if((mylist -> next == NULL) || (mylist -> next -> next == NULL))
{
return;
}
node * head, * p1, * prep1, * p2, * prep2, * temp;
head = mylist;
prep1 = head -> next;
p1 = prep1 -> next;
//prep1和p1是否需要手動後移
bool flag;
while(p1 != NULL)
{
flag = true;
temp = p1;
//由於是單向鏈表,所以只能從頭部開始檢索
for(prep2 = head, p2 = prep2 -> next; p2 != p1; prep2 = prep2 -> next, p2 = p2 -> next)
{
//發現第一個較大值
if(p2 -> val > p1 -> val)
{
p1 = p1 -> next;
prep1 -> next = p1;
prep2 -> next = temp;
temp -> next = p2;
flag = false;
break;
}
}
//手動後移prep1和p1
if(flag)
{
prep1 = prep1 -> next;
p1 = p1 -> next;
}
}
}
//=============插入排序====================
2、冒泡排序:
//=冒泡排序========
void bubbleSort(list mylist)
{
if((mylist -> next == NULL) || (mylist -> next -> next == NULL))
{
return;
}
node *head, * pre, * cur, *next, * end, * temp;
head = mylist;
end = NULL;
//從鏈表頭開始將較大值往後沉
while(head -> next != end)
{
for(pre = head, cur = pre -> next, next = cur -> next; next != end; pre = pre -> next, cur = cur -> next, next = next -> next)
{
//相鄰的節點比較
if(cur -> val > next -> val)
{
cur -> next = next -> next;
pre -> next = next;
next -> next = cur;
temp = next;
next = cur;
cur = temp;
}
}
end = cur;
}
}
//=冒泡排序========
3.簡單選擇排序:
//=簡單選擇排序====
void selectSort(list mylist)
{
if((mylist -> next == NULL) || (mylist -> next -> next == NULL))
{
return;
}
node * head, * prep1, * p1, * prep2, * p2, * premin, * min, * temp;
head = mylist;
for(prep1 = head, p1 = prep1 -> next; p1 -> next != NULL; prep1 = prep1 -> next, p1 = prep1 -> next)
{
//保存最小節點
premin = prep1;
min = p1;
for(prep2 = p1, p2 = prep2 -> next; p2 != NULL; prep2 = prep2 -> next, p2 = prep2 -> next)
{
if(min -> val > p2 -> val)
{
premin = prep2;
min = p2;
}
}
if(p1 != min)
{
//一定要注意這個情況
if(p1 -> next == min)
{
temp = min -> next;
prep1 -> next = min;
min -> next = p1;
p1 -> next = temp;
}else{
temp = min -> next;
prep1 -> next = min;
min -> next = p1 -> next;
premin -> next = p1;
p1 -> next = temp;
}
}
}
}
//=簡單選擇排序====
一、交換數據的單鏈表排序:
交換數據的排序方式就特別簡單了,因爲不用考慮前驅和後繼,只需要標記待交換的兩個節點即可。因此在這裏就直接介紹一下快速排序。
快速排序:
//=============快速排序====================
//交換節點
void swap(node * a, node * b)
{
int temp = a -> val;
a -> val = b -> val;
b -> val = temp;
}
//求中間點
node * partion(node * start, node * end)
{
if(start == end || start -> next == end)
{
return start;
}
//取第一個元素作爲基準元素
node * p = start, * q = start, * refer = start;
//從start開始向後進行一次遍歷(因爲是單鏈表,無法按從左右向中間遍歷的方法)
while(q != end)
{
if(q -> val < refer -> val)
{
p = p -> next;
swap(p, q);
}
q = q -> next;
}
swap(p, refer);
return p;
}
//遞歸
void quick_sort(node * start, node * end)
{
if(start == end || start -> next == end)
{
return;
}
node * mid = partion(start, end);
quick_sort(start, mid);
quick_sort(mid -> next, end);
}
void quickSort(list mylist)
{
if((mylist -> next == NULL) || (mylist -> next -> next == NULL))
{
return;
}
node * start = mylist -> next;
node * end = NULL;
quick_sort(start, end);
}
---------------------