Coding In C++, Day10

程序设计=数据结构+算法  外加"设计方法学"
数值算法:微积分、方程组、有限元分析等—工程计算。
非数值算法:查找、排序、决策、调度—系统编程。
一、冒泡排序
1.算法
1)比较相邻的元素,如果第一个比第二个大,就交换它们俩;
2)对每一对相邻的元素做同样的工作,从开始的第一对到结尾的最后一对,使最后的元素为最大值;
3)针对的所有的元素重复以上步骤,除了最后一个;
4)持续每次对越来越少的元素重复以上步骤,直到没有元素需要交换为止。
2.评价
平均时间复杂度:O(N^2)
稳定
对数据的有序性非常敏感
二、插入排序
1.算法
1)从第一个元素开始,该元素可以认为已经有序;
2)取出下一个元素,在已经有序的序列中从后向前扫描;
3)若该元素大于新元素,则将该元素移到下一个位置;
4)若该元素小于等于新元素,则将新元素放在该元素之后;
5)重复步骤2),直到处理完所有元素。
2.评价
平均时间复杂度:O(N^2)
稳定
对数据的有序性非常敏感
因为没有交换,所以赋值的次数比冒泡少,速度比冒泡略快。
三、选择排序
1.算法
首先在未排序序列中找到最小元素,与该序列的首元素交换,再从剩余未排序元素中继续寻找最小元素,放到有序序列的末尾。以此类推,直到所有元素均排序完毕。
2.评价
平均时间复杂度:O(N^2)
稳定
对数据的有序性不敏感
因为交换的次数少,所有速度比冒泡略快。


四、快速排序

1.算法
1)从序列中选出一个元素作为基准;
2)重排序列,所有比基准小的元素位于基准左侧,比基准大的元素位于基准右侧,和基准相等的元素位于任意一侧,此过程称为分组;
3)以递归的方式对小于基准的分组和大于基准的分组分别进行排序。
2.评价
平均时间复杂度:O(NlogN)

不稳定

如果每次能够均匀分组速度将是最快的。


五、归并排序

1.算法
1)申请空间,其大小为两个有序序列之和;
2)设定两个指针,分别指向两个有序序列的起始位置;
3)比较两个指针的目标,选择小值放入合并空间,并将指针移到下一个位置;
4)重复步骤3)直到某一个指针到达序列尾;
5)将另一序列的剩余元素直接复制到合并空间。
2.评价
平均时间复杂度:O(2NlogN)
稳定
对数据的有序性不敏感
非就地排序,不适用于大数据量的排序。

#include <iostream>
using namespace std;
// 冒泡排序
void bubbleSort (int data[], size_t size) {
	for (size_t i = 0; i < size - 1; ++i) {
		bool ordered = true;
		for (size_t j = 0; j < size - 1 - i; ++j)
			if (data[j+1] < data[j]) {
				int temp = data[j+1];
				data[j+1] = data[j];
				data[j] = temp;
				ordered = false;
			}
		if (ordered)
			break;
	}
}
// 插入排序
void insertSort (int data[], size_t size) {
	for (size_t i = 1; i < size; ++i) {
		int temp = data[i];
		size_t j;
		for (j = i; j > 0 && temp < data[j-1]; --j)
			data[j] = data[j-1];
		if (j != i)
			data[j] = temp;
	}
}
// 选择排序
void selectSort (int data[], size_t size) {
	for (size_t i = 0; i < size - 1; ++i) {
		size_t min = i;
		for (size_t j = i + 1; j < size; ++j)
			if (data[j] < data[min])
				min = j;
		if (min != i) {
			int temp = data[i];
			data[i] = data[min];
			data[min] = temp;
		}
	}
}
// 快速排序
void quickSort (int data[], size_t left,
	size_t right) {
	size_t p = (left + right) / 2;
	int pivot = data[p];
	for (size_t i = left, j = right; i < j;) {
		while (! (i>= p || pivot < data[i]))
			++i;
		if (i < p) {
			data[p] = data[i];
			p = i;
		}
		while (! (j <= p || data[j] < pivot))
			--j;
		if (j > p) {
			data[p] = data[j];
			p = j;
		}
	}
	data[p] = pivot;
	if (p - left > 1)
		quickSort (data, left, p - 1);
	if (right - p > 1)
		quickSort (data, p + 1, right);
}
// 异地合并
void merge (int data1[], size_t size1, int data2[],
	size_t size2, int data3[]) {
	size_t i = 0, j = 0, k = 0;
	for (;;)
		if (i < size1 && j < size2)
			if (data1[i] <= data2[j])
				data3[k++] = data1[i++];
			else
				data3[k++] = data2[j++];
		else if (i < size1)
			data3[k++] = data1[i++];
		else if (j < size2)
			data3[k++] = data2[j++];
		else
			break;
}
// 本地合并
void merge (int data[], size_t l, size_t m,
	size_t r) {
	int* res = new int[r-l+1];
	merge (data+l, m-l+1, data+m+1, r-m, res);
	for (size_t i = 0; i < r-l+1; ++i)
		data[l+i] = res[i];
	delete[] res;
}
// 归并排序
void mergeSort (int data[], size_t left,
	size_t right) {
	if (left < right) {
		int mid = (left + right) / 2;
		mergeSort (data, left, mid);
		mergeSort (data, mid+1, right);
		merge (data, left, mid, right);
	}
}
int main (void) {
	int data[] = {13,23,20,12,15,31,19,26,24,37};
	size_t size = sizeof (data) / sizeof (data[0]);
//	bubbleSort (data, size);
//	insertSort (data, size);
//	selectSort (data, size);
//	quickSort (data, 0, size - 1);
	mergeSort (data, 0, size - 1);
	for (size_t i = 0; i < size; ++i)
		cout << data[i] << ' ';
	cout << endl;
	/*
	int data1[] = {10, 20, 30, 45, 66};
	int data2[] = {15, 18, 27, 33};
	int data3[9];
	merge (data1, 5, data2, 4, data3);
	for (size_t i = 0; i < 9; ++i)
		cout << data3[i] << ' ';
	cout << endl;
	// 10 15 18 20 27 30 33 45 66
	/*
	int data[] = {100,10,20,30,45,66,15,18,27,33,0};
	merge (data, 1, 5, 9);
	for (size_t i = 0; i < 11; ++i)
		cout << data[i] << ' ';
	cout << endl;
	// 100 10 15 18 20 27 30 33 45 66 0
	*/
	return 0;
}






