@yanglt7
2018-10-21T15:48:11.000000Z
字数 10833
阅读 657
数据结构和算法
概念
在排序问题中,通常将数据元素称为记录。
排序的依据是关键字之间的大小关系,那么对同一记录集合,针对不同的关键字进行排序,可以得到不同的序列。
分类
插入排序类
选择排序类
交换排序类
归并排序类
冒泡排序的要点
代码实现
#include <stdio.h>
void BubbleSort(int k[], int n)
{
int i, j, temp, count1=0, count2=0;
for( i=0; i < n-1; i++ )
{
for( j=i+1; j < n; j++ )
{
count1++;
if( k[i] > k[j] )
{
count2++;
temp = k[j];
k[j] = k[i];
k[i] = temp;
}
}
}
printf("总共进行了%d次比较,进行了%d次移动!\n", count1, count2);
}
int main()
{
int i;
int a[10] = {5, 2, 6, 0, 3, 9, 1, 7, 4, 8};
BubbleSort(a, 10);
printf("排序后的结果是: \n");
for( i=0; i < 10; i++ )
{
printf("%d", a[i]);
}
printf("\n");
return 0;
}
#include <stdio.h>
void BubbleSort(int k[], int n)
{
int i, j, temp, count1=0, count2=0;
int flag = 1;
for( i=0; i < n-1 && flag; i++ )
{
for( j=n-1; j > i; j-- )
{
count1++;
flag = 0;
if( k[j-1] > k[j] )
{
count2++;
temp = k[j-1];
k[j-1] = k[j];
k[j] = temp;
flag = 1;
}
}
}
printf("总共进行了%d次比较,进行了%d次移动!\n", count1, count2);
}
int main()
{
int i;
int a[10] = {5, 2, 6, 0, 3, 9, 1, 7, 4, 8};
BubbleSort(a, 10);
printf("排序后的结果是: \n");
for( i=0; i < 10; i++ )
{
printf("%d", a[i]);
}
printf("\n");
return 0;
}
选择排序算法就是通过n-i次关键字间的比较,从n-i+1个记录中最小的记录,并和第i(1<=i<=n)个记录交换。
代码实现
#include <stdio.h>
void SelectSort(int k[], int n)
{
int i, j, min, temp, count1=0, count2=0;
for( i=0; i < n-1; i++ )
{
min = i;
for( j=i+1; j < n; j++ )
{
count1++;
if( k[j] < k[min] )
{
min = j;
}
}
if( min != i )
{
count2++;
temp = k[min];
k[min] = k[i];
k[i] = temp;
}
}
printf("总共进行了%d次比较,进行了%d次移动!\n", count1, count2);
}
int main()
{
int i;
int a[10] = {5, 2, 6, 0, 3, 9, 1, 7, 4, 8};
SelectSort(a, 10);
printf("排序后的结果是: \n");
for( i=0; i < 10; i++ )
{
printf("%d", a[i]);
}
printf("\n");
return 0;
}
直接插入排序算法(Straight Insertion Sort)的基本操作是将一个记录插入到已经排好序的有序表中,从而得到一个新的、记录数增加1的有序表。
代码实现
#include <stdio.h>
void InsertSort(int k[], int n)
{
int i, j, temp;
for( i=1; i < n; i++ )
{
if( k[i] < k[i-1] )
{
temp = k[i];
for( j=i-1; k[j] > temp; j-- )
{
k[j+1] = k[j];
}
k[j+1] = temp;
}
}
}
int main()
{
int i;
int a[10] = {5, 2, 6, 0, 3, 9, 1, 7, 4, 8};
InsertSort(a, 10);
printf("排序后的结果是: \n");
for( i=0; i < 10; i++ )
{
printf("%d", a[i]);
}
printf("\n");
return 0;
}
初始关键字 | 49 | 38 | 65 | 97 | 76 | 13 | 27 | 49 | 55 | 04 |
---|---|---|---|---|---|---|---|---|---|---|
一趟排序结果 | 13 | 27 | 49 | 55 | 04 | 49 | 38 | 65 | 97 | 76 |
二趟排序结果 | 13 | 04 | 49 | 38 | 27 | 49 | 55 | 65 | 97 | 76 |
三趟排序结果 | 04 | 13 | 27 | 38 | 49 | 49 | 55 | 65 | 76 | 97 |
#include <stdio.h>
void ShellSort(int k[], int n)
{
int i, j, temp;
int gap = n;
do
{
gap /= 3;
for( i=gap; i < n; i++ )
{
if( k[i] < k[i-gap] )
{
temp = k[i];
for( j=i-gap; k[j] > temp; j-=gap )
{
k[j+gap] = k[j];
}
k[j+gap] = temp;
}
}
} while(gap > 0);
}
int main()
{
int i;
int a[10] = {5, 2, 6, 0, 3, 9, 1, 7, 4, 8};
ShellSort(a, 10);
printf("排序后的结果是: \n");
for( i=0; i < 10; i++ )
{
printf("%d", a[i]);
}
printf("\n");
return 0;
}
堆,是具有以下性质的完全二叉树
要点
根结点一定是堆中所有结点最大或者最小者,如果按照层序遍历的方式给结点从1开始编号,则结点之间满足如下关系:
下标i与2i和2i+1是双亲和子女关系
堆排序(Heap Sort)就是利用堆进行排序的算法,它的基本思想是:
代码实现
#include <stdio.h>
int count = 0;
void swap(int k[], int i, int j)
{
int temp;
temp = k[i];
k[i] = k[j];
k[j] = temp;
}
void HeapAdjust(int k[], int s, int n)
{
int i, temp;
temp = k[s];
// i=2*s:左孩子; 2*s+1: 右孩子
for( i=2*s; i <= n; i*=2 )
{
count++;
if( i < n && k[i] < k[i+1] ) // 左孩子小于右孩子
{
i++; // 使得i指向最大的孩子的下标
}
if( temp >= k[i] ) // temp临时存放当前需要调整的双亲。如果大于孩子,则退出循环
{
break;
}
k[s] = k[i];
s = i;
}
k[s] = temp;
}
void HeapSort(int k[], int n)
{
int i;
// 从下至上,从右至左,层序遍历
for( i=n/2; i > 0; i-- )
{
HeapAdjust(k, i, n); // 构建大顶堆的函数。 k:数组 i:当前双亲结点; n:长度
}
for( i=n; i > 1; i-- )
{
swap(k, 1, i); // 调整,将第一个元素和最后一个元素进行互换,i是变化的
HeapAdjust(k, 1, i-1); // 重新调整
}
}
int main()
{
int i;
int a[10] = {-1, 5, 2, 6, 0, 3, 9, 1, 7, 4};
HeapSort(a, 9);
printf("总共执行 %d 次比较! \n", count);
printf("排序后的结果是: ");
for( i=1; i < 10; i++ )
{
printf("%d ", a[i]);
}
printf("\n");
return 0;
}
归并排序(Merge Sort)就是利用归并的思想实现的排序方法。它的原理是假设初始有n个记录,则可以看成是n个有序的子序列,每个子序列的长度为1,然后两两归并,得到[n/2]个长度为2或1的有序子序列;然后再两两归并,……,如此重复,直至得到一个长度为n的有序序列为止,这种排序方法称为2路归并排序。
归并排序的递归实现
// 递归实现
#include <stdio.h>
#define MAXSIZE 10
//实现归并,并把最后的结果存放到list1数组
void merging(int *list1, int list1_size, int *list2, int list2_size)
{
int i, j, k, m;
int temp[MAXSIZE];
i = j = k = 0
while( i < list1_size && j < list2_size )
{
if( list1[i] < list2[j] )
{
temp[k++] = list1[i++];
}
else
{
temp[k++] = list2[j++];
}
}
while( i < list1_size )
{
temp[k++] = list1[i++];
}
while( j < list2_size )
{
temp[k++] = list2[j++];
}
for( m=0; m < (list1_size + list2_size); m++ )
{
list1[m] = temp[m];
}
}
void MergeSort(int k[], int n)
{
if( n > 1 )
{
int *list1 = k;
int list1_size = n/2;
int *list2 = k + n/2; // 左半部分的地址加上左半部分的尺寸
int list2_size = n - list1_size;
MergeSort(list1, list1_size);
MergeSort(list2, list2_size);
merging(list1, list1_size, list2, list2_size);
}
}
int main()
{
int i;
int a[10] = {5, 2, 6, 0, 3, 9, 1, 7, 4, 8};
MergeSort(a, 10);
printf("排序后的结果是: \n");
for( i=0; i < 10; i++ )
{
printf("%d", a[i]);
}
printf("\n");
return 0;
}
// 迭代实现
#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 10
void MergeSort(int k[], int n)
{
int i, next, left_min, left_max, right_min, right_max;
// 申请空间存放数组
int *temp = (int *)malloc(n * sizeof(int));
// 逐级递增比较
for( i=1; i < n; i*=2 ) // 步长i
{
for( left_min=0; left_min < n-i; left_min = right_max )
{
right_min = left_max = left_min + i;
right_max = left_max + i;
// 右边的下标最大值只能为n,防止越界
if( right_max > n )
{
right_max = n;
}
// temp数组的下标,由于每次数据都有返回到k,因此每次都需重新置零
next = 0;
// 如果左边的数据还没有到分割线且右边的数据也没有到分割线,则循环
while( left_min < left_max && right_min < right_max )
{
if( k[left_min] < k[right_min] )
{
temp[next++] = k[left_min++]; // 存放较小者
}
else
{
temp[next++] = k[right_min++];
}
}
// 如果左边的游标没有到达分割线,则需要把数组接回去
// 如果右边的游标没有到达分割线,则说明右边的数据比较大,不需要移动位置
while( left_min < left_max )
{
k[--right_min] = k[--left_max];
}
while( next > 0 )
{
// 将排好序的数组返回给k
k[--right_min] = temp[--next];
}
}
}
}
int main()
{
int i;
int a[10] = {5, 2, 6, 0, 3, 9, 1, 7, 4, 8};
MergeSort(a, 10);
printf("排序后的结果是: \n");
for( i=0; i < 10; i++ )
{
printf("%d", a[i]);
}
printf("\n");
return 0;
}
#include <stdio.h>
void swap(int k[], int low, int high)
{
int temp;
temp = k[low];
k[low] = k[high];
k[high] = temp;
}
int Partition(int k[], int low, int high)
{
int point;
point = k[low];
while( low < high )
{
while( low < high && k[high] >= point )
{
high--;
}
swap(k, low, high);
while( low < high && k[low] <= point )
{
low++;
}
swap(k, low, high);
}
return low;
}
void QSort(int k[], int low, int high)
{
int point;
if( low < high )
{
point = Partition(k, low, high); // 计算基准点,将小于基准点的数放在左边,大的放在右边
QSort(k, low, point-1);
QSort(k, point+1, high);
}
}
void QuickSort(int k[], int n)
{
QSort(k, 0, n-1);
}
int main()
{
int i;
int a[10] = {5, 2, 6, 0, 3, 9, 1, 7, 4, 8};
QuickSort(a, 10);
printf("排序后的结果是: \n");
for( i=0; i < 10; i++ )
{
printf("%d", a[i]);
}
printf("\n");
return 0;
}
#include <stdio.h>
void swap(int k[], int low, int high)
{
int temp;
temp = k[low];
k[low] = k[high];
k[high] = temp;
}
int Partition(int k[], int low, int high)
{
int point;
int m = low + (high-low)/2;
if( k[low] > k[high] )
{
swap(k, low, high);
}
if( k[m] > k[high] )
{
swap(k, m, high);
}
if( k[m] > k[low] )
{
swap(k, m, low);
}
// 将low变成中间值
point = k[low];
while( low < high )
{
while( low < high && k[high] >= point )
{
high--;
}
swap(k, low, high);
while( low < high && k[low] <= point )
{
low++;
}
swap(k, low, high);
}
}
void QSort(int k[], int low, int high)
{
int point;
if( low < high )
{
point = Partition(k, low, high); // 计算基准点,将小于基准点的数放在左边,大的放在右边
QSort(k, low, point-1);
QSort(k, point+1, high);
}
}
void QuickSort(int k[], int n)
{
QSort(k, 0, n-1);
}
int main()
{
int i;
int a[10] = {5, 2, 6, 0, 3, 9, 1, 7, 4, 8};
QuickSort(a, 10);
printf("排序后的结果是: \n");
for( i=0; i < 10; i++ )
{
printf("%d", a[i]);
}
printf("\n");
return 0;
}
#include <stdio.h>
void swap(int k[], int low, int high)
{
int temp;
temp = k[low];
k[low] = k[high];
k[high] = temp;
}
int Partition(int k[], int low, int high)
{
int point;
int m = low + (high-low)/2;
if( k[low] > k[high] )
{
swap(k, low, high);
}
if( k[m] > k[high] )
{
swap(k, m, high);
}
if( k[m] > k[low] )
{
swap(k, m, low);
}
// 将low变成中间值
point = k[low];
while( low < high )
{
while( low < high && k[high] >= point )
{
high--;
}
k[low] = k[high];
while( low < high && k[low] <= point )
{
low++;
}
k[high] = k[low];
}
k[low] = point;
}
void QSort(int k[], int low, int high)
{
int point;
if( low < high )
{
point = Partition(k, low, high); // 计算基准点,将小于基准点的数放在左边,大的放在右边
QSort(k, low, point-1);
QSort(k, point+1, high);
}
}
void QuickSort(int k[], int n)
{
QSort(k, 0, n-1);
}
int main()
{
int i;
int a[10] = {5, 2, 6, 0, 3, 9, 1, 7, 4, 8};
QuickSort(a, 10);
printf("排序后的结果是: \n");
for( i=0; i < 10; i++ )
{
printf("%d", a[i]);
}
printf("\n");
return 0;
}
#include <stdio.h>
#define MAX_LENGTH_INSERT_SORT 7
void ISort(int k[], int n)
{
int i, j, temp;
for( i=1; i < n; i++ )
{
if( k[i] < k[i-1] )
{
temp = k[i];
for( j=i-1; k[j] > temp; j-- )
{
k[j+1] = k[j];
}
k[j+1] = temp;
}
}
}
void InsertSort(int k[], int low, int high)
{
ISort(k+low, high-low+1);
}
void swap(int k[], int low, int high)
{
int temp;
temp = k[low];
k[low] = k[high];
k[high] = temp;
}
int Partition(int k[], int low, int high)
{
int point;
int m = low + (high-low)/2;
if( k[low] > k[high] )
{
swap(k, low, high);
}
if( k[m] > k[high] )
{
swap(k, m, high);
}
if( k[m] > k[low] )
{
swap(k, m, low);
}
// 将low变成中间值
point = k[low];
while( low < high )
{
while( low < high && k[high] >= point )
{
high--;
}
k[low] = k[high];
while( low < high && k[low] <= point )
{
low++;
}
k[high] = k[low];
}
k[low] = point;
}
void QSort(int k[], int low, int high)
{
int point;
if( high - low > MAX_LENGTH_INSERT_SORT )
{
point = Partition(k, low, high); // 计算基准点,将小于基准点的数放在左边,大的放在右边
QSort(k, low, point-1);
QSort(k, point+1, high);
}
else
{
InsertSort(k, low, high);
}
}
void QuickSort(int k[], int n)
{
QSort(k, 0, n-1);
}
int main()
{
int i;
int a[10] = {5, 2, 6, 0, 3, 9, 1, 7, 4, 8};
QuickSort(a, 10);
printf("排序后的结果是: \n");
for( i=0; i < 10; i++ )
{
printf("%d", a[i]);
}
printf("\n");
return 0;
}
#include <stdio.h>
#define MAX_LENGTH_INSERT_SORT 7
void ISort(int k[], int n)
{
int i, j, temp;
for( i=1; i < n; i++ )
{
if( k[i] < k[i-1] )
{
temp = k[i];
for( j=i-1; k[j] > temp; j-- )
{
k[j+1] = k[j];
}
k[j+1] = temp;
}
}
}
void InsertSort(int k[], int low, int high)
{
ISort(k+low, high-low+1);
}
void swap(int k[], int low, int high)
{
int temp;
temp = k[low];
k[low] = k[high];
k[high] = temp;
}
int Partition(int k[], int low, int high)
{
int point;
int m = low + (high-low)/2;
if( k[low] > k[high] )
{
swap(k, low, high);
}
if( k[m] > k[high] )
{
swap(k, m, high);
}
if( k[m] > k[low] )
{
swap(k, m, low);
}
// 将low变成中间值
point = k[low];
while( low < high )
{
while( low < high && k[high] >= point )
{
high--;
}
k[low] = k[high];
while( low < high && k[low] <= point )
{
low++;
}
k[high] = k[low];
}
k[low] = point;
}
void QSort(int k[], int low, int high)
{
int point;
if( high - low > MAX_LENGTH_INSERT_SORT )
{
while( low < high )
{
point = Partition(k, low, high); // 计算基准点,将小于基准点的数放在左边,大的放在右边
if( point-low < high-point )
{
QSort(k, low, point-1);
low = point + 1;
}
else
{
QSort(k, point+1, high);
high = point-1;
}
}
}
else
{
InsertSort(k, low, high);
}
}
void QuickSort(int k[], int n)
{
QSort(k, 0, n-1);
}
int main()
{
int i;
int a[10] = {5, 2, 6, 0, 3, 9, 1, 7, 4, 8};
QuickSort(a, 10);
printf("排序后的结果是: \n");
for( i=0; i < 10; i++ )
{
printf("%d", a[i]);
}
printf("\n");
return 0;
}
排序方法 | 平均情况 | 最好情况 | 最坏情况 | 辅助空间 | 稳定性 |
---|---|---|---|---|---|
冒泡排序 | O(n^2) | O(n) | O(n^2) | O(1) | 稳定 |
选择排序 | O(n^2) | O(n^2) | O(n^2) | O(1) | 稳定 |
直接插入排序 | O(n^2) | O(n) | O(n^2) | O(1) | 稳定 |
希尔排序 | O(nlogn)~O(n^2) | O(n^1.3) | O(n^2) | O(1) | 不稳定 |
堆排序 | O(nlogn) | O(nlogn) | O(nlogn) | O(1) | 不稳定 |
归并排序 | O(nlogn) | O(nlogn) | O(nlogn) | O(n) | 稳定 |
快速排序 | O(nlogn) | O(nlogn) | O(n^2) | O(nlogn)~O(n) | 不稳定 |