#include <stdio.h>
//冒泡排序的原始算法
void maopao1(int data[],int n)
{
int i,j;
for(i = 0 ; i < n-1 ; i++)
{
for(j = 0 ; j < n-1;j++)
{
if(data[j] > data[j+1])
{
int t = data[j];
data[j] = data[j+1];
data[j+1] = t;
}
}
}
}
//冒泡排序的精简算法
void maopao2(int data[],int n )
{
int i , j ;
for(i = 0 ; i < n-1;i++)
{
for(j = 0 ; j < n - i - 1 ; j++)
{
if(data[j] > data[j+1])
{
int t = data[j];
data[j] = data[j+1];
data[j+1] = t;
}
}
}
}
//交换排序简化 (原始的交换排序多了多余的操作,没必要,不如这个好)
void swap(int data[],int n )
{
int i , j ;
for(i = 0; i < n ; i++)
{
for(j = i+1 ; j < n ; j++)
{
if(data[i] > data[j])
{
int t = data[i];
data[i] = data[j];
data[j] = t;
}
}
}
}
//插入排序的原始算法
void insert1(int data[],int n )
{
int i,k,j;//多了一个变量 用来移位
for(i = 1 ; i < n ; i++)
{
int temp = data[i]; //存储要插入的变量;
for(j = 0 ; j < i ; j++)
{
if(data[j] > data[i]) break;//找到插入位置
}
//先移位 再插入 -> 就要把插入点的位置的数据储存起来
for(k = i;k > j;k--)
{
data[k] = data[k-1];
}
data[j] = temp;
}
}
//精简插入排序
void insert2(int data[],int n)
{
for(int i = 1 ; i < n ; i++)
{
for(int j = 0 ; j < i ; j++)
{
if(data[i] < data[j])
{
int t = data[i];
data[i] = data[j];
data[j] = t;
}
}
}
}
//希尔排序
void insert3(int data[],int n)
{
for(int dk=n/2+1;dk>0;dk--)
{
for(int i=0;i+dk<n;i++)
{
if(data[i+dk]<data[i])
{
int t = data[i+dk];
data[i+dk] = data[i];
data[i] = t;
}
}
}
}
//快速排序
void insert4(int data[],int left,int right)
{
if(left > right)
return ;
int swap = data[left];
int i = left;
int j = right;
while(i != j)
{
while(i < j && data[j] >swap)
j--;
while(i < j && data[i] <= swap)
i++;
if(i < j )
{
int t = data[i];
data[ i] = data[j];
data[j] = t;
}
}
data[left] = data[i];
data[i] = swap;
insert4(data,left,i-1);
insert4(data,i+1,right);
}
//归并排序(递归写法)
void sort(int data[],int left,int mid,int right)
{
//每一次的mid初始值就是相对应小数组的left值,right都是相对应小数组的right的值 因为right索引在数组中也是指向一个数值的 所以用小于等于
for(int i = mid+1 ; i <= right ; i++)
{
for(int j = i ; j > 0 ; j--)
{
if (data[j] < data[j-1])
{
int t = data[j];
data[j] = data[j-1];
data[j-1] = t;
}
}
}
}
void insert5(int data[],int left,int right)
{
int mid = (left + right ) / 2;
if( mid > left)
insert5(data,left,mid);
if(mid + 1 < right)
insert5(data,mid+1,right);
sort(data,left,mid,right);
//具体的应该是先是左右部分分开 然后不断分组 待左右部分都分组完毕后 再从分组的最后结果不断向上排序
//这里有点抽象 我举个例子
//先分组 后排序
// 88 65 77 33 55
// {88 65 77} {33 55} 里面有1次分组
// {88 65} {77} {33} {55} 里面有2次分组
// {88}{65}{77} {33}{55} 里面有2次分组
// 共1+2+2 = 4 次分组
// 第一次排序 {65 88} {77} {33 55} 里面有2个排序 最后一次分组结束的结果先排序 然后依次顺序排序
// 第二次排序 {65 77 88} {33 55} 里面有1个排序
// 第三次排序 {33 55 65 77 88} 里面有1个排序
// 共 2+1+1 = 4 次排序
// 分组次数等于排序次数 只不过分组先来,排序后来
}
//如果不好理解 我自创了一个方法
//这个分组必须要理解是什么东西
//排序可以这样理解 就把right看成n-1 left看成0 mid看成left也是0
//这样的话就类似直接插入排序的精简算法了 只不过那个是data[i]依次与data[j]比较
//而这里是用冒泡的方法扮演精简算法 其实原理都一样
//折半插入排序 不断折半数组找到插入点然后移位最后插入
int search(int data[],int key,int n)
{
int left = 0,right = n-1;
while(right >= left)
{
int mid = (left + right) / 2;
if(data[mid] == key)
return mid;
else if(data[mid] > key)
right = mid - 1;
else
left = mid + 1;
}
right++;
return right;
}
void insert6(int data[],int n)
{
for(int i = 1 ; i < n ; i++)
{
int swap = data[i];
int index = search(data,swap,i);
for(int t = i ; t > index ; t--)
{
data[t] = data[t-1];
}
data[index] = swap;
}
}
堆排
void headvisit(int data[],int n)
{
int i , j , t;
while(n>1) //共有n个元素,每一个都要与父节点的值相比较
{
for(i=n/2;i>=1;i--)// n/2是找到最后一个叶子的父节点在树中的位置,当i=1时,就说明此时在根节点处,在树中根节点是从1开始的 并不是0
{
if(data[i-1]>data[2*i-1]) //根据树的基本结构 此处是与左孩子比较
{
t = data[2*i-1];
data[2*i-1] = data[i-1];
data[i-1] = t;
}
//先判断右孩子是否存在 右孩子的度一定是小于等于总节点数的(n)
if( 2*i+1 <= n && data[i-1] > data[2*i-1+1])
{
t = data[2*i-1+1];
data[2*i-1+1] = data[i-1];
data[i-1] = t;
}
}
data++;
n--;
}
}
void outs(int data[],int n)
{
for(int i = 0 ; i < n ; i++)
{
printf("%10d",data[i]);
}
}
int main()
{
int data[5] = {9,25,444,17536,9456};
headvisit(data,5);
outs(data,5);
return 0;
}
void out(int data[],int n )
{
for(int i = 0 ; i < n ; i++)
{
printf("%6d",data[i]);
}
}
int main()
{
int n = 5;
int data[n]={652,2145,12,2,847};
insert6(data,n);
out(data,n);
return 0;
}