数据结构基础 排序
插入排序
1.直接插入排序
思想:
- 将待排序列的第一个元素看成有序区,其余的是无序区;
- 从无序区的第一个元素开始,将其加入有序区的
合适位置
; - 直到无序区无元素。
算法:
// 直接插入排序
void InsertSort(int r[], int n)
{
int i,j,tmp;
// n-1 次循环
for(i = 1; i < n; i++)
{
// 记录当前值
tmp = r[i];
// 找到当前值插入在其前面有序区的合适位置
for(j = i - 1; tmp < r[j]; j--)
r[j + 1] = r[j];
// 把当前值 插入到 合适位置
r[j + 1] = tmp;
}
}
算法注解:
1.因为序列有 n 个元素,而且第一个元素(位置0)已经归入有序区,所以外循环从第二个元素开始(即位置1),共 n-1 个元素。
2.把当前元素插入到前面 合适位置
很重要!这就意味着可能会需要不断地向后移动值(r[j + 1] = r[j]; 把前一个值赋给其后面的位置),直到找到它的合适位置,所以需要 记录当前值,这样当找到合适位置时,直接置为当前值。
2.希尔排序
思想:
- 把待排序列分成若干子序列;
- 对每个子序列进行直接插入排序;
- 待序列基本有序时,对整体进行一次直接插入排序。
算法:
// 希尔排序
void ShellSort(int r[], int n)
{
int i,j,d,tmp;
// 由 n 决定的多次循环
for(d = n / 2; d > 0; d /= 2)
{
// 子序列内循环
for(i = d; i < n; i++)
{
// 进行直接插入排序
if(r[i] < r[i + d])
{
tmp = r[i];
j = i - d;
while (j >= 0 && tmp < r[j])
{
r[j + d] = r[j];
j -= d;
}
r[j + d] = tmp;
}
}
}
}
交换排序
1.冒泡排序
思想:
- 从待排序列第一个元素一开始,与其下一个元素进行比较;
- 大于则交换值,小于则从下一个元素开始与其下一个元素比较;
- 直到最后一个元素。
算法:
// 冒泡排序
void BubbleSort(int r[], int n)
{
int i,j,tmp;
// n-1 次循环
for(i = 0; i < n; i++)
{
// 从当前值的下一个值开始对比,直到序列最后一个值
for(j = i + 1; j < n; j++)
{
// 如果当前值大于其对比值,进行值交换
if(r[i] > r[j])
{
tmp = r[i];
r[i] = r[j];
r[j] = tmp;
}
}
}
}
2.快速排序
思想:
- 标记待排序列的头元素和尾元素;
- 先从右边开始,把标记的尾元素与标记的头元素比较,小于则标记向前移动一位;直到标记头元素大于标记尾元素,便交换二者的值,并从左侧标记头元素开始;
- 从左侧开始,把标记的头元素与标记的尾元素比较,小于则标记向后移动一位;直到标记头元素大于标记尾元素,便交换二者的值,并从右侧标记头元素开始;
- 第一次排序后以待排序列的中间位置为基准,形成左右两个子区间;
- 再分别对两个子区间执行快速排序(递归)。
算法:
// 快速排序
// 递归-执行函数
int Implement(int r[], int begin, int end)
{
int i,j,tmp;
i = begin;
j = end;
while (i < j)
{
// 先从右边开始
while (r[i] < r[j])
j--;
// 当左边值大于右边值,交换二者的值,并从左侧开始
if(r[i] > r[j])
{
tmp = r[i];
r[i] = r[j];
r[j] = tmp;
i++;
}
// 从左侧开始
while (r[i] < r[j])
i++;
// 当左边值大于右边值,交换二者的值,并从右侧开始
if(r[i] > r[j])
{
tmp = r[i];
r[i] = r[j];
r[j] = tmp;
j--;
}
}
return i;
}
void QuickSort(int r[], int begin, int end)
{
int pos;
if(begin < end)
{
// 第一次快速排序,以中间值为基准,形成左边区 和 右边区
pos = Implement(r, begin, end);
// 在右边区进行快排
QuickSort(r, pos + 1, end);
// 在左边区进行快排
QuickSort(r, begin, pos - 1);
}
}
选择排序
简单选择排序
思想:
- 假设有序区为空,无序区为待排序列;
- 每次从待排序列中选择一个最小值加入有序区;
- 直到无序区为空。
算法:
void SelectSort(int r[], int n)
{
int i,j,tmp,index;
// n-2 次循环
for(i = 0; i < n - 1; i++)
{
// 记住当前值的位置
index = i;
// 在当前值后的序列中,找到最小值的位置
for(j = i + 1; j < n; j++)
{
if(r[j] < r[index])
index = j;
}
// 对比当前值和选出来的最小值,如果两者不是同一个值(相等的话说明当前值就是最小值),就交换二者的值
if(index != i)
{
tmp = r[index];
r[index] = r[i];
r[i] = tmp;
}
}
}