算法复习-归并、快排、插入、堆-c++实现

1、归并排序:时间最差o(nlogn) 空间O(n),稳定排序,算法表现也很稳定

void merge(int list[], int s, int mid, int e)
{
	int n1 = mid-s;
	int n2 = e-mid;
	int *list1= new int[n1+1];
	int *list2= new int[n2+1]; // 将前半部分和后半部分分别赋给数组list1和list2

	int i=0;
	for(i=0;i<n1;i++)
		list1[i] = list[i+s];
	list1[n1] = INT_MAX;
	for(i=0;i<n2;i++)
		list2[i] = list[i+mid];
	list2[n2] = INT_MAX; // 加入哨兵

	int i1=0, i2=0;
	i=0;
	while(i<n1+n2) // 注意list从s开始到e,而list1和list2是从0开始,索引不要弄错!
		list[s+i++] = list1[i1]<list2[i2]?list1[i1++]:list2[i2++];
	delete[] list1,list2;
}

void mergesort(int *list, int s, int e)
{
	if (s+1>=e) // 只有一个数则不merge
		return;
	int mid = (e-s)/2+s;
	//cout<<"s mid e "<<s<<' '<<mid<<' '<<e<<endl;
	mergesort(list, s, mid);
	mergesort(list, mid, e);
	merge(list, s, mid, e);
}


测试 n=10^5 时耗时 0.21 秒


2、快排:时间期望o(nlogn) 空间O(1)(性能差异大)不稳定排序

// 快排的partition函数
int partition(int *list, int s, int e)
{
	int flag = list[e-1];
	int i=s,j=s-1,tmp;
	for (;i<e;i++)
	{
		if (list[i]<=flag)
		{
			j++;
			tmp = list[i];
			list[i] = list[j];
			list[j] = tmp;
		}
	}
	return j;
}
// 快排 10**5 需要0.262秒
void quicksort(int *list, int s, int e)
{
	if (s+1>=e)
		return;
	int deli = partition(list, s, e);
	quicksort(list, s, deli);
	quicksort(list, deli+1, e);
}


3、插入排序:时间最差o(n^2) 空间O(1) 稳定排序,数据小时效果好 

void insertsort(int *list, int n)
{
	int j,tmp;
	for(int i=1;i<n;i++)
	{
		j = i-1;
		tmp = list[i];
		while(j>=0 && list[j]>tmp) // 前面的大,则向后移一位
		{
			list[j+1] = list[j];
			j--;
		}
		list[j+1] = tmp;
	}
}

n=10^5 时耗时 7.023 秒


4、堆排序:时间最差o(nlogn) 空间O(1) (不稳定)常用于求出数列中最大/小的前n个树,分别用最小/大堆实现

class Heap
{
public:
	int length;
	int heapsize;
	int *list;

	Heap(int *li, int n)
	{
		length = n;
		heapsize = n;
		list = new int[n];
		for(int i=0;i<n;i++)
			list[i] = li[i];

		buildheap();
	}
	~Heap(){delete[] list;}

	// 左右节点,父节点,交换
	int left(int i){return i*2+1;}
	int right(int i){return i*2+2;}
	int pre(int i){return (i-1)/2;}
	void swap(int &x, int &y){int tp=x;x=y;y=tp;}

	// 保持堆的性质
	void heapify(int i)
	{
		int imax = i;
		if (left(i)<heapsize && list[left(i)]>list[imax]) 
			imax = left(i);
		if (right(i)<heapsize && list[right(i)]>list[imax])
			imax = right(i);

		if (imax!=i)
		{
			swap(list[imax], list[i]);
			heapify(imax);
		}
	}
		
	// 建堆
	void buildheap()
	{
		for (int i=heapsize/3;i>=0;i--) // 从有子节点的节点往上heapify
			heapify(i);
	}

	// 堆排序
	void heap_sort()
	{
		for (int i=length-1;i>0;i--)
		{
			//cout<<"heapsize: "<<heapsize<<endl;
			swap(list[0], list[i]);
			heapsize--;
			heapify(0);
		}
	}

	// 返回最大值
	int getmax(){return list[0];}

	// 抽取最大值
	int exctratmax()
	{
		swap(list[0], list[heapsize-1]);
		heapsize--;
		heapify(0);
		return list[heapsize];
	}


};

n=10^5 时耗时 0.331 秒,建堆O(n),heapify O(logn);排序时将顶点元素换至队尾,再对顶点元素进行heapify,因此复杂度为nlogn



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值