/*
 *  泛型的快速排序
 *
 * C语言标准库中提供的快速排序就是通过函数指针、通过内存拷贝实现了泛型;
 * C语言向下泛型,因为物理层面他们计算机中的信息没有类型区别;
 */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
static void quickSort (void* base, size_t left,
	size_t right, size_t size, int (*compar) (
	const void*, const void*)) {
	size_t p = (left + right) / 2;
	void* pivot = malloc (size);
	memcpy (pivot, base + p * size, size);
	size_t i, j;
	for (i = left, j = right; i < j;) {
		while (! (i >= p || compar (pivot,
			base + i * size) < 0))
			++i;
		if (i < p) {
			memcpy (base + p * size,
				base + i * size, size);
			p = i;
		}
		while (! (j <= p || compar (
			base + j * size, pivot) < 0))
			--j;
		if (j > p) {
			memcpy (base + p * size,
				base + j * size, size);
			p = j;
		}
	}
	memcpy (base + p * size, pivot, size);
	free (pivot);
	if (p - left > 1)
		quickSort (base, left, p - 1, size, compar);
	if (right - p > 1)
		quickSort (base, p+1, right, size, compar);
}
void my_qsort (void* base, size_t numb, size_t size,
	int (*compar) (const void*, const void*)) {
	quickSort (base, 0, numb -1, size, compar);
}
int cmpInt (const void* a, const void* b) {
	return *(const int*)a - *(const int*)b;
}
int cmpStr (const void* a, const void* b) {
	return strcmp (*(const char* const*)a,
		*(const char* const*)b);
}
int main (void) {
	int na[] = {34, 22, 19, 27, 30};
	size_t size = sizeof (na[0]);
	size_t numb = sizeof (na) / size;
//	qsort (na, numb, size, cmpInt);
	my_qsort (na, numb, size, cmpInt);
	size_t i;
	for (i = 0; i < numb; ++i)
		printf ("%d ", na[i]);
	printf ("\n");
	const char* sa[] = {"beijing", "chongqing",
		"shanghai", "tianjin", "guangzhou"};
	size = sizeof (sa[0]);
	numb = sizeof (sa) / size;
//	qsort (sa, numb, size, cmpStr);
	my_qsort (sa, numb, size, cmpStr);
	for (i = 0; i < numb; ++i)
		printf ("%s ", sa[i]);
	printf ("\n");
	return 0;
}


/*
 * 泛型的快速排序
 *
 * C语言标准库中提供的快速排序通过函数指针、通过内存拷贝实现了泛型;而C++因为可以让对象支持统一的行为(比如都支持* /->操作), 进而通过C++的模板就也实现了泛型;
 * 他们的区别是:
 * C语言向下泛型,因为物理层面他们计算机中的信息没有类型区别;
 * C++语言向上泛型,因为C++通过对行为的抽象,通过让对象支持统一的行为,对于统一的行为通过模板实现泛型。
 */
