目录
前言
本文部分代码参考2022年王道数据结构实现,所有代码均可运行。
插入排序
1.直接插入排序
void display(int a[],int n)
{
for(int i = 0; i < n; ++i)
cout<<a[i]<<" ";
cout<<endl;
}
void dinsert(int a[],int n)
{
int temp = 0,i,j;
for(i = 0; i < n-1;++i)
{
// 如果不是有序的话,那么找到合适的位置
if(a[i] > a[i+1])
{
temp = a[i+1];
for(j = i; temp < a[j] && j >= 0; --j)
{
a[j+1] = a[j];
}
a[j+1] = temp; //先--再跳出去的,所以需要j+1
}
}
display(a,n);
}
2.折半插入排序
void display(int a[],int n)
{
for(int i = 0; i < n; ++i)
cout<<a[i]<<" ";
cout<<endl;
}
void binarysort(int a[], int n)
{
int temp,i,j,low,high,mid;
for(i = 1;i < n;++i)
{
low = 0,high = i-1; // 在0至i-1的范围内视为有序区,i代表新的待插数
temp = a[i];
// 在有序区内进行二分查找
while(low <= high)
{
mid = (low + high)/2;
if(a[mid] > temp)
high = mid -1;
else
low = mid + 1;
}
// 移动位置,high+1就是mid的位置,也就是我们需要插入的位置
for(j = i-1;j >= high +1; --j)
{
a[j+1] = a[j];
}
a[high+1] = temp;
}
display(a,n);
}
3.希尔排序
void display(int a[],int n)
{
for(int i = 0; i < n; ++i)
cout<<a[i]<<" ";
cout<<endl;
}
void shellsort(int a[],int n)
{
int d ,i,j,k,temp;//首先是分成一半进行排序
for(d = n/2; d >= 1; d/=2)
{
for(i = d; i < n; ++i) //多组同时进行遍历
{
if(a[i] < a[i-d])
{
temp = a[i];
for(j = i-d; j >= 0 && temp < a[j]; j -= d)
{
a[j+d] = a[j];
}
a[j+d] = temp;
}
}
}
display(a,n);
}
交换排序
1.冒泡排序
void display(int a[],int n)
{
for(int i = 0; i < n; ++i)
cout<<a[i]<<" ";
cout<<endl;
}
void swap(int &a,int &b)
{
int temp;
temp = a;
a = b;
b = temp;
}
void bubblesort(int a[],int n)
{
int i,j;
for(i = 0; i < n; ++i)
{
for(j = i+1; j < n; ++j)
{
if(a[i] > a[j])
swap(a[i],a[j]);
}
}
display(a,n);
}
2.快速排序
void quicksort(int a[],int low,int high)
{
if(low >= high) // 超出处理范围了
return;
int pivot = a[low],left = low,right = high;
while(low < high) // 反复寻找,直至将这次范围内的数都排到轴的左右
{
while (a[high] > pivot && low < high) // 找到比pivot大的数
--high;
a[low] = a[high]; // pivot的数据就是low的数据所以可以直接存
while (a[low] <= pivot && low < high) //找到小于或等于pivot的数
++low;
a[high] = a[low]; // low经过上面的while语句指向了不符合要求的数,所以用high来存它
//通过上面两个赋值语句,不符合要求的数就被交换了
}
a[low] = pivot;
//从上述语句跳转出来,low处的值必定被保存了,而且low此时的位置是数组以pivot为中心的中间部分
// 所以使用low处来存pivot
quicksort(a,left,low-1);
quicksort(a,low+1,right);
}
选择排序
1.简单选择排序
void display(int a[],int n)
{
for(int i = 0; i < n; ++i)
cout<<a[i]<<" ";
cout<<endl;
}
void selectsort(int a[],int n)
{
int i,j,k;
for(i = 0; i < n; ++i)
{
k = i;
for(j = i+1; j < n; ++j)
{
if(a[k] > a[j])
k = j;
}
swap(a[i],a[k]);
}
display(a,n);
}
2.堆排序
void display(int a[],int n)
{
for(int i = 0; i < n; ++i)
cout<<a[i]<<" ";
cout<<endl;
}
void swap(int &a,int &b)
{
int temp;
temp = a;
a = b;
b = temp;
}
void construct_heap(int a[],int start, int end)
{
// 完全二叉树的知识,父节点与子节点
int father = start;
int son = 2*start+1;
// 当达到遍历的界限时
while (son <= end)
{
if(son+1 <= end && a[son] < a[son+1]) //选择最大的子节点
son++;
if(a[father] > a[son]) //如果已经是一颗大根堆了,就不需要继续遍历了
return ;
else
{
swap(a[father],a[son]); //进行交换,成为大根堆
//继续往下遍历,完善大根堆
father = son;
son = son*2 + 1;
}
}
}
void heapsort(int a[],int n)
{
int i;
for(i = n/2 - 1; i >= 0; --i) //从比较小的树一步步往上建立
construct_heap(a,i,n-1);
for(i = n-1; i > 0; --i) // 0处存储的值都是每次选出来的最大值
{
swap(a[0],a[i]);
construct_heap(a,0,i-1); //重新进行大根堆的建立,这次由于0节点改变,所以直接从整棵树开始建立
//减小遍历的范围
}
display(a,n);
}
二路归并排序
void merge(int a[],int low, int mid, int high)
{
int i = 0,j,k = low;
//存储起来
for(i = low; i <= high; ++i)
b[i] = a[i];
for(i = low,j = mid + 1;i <= mid && j <= high ;k++)
{
if(b[i] > b[j])
{
a[k] = b[j];
++j;
}
else
{
a[k] = b[i];
++i;
}
}
while(i <= mid)
{
a[k] = b[i];
++i;++k;
}
while(j <= high)
{
a[k] = b[j];
++j;++k;
}
}
void mergesort(int a[],int low, int high)
{
if(low < high)
{
int mid = (low+high)/2;
mergesort(a,low,mid);//对左半部分排序
mergesort(a,mid+1,high);//对右半部分排序
merge(a,low,mid,high);//将排序后的结果合并
}
}