所有例子都是升序排序。
数据分成两部分:已排序和待排序。
排序过程中,数据移动分为两种:
1. 直接移动:移动数据的存储位置,消耗时间
2. 逻辑移动:改变指向这些数据的指针
选择排序
特点:遍历待排序数据,把最小值与起始数据(最左边)交换位置
次数:第一轮n-1次,第k轮n-k次
步骤:
1. 如果待排序数据大于0,则循环2,3
2. 从待排序的数据取第一个值data[i](前面的i-1个数据已经排好了)
3. 如果data[i]>data[i+n]则交换(即从待排序的数据中找到最小值,放到i那个位置上)
char temp;
char data[5]={ 2, 7, 4, 0, 6 };
int n = sizeof(data);
for(int i=0; i<n; i++) {
for(int j=i+1; j<n; ++) {
if(data[i] > data[j]) {
temp = data[i];
data[i] = data[j];
data[j] = temp;
}
}
}
冒泡排序(交换排序)
特点:从左边开始,对比相邻两个数据,根据大小调整顺序,慢慢把比较大的数移动到右边
次数:第一轮n-1次,第k轮n-k次
步骤:
1. 如果待排序数据大于0,则循环2,3
2. 从待排序的数据取第一个值data[i]和data[i+1]
3. 如果data[i]>data[i+1]则交换,把正在比较的值向后移动一位(右边是已排序部分)
char temp;
char data[5]={ 2, 7, 4, 0, 6 };
int n = sizeof(data);
for(int i=n-1; i>=0; i–) {
for(int j=0; j<=i-1; j++) {
if(data[j] > data[j+1]) {
temp = data[j];
data[j] = data[j+1];
data[j+1] = temp;
}
}
}
桶排序
特点:简单,需要很大的数组
步骤:
1. 定义数组,初始值为0
2. 从待排序的数据取值,数组中对应下标的数据加1
3. 把数组的下标的值取出来
char temp[8]={0};
char data[5]={ 2, 7, 4, 0, 6 };
int n = sizeof(data);
for(int i=0; i<n; i++) {
temp[data[i]] +=1;
}
int index=0;
for(int i=0; i<8; i++) {
while(temp[i] > 0) {
data[index++]=temp[i];
temp[i] -=1;
}
}
插入排序
特点:把未排序数据取出,插入已排序的数据的响应位置
步骤:
1. 从待排序的数据中取出一个
2. 从右往左与已排序的数据比较,如果小于,则继续比较,直到大于时,确定插入位置
3. 已排序的数据中,插入位置右边的数据要整体右移一位
4. 数据插入指定位置
或者
1. 从待排序的数据中取出一个
2. 向左边的数据比较,如果小于,交换,直到大于时
char data[5]={ 2, 7, 4, 0, 6 };
int n = sizeof(data);
for(int i=i; i<n-1; i++) {
for(int j=i-1; j>=0; i–) {
if(data[i] > data[j]) {
temp = data[i];
for(int k=i; k>=j+1; k–) {
data[k]=data[k-1];
}
data[j] = temp;
break;
}
}
}
快速排序
特点:未排序数据中任选一个基准数据,以数据为分割点,小于基准的放左边,大基准的放右边。再对基准两边是数据进行同样的操作,直到只剩下一个数。(其实是使用递归)
步骤:
1. 选取基准点
2. 小于放左边,大于放右边
3. 一直到分组后,每组只有一位
4. 从左向右找ki,使得ki>k
5. 从右向左找kj,使得kj<k
6. 如果i<j,或换
7. 如果i>=j,k和kj互换,并已j为基准点分割成两部分,对左右两边排序,直到左半边的值等于右半边
希尔排序
特点:把目标数据分成几个区域,再对区块内的数据进行插入排序,再减少间隔。适用于大部分已经排好序的数据
步骤:
1. 数据之间的间隔是n/2,第1个和第n/2+1个进行插入排序,第2个和第n/2+2个进行插入排序,以此类推
2. 数据之间的间隔是n/4,第1个、n/4+1, 2n/4, 3n/4个进行插入排序,以此类推
3. 循环直到间隔为1
归并排序
特点:把数据分割为更小的部分进行排序,再把排序好的数据合并
步骤:
1. 将N个长度为1的键值成对合并成N/2个长度为2的键值组
2. 成对合并成N/4个长度为4的键值组
3. 一直到N个长度为1的键值
基数排序法
不进行元素之间的直接比较,按比较方向分为最高位优先msd和最低位优先lsd。msd从最左边的位数开始比较