前言:学了很多排序,感受最深的一点——算法的多样性
先上代码:
#include <stdio.h>
#include <malloc.h>
#define TABLE_SIZE 19
/**
* <key, value> pair.
*/
typedef struct Node{
int key;
char value;
}Node, *NodePtr;
/**
* <key, value> pair.
*/
typedef struct SequentialList{
int length;
NodePtr elements;
}SequentialList, *ListPtr;
/**
* Initialize a data array.
*/
ListPtr initList(int* paraKeys, char* paraValues, int paraLength){
int i;
ListPtr resultPtr = (ListPtr)malloc(sizeof(struct SequentialList));
resultPtr->length = paraLength;
resultPtr->elements = (NodePtr)malloc(paraLength * sizeof(struct Node));
for (i = 0; i < paraLength; i ++){
//printf("setting key for index %d: %d and value: %c\r\n", i, paraKeys[i], paraValues[i]);
resultPtr->elements[i].key = paraKeys[i];
resultPtr->elements[i].value = paraValues[i];
}//Of for i
return resultPtr;
}//Of initList
/**
* Print the list.
*/
void printList(ListPtr paraPtr) {
int i;
printf("(Keys, values)\r\n");
for (i = 0; i < paraPtr->length; i ++) {
printf("%d\t", paraPtr->elements[i].key);
}//Of for i
printf("\r\n");
for (i = 0; i < paraPtr->length; i ++) {
printf("%c\t", paraPtr->elements[i].value);
}//Of for i
}//Of printList
/**
* Insertion sort. paraPtr->elements[0] does not store a valid data. paraPtr->elements[0].key should
* be smaller than any valid key.
*/
void insertionSort(ListPtr paraPtr) {
Node tempNode;
int j;
for (int i = 2; i < paraPtr->length; i++) {
tempNode = paraPtr->elements[i];
//Find the position to insert.
//At the same time, move other nodes.
for (j = i - 1; paraPtr->elements[j].key > tempNode.key; j--) {
paraPtr->elements[j + 1] = paraPtr->elements[j];
} // Of for j
//Insert.
paraPtr->elements[j + 1] = tempNode;
} // Of for i
}// Of insertionSort
/**
* Test the method.
*/
void insertionSortTest() {
int tempUnsortedKeys[] = { -100, 5, 3, 6, 10, 7, 1, 9 };
char tempContents[] = { 'n', 'i', 't', 'e', 's', 'c', 'f', 'w' };
ListPtr tempList = initList(tempUnsortedKeys, tempContents, 8);
printf("\r\nBefore insertion sort:\r\n");
printList(tempList);
insertionSort(tempList);
printf("\r\nAfter insertion sort:\r\n");
printList(tempList);
}// Of insertionSortTest
/**
* Shell sort.
*/
void shellSort(ListPtr paraPtr) {
Node tempNode;
int tempJumpArray[] = { 5, 3, 1 };
int tempJump;
int p, i, j, k;
for (i = 0; i < 3; i++) {
tempJump = tempJumpArray[i];
for (j = 0; j < tempJump; j++) {
for (k = j + tempJump; k < paraPtr->length; k += tempJump) {
tempNode = paraPtr->elements[k];
// Find the position to insert.
// At the same time, move other nodes.
for (p = k - tempJump; p >= 0; p -= tempJump) {
if (paraPtr->elements[p].key > tempNode.key) {
paraPtr->elements[p + tempJump] = paraPtr->elements[p];
} else {
break;
} // Of if
} // Of for p
// Insert.
paraPtr->elements[p + tempJump] = tempNode;
} // Of for k
} // Of for j
} // Of for i
}// Of shellSort
/**
* Test the method.
*/
void shellSortTest() {
int tempUnsortedKeys[] = {5, 3, 6, 10, 7, 1, 9 };
char tempContents[] = {'i', 't', 'e', 's', 'c', 'f', 'w' };
ListPtr tempList = initList(tempUnsortedKeys, tempContents, 7);
printf("\r\nBefore shell sort:\r\n");
printList(tempList);
shellSort(tempList);
printf("\r\nAfter shell sort:\r\n");
printList(tempList);
}// Of shellSortTest
/**
* Bubble sort.
*/
void bubbleSort(ListPtr paraPtr) {
bool tempSwapped;
Node tempNode;
int i, j;
for (i = paraPtr->length - 1; i > 0; i--) {
tempSwapped = false;
for (j = 0; j < i; j++) {
if (paraPtr->elements[j].key > paraPtr->elements[j + 1].key) {
// Swap.
tempNode = paraPtr->elements[j + 1];
paraPtr->elements[j + 1] = paraPtr->elements[j];
paraPtr->elements[j] = tempNode;
tempSwapped = true;
} // Of if
} // Of for j
// No swap in this round. The data are already sorted.
if (!tempSwapped) {
printf("Premature.\r\n");
break;
} // Of if
} // Of for i
}// Of bubbleSort
/**
* Test the method.
*/
void bubbleSortTest() {
int tempUnsortedKeys[] = {5, 3, 6, 10, 7, 1, 9 };
char tempContents[] = {'i', 't', 'e', 's', 'c', 'f', 'w' };
ListPtr tempList = initList(tempUnsortedKeys, tempContents, 7);
printf("\r\nBefore bubble sort:\r\n");
printList(tempList);
shellSort(tempList);
printf("\r\nAfter bubble sort:\r\n");
printList(tempList);
}// Of bubbleSortTest
/**
* Quick sort recursive.
*/
void quickSortRecursive(ListPtr paraPtr, int paraStart, int paraEnd) {
int tempPivot, tempLeft, tempRight;
Node tempNodeForSwap;
// Nothing to sort.
if (paraStart >= paraEnd) {
return;
} // Of if
tempPivot = paraPtr->elements[paraEnd].key;
tempLeft = paraStart;
tempRight = paraEnd - 1;
// Find the position for the pivot.
// At the same time move smaller elements to the left and bigger one to the
// right.
while (true) {
while ((paraPtr->elements[tempLeft].key < tempPivot) && (tempLeft < tempRight)) {
tempLeft++;
} // Of while
while ((paraPtr->elements[tempRight].key >= tempPivot) && (tempLeft < tempRight)) {
tempRight--;
} // Of while
if (tempLeft < tempRight) {
// Swap.
//System.out.println("Swapping " + tempLeft + " and " + tempRight);
tempNodeForSwap = paraPtr->elements[tempLeft];
paraPtr->elements[tempLeft] = paraPtr->elements[tempRight];
paraPtr->elements[tempRight] = tempNodeForSwap;
} else {
break;
} // Of if
} // Of while
// Swap
if (paraPtr->elements[tempLeft].key > tempPivot) {
tempNodeForSwap = paraPtr->elements[paraEnd];
paraPtr->elements[paraEnd] = paraPtr->elements[tempLeft];
paraPtr->elements[tempLeft] = tempNodeForSwap;
} else {
tempLeft++;
} // Of if
//System.out.print("From " + paraStart + " to " + paraEnd + ": ");
//System.out.println(this);
quickSortRecursive(paraPtr, paraStart, tempLeft - 1);
quickSortRecursive(paraPtr, tempLeft + 1, paraEnd);
}// Of quickSortRecursive
/**
* Quick sort.
*/
void quickSort(ListPtr paraPtr) {
quickSortRecursive(paraPtr, 0, paraPtr->length - 1);
}// Of quickSort
/**
* Test the method.
*/
void quickSortTest() {
int tempUnsortedKeys[] = {5, 3, 6, 10, 7, 1, 9 };
char tempContents[] = {'i', 't', 'e', 's', 'c', 'f', 'w' };
ListPtr tempList = initList(tempUnsortedKeys, tempContents, 7);
printf("\r\nBefore quick sort:\r\n");
printList(tempList);
quickSort(tempList);
printf("\r\nAfter quick sort:\r\n");
printList(tempList);
}// Of quickSortTest
/**
* Selection sort.
*/
void selectionSort(ListPtr paraPtr) {
Node tempNode;
int tempIndexForSmallest, i, j;
for (i = 0; i < paraPtr->length - 1; i++) {
// Initialize.
tempNode = paraPtr->elements[i];
tempIndexForSmallest = i;
for (j = i + 1; j < paraPtr->length; j++) {
if (paraPtr->elements[j].key < tempNode.key) {
tempNode = paraPtr->elements[j];
tempIndexForSmallest = j;
} // Of if
} // Of for j
// Change the selected one with the current one.
paraPtr->elements[tempIndexForSmallest] = paraPtr->elements[i];
paraPtr->elements[i] = tempNode;
} // Of for i
}// Of selectionSort
/**
* Test the method.
*/
void selectionSortTest() {
int tempUnsortedKeys[] = {5, 3, 6, 10, 7, 1, 9 };
char tempContents[] = {'i', 't', 'e', 's', 'c', 'f', 'w' };
ListPtr tempList = initList(tempUnsortedKeys, tempContents, 7);
printf("\r\nBefore selection sort:\r\n");
printList(tempList);
selectionSort(tempList);
printf("\r\nAfter selection sort:\r\n");
printList(tempList);
}// Of selectionSortTest
/**
* Adjust heap.
*/
void adjustHeap(ListPtr paraPtr, int paraStart, int paraLength) {
Node tempNode = paraPtr->elements[paraStart];
int tempParent = paraStart;
int tempKey = paraPtr->elements[paraStart].key;
for (int tempChild = paraStart * 2 + 1; tempChild < paraLength; tempChild = tempChild * 2 + 1) {
// The right child is bigger.
if (tempChild + 1 < paraLength) {
if (paraPtr->elements[tempChild].key < paraPtr->elements[tempChild + 1].key) {
tempChild++;
} // Of if
} // Of if
//System.out.println("The parent position is " + tempParent + " and the child is " + tempChild);
if (tempKey < paraPtr->elements[tempChild].key) {
// The child is bigger.
paraPtr->elements[tempParent] = paraPtr->elements[tempChild];
//System.out.println("Move " + paraPtr->elements[tempChild].key + " to position " + tempParent);
tempParent = tempChild;
} else {
break;
} // Of if
} // Of for tempChild
paraPtr->elements[tempParent] = tempNode;
}// Of adjustHeap
/**
* Heap sort.
*/
void heapSort(ListPtr paraPtr) {
Node tempNode;
int i;
// Step 1. Construct the initial heap.
for (i = paraPtr->length / 2 - 1; i >= 0; i--) {
adjustHeap(paraPtr, i, paraPtr->length);
} // Of for i
// Step 2. Swap and reconstruct.
for (i = paraPtr->length - 1; i > 0; i--) {
tempNode = paraPtr->elements[0];
paraPtr->elements[0] = paraPtr->elements[i];
paraPtr->elements[i] = tempNode;
adjustHeap(paraPtr, 0, i);
//System.out.println("Round " + (length - i) + ": " + this);
} // Of for i
}// Of heapSort
/**
* Test the method.
*/
void heapSortTest() {
int tempUnsortedKeys[] = {5, 3, 6, 10, 7, 1, 9 };
char tempContents[] = {'i', 't', 'e', 's', 'c', 'f', 'w' };
ListPtr tempList = initList(tempUnsortedKeys, tempContents, 7);
printf("\r\nBefore heap sort:\r\n");
printList(tempList);
heapSort(tempList);
printf("\r\nAfter heap sort:\r\n");
printList(tempList);
}// Of heapSortTest
/**
* Selection sort.
*/
void mergeSort(ListPtr paraPtr) {
// Step 1. Allocate space.
int tempRow; // The current row
int tempGroups; // Number of groups
int tempActualRow; // Only 0 or 1
int tempNextRow = 0;
int tempGroupNumber;
int tempFirstStart, tempSecondStart, tempSecondEnd;
int tempFirstIndex, tempSecondIndex;
int tempNumCopied;
int i;
int tempSize;
/*
ListPtr tempMatrix[2];
int* tempIntArray = (int*)malloc(paraPtr->length * sizeof(int));
char* tempCharArray = (char*)malloc(paraPtr->length * sizeof(char));
tempMatrix[0] = paraPtr;
tempMatrix[1] = initList(tempIntArray, tempCharArray, paraPtr->length);
*/
Node** tempMatrix = (Node**)malloc(2 * sizeof(Node*));
tempMatrix[0] = (Node*)malloc(paraPtr->length * sizeof(Node));
tempMatrix[1] = (Node*)malloc(paraPtr->length * sizeof(Node));
for (i = 0; i < paraPtr->length; i ++) {
tempMatrix[0][i] = paraPtr->elements[i];
}//Of for i
/*
Node tempMatrix[2][length];
// Step 2. Copy data.
for (i = 0; i < length; i++) {
tempMatrix[0][i] = data[i];
} // Of for i
*/
// Step 3. Merge. log n rounds
tempRow = -1;
for (tempSize = 1; tempSize <= paraPtr->length; tempSize *= 2) {
// Reuse the space of the two rows.
tempRow++;
//System.out.println("Current row = " + tempRow);
tempActualRow = tempRow % 2;
tempNextRow = (tempRow + 1) % 2;
tempGroups = paraPtr->length / (tempSize * 2);
if (paraPtr->length % (tempSize * 2) != 0) {
tempGroups++;
} // Of if
//System.out.println("tempSize = " + tempSize + ", numGroups = " + tempGroups);
for (tempGroupNumber = 0; tempGroupNumber < tempGroups; tempGroupNumber++) {
tempFirstStart = tempGroupNumber * tempSize * 2;
tempSecondStart = tempGroupNumber * tempSize * 2 + tempSize;
if (tempSecondStart > paraPtr->length - 1) {
// Copy the first part.
for (i = tempFirstStart; i < paraPtr->length; i++) {
tempMatrix[tempNextRow][i] = tempMatrix[tempActualRow][i];
} // Of for i
continue;
} // Of if
tempSecondEnd = tempGroupNumber * tempSize * 2 + tempSize * 2 - 1;
if (tempSecondEnd > paraPtr->length - 1) {
tempSecondEnd = paraPtr->length - 1;
} // Of if
tempFirstIndex = tempFirstStart;
tempSecondIndex = tempSecondStart;
tempNumCopied = 0;
while ((tempFirstIndex <= tempSecondStart - 1)
&& (tempSecondIndex <= tempSecondEnd)) {
if (tempMatrix[tempActualRow][tempFirstIndex].key <= tempMatrix[tempActualRow][tempSecondIndex].key) {
tempMatrix[tempNextRow][tempFirstStart
+ tempNumCopied] = tempMatrix[tempActualRow][tempFirstIndex];
tempFirstIndex++;
//System.out.println("copying " + tempMatrix[tempActualRow][tempFirstIndex]);
} else {
tempMatrix[tempNextRow][tempFirstStart
+ tempNumCopied] = tempMatrix[tempActualRow][tempSecondIndex];
//System.out.println("copying " + tempMatrix[tempActualRow][tempSecondIndex]);
tempSecondIndex++;
} // Of if
tempNumCopied++;
} // Of while
while (tempFirstIndex <= tempSecondStart - 1) {
tempMatrix[tempNextRow][tempFirstStart
+ tempNumCopied] = tempMatrix[tempActualRow][tempFirstIndex];
tempFirstIndex++;
tempNumCopied++;
} // Of while
while (tempSecondIndex <= tempSecondEnd) {
tempMatrix[tempNextRow][tempFirstStart
+ tempNumCopied] = tempMatrix[tempActualRow][tempSecondIndex];
tempSecondIndex++;
tempNumCopied++;
} // Of while
} // Of for groupNumber
} // Of for tempStepSize
for (i = 0; i < paraPtr->length; i ++) {
paraPtr->elements[i] = tempMatrix[tempNextRow][i];
}//Of for i
}// Of mergeSort
/**
* Test the method.
*/
void mergeSortTest() {
int tempUnsortedKeys[] = {5, 3, 6, 10, 7, 1, 9 };
char tempContents[] = {'i', 't', 'e', 's', 'c', 'f', 'w' };
ListPtr tempList = initList(tempUnsortedKeys, tempContents, 7);
printf("\r\nBefore merge sort:\r\n");
printList(tempList);
mergeSort(tempList);
printf("\r\nAfter merge sort:\r\n");
printList(tempList);
}// Of mergeSortTest
/**
* The entrance of the program.
*/
int main() {
insertionSortTest();
//shellSortTest();
//bubbleSortTest();
//quickSortTest();
//selectionSortTest();
//heapSortTest();
//mergeSortTest();
return 1;
}// Of main
运行结果:
1、直接插入排序
从第一个元素开始,依次取出,比较取出的元素和其左边的所有元素,如果比左边所有元素大,则直接插入,否则依次将比该元素大的元素向后移动,然后插入即可。
每次保证前 i 个数据是有序的.
先做简单的事情 (第 1 轮最多有 1 次移动), 再做麻烦的事情 (最后一轮最多有 n − 1 n - 1n−1 次移动).
下标 0 的数据为岗哨. 比其它排序方式多用一个空间.
2、希尔排序
用元素个数除以2或3求得间距d1,从第一个元素开始,每隔d1个间距的元素分为一组,将每组的元素排序,再将d1除以2或3求得间距d2,同上,直到间距变为1。
多达 4 重循环, 但时间复杂度只有 O ( n 2 ) O(n^2 )O(n2).
可以改变 tempJumpArray.
3、折半插入排序(二分查找)
key为要查找的元素,先将low指向第一个元素,high指向最后一个元素,在low<high的条件下,mid指向中间的元素,如果midVal<key,low=mid+1;如果midVal>key,high=mid-1;如果midVal=key,则查找成功。low>high则查找失败。
注意:在有序的一组数中查找。
4、简单选择排序(直接选择排序)
首先从1到n这n个记录中找出最小关键字所在的记录,然后把它与第1个记录交换位置,接着再从2到n这n-1个记录中,找出最小(也就是整个文件中次小的)关键字所在的记录和第2个记录交换位置,依次进行,直到从n-1到n,最后两个记录中,找出最小关键字所在记录把它和n-1位置上的记录交换位置为止,排序结束。
5、堆排序
a.将无序序列构建成一个堆(完全二叉树),根据升序降序需求选择大顶堆或小顶堆;
b.将堆顶元素与末尾元素互换,将最大(小)元素沉到数组末端;
c.重新调整结构,使其满足堆定义,然后继续交换堆顶元素与当前末尾元素,反复执行调整+交换步骤,直到整个序列有序。
6、冒泡排序
时间复杂度: 最好复杂度:O(n) ; 最坏复杂度:O(n2); 平均复杂度:O(n2) 稳定
7、快速排序
通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
快排第i趟至少应有i个元素就位。(元素的左边元素都小于该元素,元素的右边元素都小于该元素。)
a.设置两个变量i、j,排序开始的时候:i=0,j=N-1;
b.以第一个数组元素作为关键数据,赋值给key,即key=A[0];
c.从j开始向前搜索,即由后开始向前搜索(j–),找到第一个小于key的值A[j],将A[j]和A[i]的值交换;
d.从i开始向后搜索,即由前开始向后搜索(i++),找到第一个大于key的A[i],将A[i]和A[j]的值交换;
e.重复第3、4步,直到i=j; (3,4步中,没找到符合条件的值,即3中A[j]不小于key,4中A[i]不大于key的时候改变j、i的值,使得j=j-1,i=i+1,直至找到为止。找到符合条件的值,进行交换的时候i, j指针位置不变。另外,i==j这一过程一定正好是i+或j-完成的时候,此时令循环结束)。
时间复杂度: O(nlog2n) 不稳定
8、归并排序
将两个顺序序列合并成一个顺序序列。(两两归并)
时间复杂度: O(nlog2n) 稳定