首页 > 代码库 > 数据结构与算法二

数据结构与算法二

1.课程安排表:

1. 线性表

2. 字符串

3. 栈和队列

4.树

5.查找

6.排序

7.暴力枚举法

8.广度优先搜索

9.深度优先搜索

10.分治

11.贪心

12.动态规划

13.图

14.数学方法与常见模型

15.大整数运算

16. 基础功能

2.   编程技巧:

1.把较大的数组放在main 函数(全局变量)外,作为全局变量,这样可以防止栈溢出,因为栈的大小是有限制的。GCC (C编译器) 段错误

2.如果能够预估栈,队列的上限,则不要用stack,queue,使用数组来模拟,这样速度最快。

3.输入数据一般放在全局变量,且在运行过程中不要修改这些变量。

4.在判断两个浮点数a 和b 是否相等时,不要用a==b,应该判断二者之差的绝对值fabs(a-b) 是否小于某个阈值,例如1e-9。

5.判断一个整数是否是为奇数,用x % 2 !=0,不要用x % 2 ==1,因为x 可能是负数。

6.用char 的值作为数组下标(例如,统计字符串中每个字符出现的次数),要考虑到char 可能是负数。有的人考虑到了,先强制转型为unsignedint 再用作下标,这仍然是错的。正确的做法是,先强制转型为unsignedchar,再用作下标。这涉及C++ 整型

提升的规则,就不详述了。

3.线性表小结:

题目:快速找到未知长度单链表的中间节点。

设置2个指针,一开始同时指向头,第一个指针比第二个指针快2倍

4. 字符串函数的内部实现

1.strlen

描述:实现strlen,获取字符串的长度。函数原型如下:

int strlen(const char *str)

代码:

int strlen(const char *str)
{
	const char *s;
	for(s=str; *s; ++s)
		;
	return (s-str);
}

2.strcpy

   实现strcpy,字符串拷贝函数,函数原型如下:

char*strcpy(char *to, const char *from);

代码:

char *strcpy(char *to, const char *from)
{
	assert(to != NULL  && from != NULL);//断言错误
	char *p = to;
	while((*p++ = *from++) != '\0')
	;
	return to;
}

5.在排列中实现下一次排列


例如:数字1,2,3

1 2 3       ;    当前序号1

1 3 2       ;    当前序号2

2 1 3       ;    当前序号3

2 3 1       ;    当前序号4

3 1 2       ;    当前序号5

3 2 1       ;    当前序号6

三个数字1,2,3,有6种可能的排序情况,上述分别将序号都列举了出来。

那么现在需要解决的问题就是:已知当前排列中的序号 N, 求下一个序列 N+1。

 

求解过程:

为了便于操作,我们假设5个数字,分别是1,2,3,4,5

测试序列:以当前序列:1,4,3,5,2求出它的下一次排列。

现在将问题分解为4步骤:

1. 从后向前找出第一个不符合降序排列的数的下标,记为 i_pos,在本例子中那么就是数字3,下标i_pos 就是2。这里解释下何为第一个“不符合降序排列的数”,以例子来解释,从后向前找数的过程中,5,2,  是一个降序的排列,而3,5,2, 则破坏了这个降序的排列结构。

2. 在第一步找到的降序队列中,从其中找出大于下标为i_pos 的数,并且这个数在所有大于下标为i_pos 的数列中是最小的。那么以例子来说,这一步找到的数就是5,记录下标为j_pos;

3. 交换i_pos, 和 j_pos 下标的值。  执行完之后: 1,4,5,3,2

4. 从下标i_pos+1 开始知道末尾,对数列进行升序。例子中就应该是对 3,2 进行升序,最后的结果就是: 1,4,5,2,3

5. 最后输出结果。

 

代码实现:


#include <iostream>
#define swapData(x,y) {int tmp=x; x = y; y = tmp;}

using namespace std;

int next_permutation(int *num, int n)
{
	int length = n-1;
	int i_pos=-1;
	
	for(int i=length; i > 0; i --)
	{
		if(num[i]>num[i-1])
		{
			i_pos = i-1;
			break;
		}
	}
	// 判断是否到了末尾,即全部序列是降序的 
	if(i_pos==-1) return 0;
	
	int j_pos;
	for(int i=length; i > i_pos; i--)
	{
		if(num[i] > num[i_pos])
		{
			j_pos = i;
			break;
		}
	}
	
	swapData(num[i_pos], num[j_pos]);
	
	
	//冒泡排序 
	for(int i=i_pos+1; i < n; i++)
	{
		for(int j=length;  j > i; j--)
		{
			if(num[j] < num[j-1])
				swapData(num[j], num[j-1]);
		}
	}
		
	return 1;
}

main()
{
	int num[5]={1,2,3,4,5};
	do
	{
		for(int i=0; i <= 4; i++)
			cout << num[i] << " ";
		cout << endl;
	}while(next_permutation(num, 5));
	return 0;
}