#include <iostream>
#include <vector>
#include <list>
using namespace std;
template<class iterator>
void print(iterator begin, iterator end)
{
    while (begin != end) {
	cout << *begin++ << ' ';
    }

    cout << endl;
}
template<typename type>
void my_swap (type& a, type& b) {
	type c = a;
	a = b;
	b = c;
}
template<typename iterator>
void my_sort (iterator begin, iterator end) {
	iterator p = begin;
	iterator last = end;
	--last;
	for (iterator i = begin, j = last; i != j;) {
		while (! (i == p || *p < *i))
			++i;
		if (i != p) {
			my_swap (*p, *i);
			p = i;
		}
		while (! (j == p || *j < *p))
			--j;
		if (j != p) {
			my_swap (*p, *j);
			p = j;
		}
	}
	iterator it = begin;
	++it;
	if (p != begin && p != it)
		my_sort (begin, p);
	it = p;
	++it;
	if (it != end && it != last)
		my_sort (it, end);
}
template<typename iterator, typename comparator>
void my_sort (iterator begin, iterator end,
	comparator cmp) {
	iterator p = begin;
	iterator last = end;
	--last;
	for (iterator i = begin, j = last; i != j;) {
		while (! (i == p || cmp (*p, *i)))
			++i;
		if (i != p) {
			my_swap (*p, *i);
			p = i;
		}
		while (! (j == p || cmp (*j, *p)))
			--j;
		if (j != p) {
			my_swap (*p, *j);
			p = j;
		}
	}
	iterator it = begin;
	++it;
	if (p != begin && p != it)
		my_sort (begin, p, cmp);
	it = p;
	++it;
	if (it != end && it != last)
		my_sort (it, end, cmp);
}

//测试用例
class CmpInt {
public:
	bool operator() (int a, int b) const {
		return a > b;
	}
};


bool Compare(int a, int b)
{
    return a > b;
}



int main (void) {
	int na[] = {13, 24, 22, 19, 44, 56, 88, 22};
	vector<int> vi (na, na + 8);
	list<int> li (na, na + 8);
	my_sort (na, na + 8);
	print (na, na + 8);
	my_sort (vi.begin (), vi.end ());
	print (vi.begin (), vi.end ());
	my_sort (li.begin (), li.end (), CmpInt ());
	print (li.begin (), li.end ());
	my_sort (li.begin (), li.end (),Compare);
	print (li.begin (), li.end ());
	return 0;
}





六、线性查找
1.算法
从表头开始依次比较,直到找到与查找目标匹配的元素,或者找不到。
2.评价
平均时间复杂度:O(N)
对数据的有序性没有要求

七、二分查找

1.算法
首先必须保证查找样本必须有序,将表中值与查找目标进行比较,如果二者相等,则查找成功,否则根据查找目标比中值大或者小,在其右侧或者左侧继续前述过程。直到查找成果或者失败。
2.评价
平均时间复杂度:O(logN)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C和C++的安全编码是指在编写C和C++代码时,采取一系列的措施来确保代码的安全性和防止常见的安全漏洞。由于C和C++是底层的编程语言,它们允许对内存直接进行操作,这也使得它们容易受到各种安全威胁的攻击。 在进行安全编码时,有几个关键的原则需要遵循。首先是验证输入。由于输入数据往往是来自外部,我们需要对输入进行验证,以确保它们符合预期的格式和范围。这样可以防止缓冲区溢出和格式化字符串漏洞等攻击。 其次,应该正确地管理内存。C和C++允许直接控制内存的分配和释放,但这也意味着需要手动管理内存的生命周期。如果没有正确地分配和释放内存,会导致内存泄漏和非法内存访问等问题。因此,务必要仔细检查并指定正确的内存操作。 此外,还应注意避免使用不安全的函数和功能。一些函数和功能可能存在安全风险,如strcpy和scanf等。应该使用更安全的替代函数,如strncpy和fgets等,以提高代码的安全性。 最后,代码的安全性也需要经过不断的测试和审查。通过进行静态代码分析和动态测试,可以发现和纠正代码中的潜在安全问题。此外,代码审查也是非常重要的,通过互相审查可以找到潜在的漏洞和错误。 总而言之,C和C++的安全编码需要遵循验证输入、正确管理内存、避免使用不安全函数和功能以及进行测试和审查等原则。只有通过采取适当的安全措施,才能确保代码的安全性并防止潜在的安全漏洞。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值