@(笔试面试)
数据结构复习 — 排序算法
排序算法是在笔试面试中常考,以前在写复习材料的时候,也整理过,但是具体的算法并没有完全测试过,前些天在查找桶排序的算法时,发现别人已经整理的很好了,我拿过来练练手,并记录下来。
插入排序
直接插入排序
代码如下:1
2
3
4
5
6
7
8
9
10
11
12
13void insertsort(int nums[],int n)
{
// original insert sort
int i,j;
int key;
for(i = 1;i<n;++i)
{
key = nums[i];
for(j=i-1;j>=0 && key < nums[j];--j)
nums[j+1] = nums[j];
nums[j+1] = key;
}
}
稍作改进,在每次插入的时候,首先检查与已排序元素的最后一个元素比较,若比最后一个元素大,则不用插入排序;否则进行插入排序,性能没有改进多少,就是程序结构清晰了。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16void insertsort2(int nums[],int n)
{
// advance insert sort
int i,j;
int key;
for(i =1;i<n;++i)
{
key = nums[i];
if(key < nums[i-1])
{
for(j=i-1;j>=0 && key < nums[j];--j)
nums[j+1] = nums[j];
nums[j+1] = key;
}
}
}
再改进一点,就是二分插入排序,针对前半部分进行二分查找。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22void binaryinsertsort(int nums[],int n)
{
// binary insert sort
int i,j,low,high,mid;
int key;
for(int i=1;i<n;++i)
{
key = nums[i];
low = 0;high = i-1;
while(low <= high)
{
mid = (low+high)/2;
if(nums[mid] > key)
high = mid-1;
else
low = mid +1;
}
for(j =i-1;j>high;--j)
nums[j+1] = nums[j];
nums[j+1] = key;
}
}
交换类排序
冒泡排序
每次都要交换:1
2
3
4
5
6
7
8
9
10
11
12void bubblesort(int nums[],int n)
{
// original bubble sort
for(int i=0;i<n;i++)
{
for(int j = 1;j<n-i;++j)
{
if(nums[j] < nums[j-1])
swap(nums[j],nums[j-1]);
}
}
}
稍微改进一下,若一次冒泡的过程中没有发生一次交换,那就正好有序了。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19void bubblesort(int nums[],int n)
{
// original bubble sort
bool flag = false;
for(int i=0;i<n;i++)
{
flag = false;
for(int j = 1;j<n-i;++j)
{
if(nums[j] < nums[j-1])
{
swap(nums[j],nums[j-1]);
flag = true;
}
}
if(!flag)
break;
}
}
快速排序
1 | int partition(int nums[],int low,int high) |
选择类排序
简单选择排序
1 | void selectsort(int nums[],int n) |
递归版的简单选择排序
1 | void simplleSelectSortMore(int nums[],int n) |
堆排序
堆是一个类似于完全二叉树的结构,但是其中根节点的值要大于其叶子节点的值(大根堆),或者小于其叶子节点的值(小根堆)。正好可以用数组来表示堆结构。堆排序的过程就是一个删除根节点,调整堆结构的过程。
1 | void maxHeap(int nums[],int n,int i) |
参考的博客里面的下标都是从1开始,我写的程序都是从0开始的,但是并不影响理解程序。
归并排序
也是分治思想
1 | void merge(int nums[],int beg,int end,int mid) |