排序算法一------插入排序,使用二分查找法对插入排序进行优化,希尔排序

外部排序:指数据不能一次性加载到内存里去
内部排序:指数据能一次性加载到内存里去
非比较排序:不用比较就能进行的排序
比较排序:进行比较才能进行的排序
稳定性:如两个学生按照学号排:a在b的前面,按照成绩排a还是在b的前面,则这种排序算法是稳定的;若是如两个学生按照学号排:a在b的前面,按照成绩排b在a的前面,则是不稳定的(成绩是有序的)
排序算法分类:
    1、插入排序:
插入排序

.h

# pragma once
# include<stdio.h>
# include<string.h>
# include<stdlib.h>
# include<assert.h>
//插入排序
void PrintArray(int *array, int size);
void InsertSort(int *array, int size);
 

.c

# include"paixu1.h"
void PrintArray(int *array, int size)
{
	int i = 0;
	for (; i < size; ++i)
	{
		printf("%d", array[i]);
	}
	printf("\n");
}
void InsertSort(int *array, int size)
{
	int i = 1;
	for (; i < size; ++i)
	{
		int key = array[i];
		int end = i - 1;
		//查找待插入元素的位置
		while (end >= 0 && key < array[end])
		{
			array[end + 1] = array[end];
			--end;
		}
		//key大于end+1处的元素
		array[end + 1] = key;
	}
}
void TestChaRuSort()
{
	int array[] = { 2, 5, 4, 9, 3, 6, 8, 7, 1, 0 };
	PrintArray(array, sizeof(array) / sizeof(array[0]));
	InsertSort(array, sizeof(array) / sizeof(array[0]));
	PrintArray(array, sizeof(array) / sizeof(array[0]));
}
 
test.c
# include"paixu1.h"
void PrintArray(int *array, int size)
{
	int i = 0;
	for (; i < size; ++i)
	{
		printf("%d", array[i]);
	}
	printf("\n");
}
void InsertSort(int *array, int size)
{
	int i = 1;
	for (; i < size; ++i)
	{
		int key = array[i];
		int end = i - 1;
		//查找待插入元素的位置
		while (end >= 0 && key < array[end])
		{
			array[end + 1] = array[end];
			--end;
		}
		//key大于end+1处的元素
		array[end + 1] = key;
	}
}
void TestChaRuSort()
{
	int array[] = { 2, 5, 4, 9, 3, 6, 8, 7, 1, 0 };
	PrintArray(array, sizeof(array) / sizeof(array[0]));
	InsertSort(array, sizeof(array) / sizeof(array[0]));
	PrintArray(array, sizeof(array) / sizeof(array[0]));
}
 
结果:

(1)插入排序用二分法优化
begin标记起始地址,end标记最后一个元素的位置;key与中间元素进行比较

搬移元素的次数没改变,但是比较的次数相对于未优化的场景减少了;插入排序适用于(1、数据接近于有序的情况时间复杂度为O(n),不用搬移数据;2、适用于数据量较小的、元素个数较少的)
头文件及测试代码同上

.c

# include"paixu1.h"
void PrintArray(int *array, int size)
{
	int i = 0;
	for (; i < size; ++i)
	{
		printf("%d", array[i]);
	}
	printf("\n");
}
void InsertSort(int *array, int size)
{
	int i = 1;
	for (; i < size; ++i)
	{
		int key = array[i];
		int begin = 0;
		int end = i - 1;
 		int mid =-1;
		//通过二分查找查找待插入元素的位置
		while (begin<=end)
		{
			mid = begin + ((end - begin) >> 1);
			if (key>=array[mid])
				begin = mid + 1;
			else
				end = mid - 1;
		}
		//搬移元素
		end = i - 1;
		while (end >= begin)
		{
			array[end + 1] = array[end];
			--end;
		}
		array[begin] = key;
	}
}
void TestChaRuSort()
{
	int array[] = { 2, 5, 4, 9, 3, 6, 8, 7, 1, 0 };
	PrintArray(array, sizeof(array) / sizeof(array[0]));
	InsertSort(array, sizeof(array) / sizeof(array[0]));
	PrintArray(array, sizeof(array) / sizeof(array[0]));
}
 

2、希尔排序

.c

源文件及测试代码同未优化的插入排序

void shellSort(int *array, int size)
{
	int i = 1;
	int gap = 3;//将分组的间隔给为3
	while (gap>0)
	{
		for (i = gap; i < size; ++i)//第一个分组的排序
		{
			int key = array[i];
			int end = i - gap;
			//查找待插入元素的位置
			while (end >= 0 && key < array[end])
			{
				array[end + gap] = array[end];
				end -= gap;
			}
			//插入元素
			array[end + gap] = key;
		}
		gap--;
	}
}

关于gap取值的多种方式:
1、首先将gap直接给为size,每次给gap直接除二

2、每次都给gap取一些素数,直至取到1为止
3、每次让gap取gap除三加1的方式,gap从size的位置开始,效率很高。代码如下:
void shellSort(int *array, int size)
{
	int i = 1;
	int gap = size;//将分组的间隔给为3
	while (gap>1)//因为按照这种方式,gap最后一次的取值一定是1而不是0
	{
		gap = gap / 3 + 1;
		for (i = gap; i < size; ++i)//第一个分组的排序
		{
			int key = array[i];
			int end = i - gap;
			//查找待插入元素的位置
			while (end >= 0 && key < array[end])
			{
				array[end + gap] = array[end];
				end -= gap;
			}
			//插入元素
			array[end + gap] = key;
		}
 	}
}

猜你喜欢

转载自blog.csdn.net/xuruhua/article/details/80497494