插入排序:(假设是升序)
思路:假设有一个数组a[10] = {10,3,4,6,5,2,1,9,8,7} ,设置一个tmp,第一次值是a[1],因为tmp值小于a[0],所以把a[0]的值往后移,a[0] = tmp,数组变为a[10] = {3,10,4,6,5,2,1,9,8,7} ; 第二次tmp值是a[2],因为tmp值小于a[1],所以把a[1]的值往后移,tmp不小于a[0],所以a[0]不用往后移,tmp的值就放在a[1],数组变为a[10] = {3,4,10,6,5,2,1,9,8,7},以此类推,每次设一个tmp值,如果tmp小于前一个数,就把前一个数往后移,如果不大于就放在当前位置。
代码:
<span style="font-size:18px;"><span style="font-size:18px;"><pre name="code" class="cpp">void InsertSort(int *a,int size)
{
int i,j;
for(i = 0;i < size-1;++i)
{
int tmp = a[i+1];
for(j = i+1;j > 0;--j)
{
if(tmp < a[j-1])
{
a[j] = a[j-1];
}
else
{
a[j] = tmp;
break;
}
}
}
}</span></span>
它的时间复杂度最好情况是O(n),最坏情况是O(n^2),平均是O(n^2)
希尔排序:
希尔排序是对插入排序的一种优化,假设最小的值或者接近最小的值在数组的最后,就需要移动n次才能把它放在正确的位置。希尔排序设置了一个间距值,每次不是往后移动到下一个位置,而是移动到距离它为间距值的位置。
代码:
<span style="font-size:18px;"><span style="font-size:18px;">void ShellSort(int *a,int size)
{
assert(a);
int gap = size;
while(gap > 1)
{
gap = gap/3 + 1;
for(int i = gap;i < size;++i)
{
int index = i;
int tmp = a[index];
int end = index - gap;
while(end >= 0 && tmp < a[end])
{
a[end + gap] = a[end];
end -= gap;
}
a[end + gap] = tmp;
}
}
}</span></span>
画图说明:
选择排序:
思路是第一趟找到最小(或是最大)的数的下标,然后将它和a[0](或是a[n-1])交换,第二趟找到次小(或是次大)的数,与a[1](或是a[n-2])交换,但这样效率较低,对它优化的思路是每一趟找到最大和最小的数,但交换的时候需要注意。
代码:
<span style="font-size:18px;"><span style="font-size:18px;">void SelectSort(int *a,int size)
{
int min;
int max;
int i,j;
for(i = 0;i < size-1;++i)
{
min = i;
max = i;
for(j = i + 1;j < size - i;++j)
{
if(a[j] < a[min])
min = j;
if(a[j] > a[max])
max = j;
}
if(min != i)
swap(a[i],a[min]);
if(min != j-1)
{
if(max != i && max != j-1)
swap(a[j-1],a[max]);
if(max != j-1 && max == i)
swap(a[j-1],a[min]);
}
}
}</span></span>
堆排序:
建一个大堆(这里一定是大堆,而不是小堆,因为小堆只能满足根节点是树里面最小,左右子数的值无法比较)然后
将堆顶的数和a[n-1]交换,再将堆的大小缩小进行调整,下一次堆顶的数就是次大的,将它和a[n-2]交换,直到全部排完。
代码:
<span style="font-size:18px;">void AdjustDown(int *a,int size,int root)
{
int child = root*2 + 1;
while(child < size)
{
if(child + 1 < size && a[child + 1] > a[child])
{
++child;
}
if(a[child] > a[root])
{
swap(a[child],a[root]);
root = child;
child = root * 2 + 1;
}
else
{
break;
}
}
}
void HeatSort(int *a,int size) //升序
{
for(int i = (size - 2)/2;i >= 0;i--) //建一个大堆
{
AdjustDown(a,size,i);
}
for(int i = 0;i < size-1;i++)
{
swap(a[0],a[size-1-i]);
AdjustDown(a,size-1-i,0);
}
}</span>
它的时间复杂度最好情况是O(n*lgn),最坏情况是O(n*lgn),平均是O(n*lgn)
<span style="font-size:18px;"><span style="font-size:18px;">int GetMidIndex(int left,int mid,int right)
{
if(left < right)
{
if(mid < left)
return left;
else if(mid > right)
return right;
else
return mid;
}
else
{
if(mid < right)
return right;
else if(mid > left)
return left;
else
return mid;
}
}
int PartionSort(int *a,int left,int right)
{
int index = GetMidIndex(left,(right-left)/2,right);
swap(a[index],a[right]);
int begin = left;
int end = right - 1;
int key = a[right];
while(begin < end)
{
while(begin < end && a[begin] <= key)
++begin;
while(begin < end && a[end] >= key)
--end;
if(begin < end)
swap(a[begin],a[end]);
}
if(a[begin] > key)
{
swap(a[begin],a[right]);
return begin;
}
else
{
return right;
}
}
void QuickSort(int *a,int left,int right)
{
assert(a);
if(left - right > 13)
{
int boundary = PartionSort(a,left,right);
QuickSort(a,left,boundary-1);
QuickSort(a,boundary+1,right);
}
else
{
InsertSort(a,right-left+1);
}
}</span>
</span>
归并排序:
思路类似于合并两个单链表,以空间换时间。
<span style="font-size:18px;">void MergeSection(int *a,int *tmp,int begin1,int end1,int begin2,int end2)
{
int index = begin1;
while(begin1 <= end1 && begin2 <= end2)
{
if(a[begin1] < a[begin2])
tmp[index++] = a[begin1++];
else
tmp[index++] = a[begin2++];
}
while(begin1 <= end1)
tmp[index++] = a[begin1++];
while(begin2 <= end2)
tmp[index++] = a[begin2++];
}
void _MergeSort(int *a1,int *tmp,int left,int right)
{
assert(a);
if(left < right)
{
int mid = (right+left)/2;
_MergeSort(a,tmp,left,mid);
_MergeSort(a,tmp,mid+1,right);
MergeSection(a,tmp,left,mid,mid+1,right);
memcpy(a+left,tmp+left,(right-left+1)*4);
}
}
void MergeSort(int *a1,int size)
{
int *tmp = new int[size];
_MergeSort(a,tmp,0,size-1);
delete[] tmp;
}</span>
计数排序:
<span style="font-size:18px;">void CountSort(int *a,size_t size)
{
int max = a[0];
int min = a[0];
for(int i = 1;i < size;++i)
{
if(a[i] > max)
max = a[i];
else if(a[i] < min)
min = a[i];
}
int range = max-min+1;
int *CountArray = new int[range];
memset(CountArray,0,sizeof(int)*size);
for(int i = 0;i < size;++i)
{
CountArray[a[i] - min]++;
}
int index = 0;
for(int i = 0;i < range;++i)
{
while(CountArray[i]-- > 0)
{
a[index++] = i+min;
}
}
}
</span>
基数排序:
<span style="font-size:18px;">int GetMaxBit(int *a,size_t size)
{
int digit = 1;
int max = 1;
for(int i = 0;i < size;++i)
{
while(a[i] >= max)
{
++digit;
max *= 10;
}
}
return digit;
}
void DigitSortLSD(int *a,size_t size)
{
assert(a);
int MaxBit = GetMaxBit(a,size);
int *bucket = new int[size];
int count[10];
int start[10];
int digit = 1;
int bit = 1;
while(bit <= MaxBit)
{
memset(count,0,sizeof(int)*10);
memset(start,0,sizeof(int)*10);
for(int i = 0;i < size;++i)
{
int num = a[i]/digit %10;
count[num]++;
}
start[0] = 0;
for(int i = 1;i < size;++i)
{
start[i] = start[i-1] + count[i-1];
}
for(int i = 0;i < size;++i)
{
int num = a[i]/digit %10;
bucket[start[num]++] = a[i];
}
memcpy(a,bucket,sizeof(int)*10);
digit *= 10;
++bit;
}
}</span>