《算法笔记》2

// 链表
// 创建链表
#include 
#include 
struct node{
	int data;
	node* next;
};
node* create(int Array[]) {
	node *head, *p, *pre;
	head = new node;
	head->next = NULL;
	pre = head;  //头是空的
	for(int i=0; i<5; i++) {
		p = new node;
		p->data = Array[i];
		p->next = NULL;
		pre->next = p;
		pre = p;
	}
	return head;
}
int main() {
	int Array[5] = {4, 5, 6, 2, 3};
	node* L = create(Array);
	// 输出
	L = L->next;
	while(L != NULL) {
		printf("%d ",L->data);
		L = L->next;
	}
}
// 插入元素
void insert(node* head, int pos, int x) {
	//插到pos位置 例 原 5 3 6 1 2 pos=3 x=4 后 5 3 '4' 6 1 2
	node*p = head;
	for(int i=0; inext;  //p为插入位置的前个节点
	}
	node* p = new node;
	q->data = x;
	q->next = p->next;
	p->next = q;
}
// 删除元素
void del(node* head, int x) {
	node* pre = head;

	node* p = head->next;
	while(p != NULL) {
		if(p->data = x) {
			pre->next = p->next;
			delete(p);  //手动释放空间
			p = p->next;
		} else {
			pre = p;
			p = p->next;
		}
	}
}

// 静态链表
struct node{
	int data;
	int next;
} Node[MAXN];
// 大整数类 ------------------------------------------
struct bign{
	int d[1000];
	int len;
	// bign() {
	// 	memset(d, 0, sizeof(d));
	// 	len = 0;
	// }
}
// 将字符串表示的大整数转化成bign
bign change(char str[]) {
	bign a;
	a.len = strlen(str);
	for(int i=0; i b.len) {
		return 1;
	} else if(a.len < b.len) {
		return -1;
	} else {
		for(int i=0; i b.d[i]) {
				return 1;
			} else {
				return 1;
			}
		}
		return 0;
	}
}
// 高精度 + 高精度
bign add(bign a, bign b) {
	bign c;
	int carry = 0;
	for(int i=0; i= 2 && c.d[c.len - 1] == 0) {
	//长度至少是2(因为若只有一位的话,那么允许为零),且最高位为零
		c.len --;  //即:去处高位的0,同时至少保留一位最低位(0)
	}
	return c;
}
// 高精度 * 低精度
bign multi(bign a, int b) {
	bign c;
	int carry = 0;
	for(int i=0; i=0; i--) {  //从高位开始
		r = r * 10 + a.d[i];
		if(r < b) c.d[i] = 0;  //不够除
		else {
			c.d[i] = r / b;
			r = r % b;
		}
	}
	while(c.len >= 2 && c.d[c.len - 1] == 0) {
		//长度至少是2(因为若只有一位的话,那么允许为零),且最高位为零
		c.len--;  // 去处高位的0,同时至少保留一位最低位(0)
	}
	return c;
}
// 进制转换 ------------------------------------------

---代码1---
// 将10进制的数字N的每位转换为D(任意)进制存到数组number[],即:'除基(D)求余(D)'得到每位然后存到数组。《3.5》
// 为什么输入的必须是10进制(或问只被计算机认为是10进制呢),因为'除基求余法'基于'多项式求和',所有的任意进制分解都是以它为和进行的。(纯属XB~)
	int len = 0;
	do{  // 0
		number[len++] = N % D;  //数组0号下标存个位数字
		N /= D;
	} while(N != 0);  //注:结束时N为0
// 例如:	input:N=(10进制数字)123,D=8
// 			output:(8进制数字)371(即:173)

---代码2---
// 当上面代码的D=10时,又多了一个新功能:取原数的每位存到数组number[]
	int len = 0;
	do{  // 0
		number[len++] = N % 10;  //数组0号下标存个位数字
		N /= 10;
	} while(N != 0);  //注:结束时N为0

---代码3---
// 以下代码可以理解为上面代码的增加* product后的新增功能,但不无完全是,因为:强行指定了:p进制:product*=p,而不是上述的10进制了
// p(强行指定:product*=p,而不是上述的10进制了)进制x(直接)转为十进制y(不满足任意进制,Only:10进制),即:'除基(10)求余(10)'得到每位然后乘以对应的权值(p的n次方)(实质即:以p为基数的多项式求和)。《3.5》
// 与秦九韶公式的区别:不需要数组; 从低位开始,而秦九韶从高位开始。
	int y = 0, product = 1;
	while(x != 0) { //for循环不如while,for循环需要先知道位数,while循环的条件只是'x!=0',且可以顺便求位数
		y += (x % 10) * product;  //初始时从个位开始
		x /= 10;  //x指向高一位
		product *= p;  //product加权
	}

---代码4---
// 得到number[]的情况下用秦九韶公式计算多项式和(因为秦九韶需要数组),进制(基数)为D
	int N = 0;  //括号内的是N,然后N*D
	for(int i=len-1; i>0; i--) {
	//因为得到的number[]是倒序存的(即:下标由小到大对应数字的由个位到高位),而秦九韶要求从高位开始,所以起始i=len-1
	//若number[]本来即为正序的,则起始i=0
		N = N * D + number[i];
	}

其中:‘代码3’等价于‘代码2+代码4’,但后者实现代码较长、时间复杂度较优(原因在于秦九韶公式求和比一般的多项式累加求和的计算次数要少)。

8进制  >>>(代码3 或 代码2+代码4)>>>  10进制
10进制  >>>(代码1)>>>  16进制
8进制  >>>(代码3 或 代码2+代码4)>>>  10进制  >>>(代码1)>>>  16进制

但是,用“ 8进制  >>>(代码3 或 代码2+代码4)>>>  10进制  >>>(代码1)>>>  16进制 ”的方式时,对于长数(1000位)溢出。
所以位数长时,用8进制  >>>>>>  2进制  >>>>>>  16进制,例题代码如下:

原题:十六进制转八进制
#include 
#include 
#include 
#include 
using namespace std; 
int N;
int main() {
    scanf("%d",&N);
    for(int i=0; i>str1;
        for(int j=0; j
#include 
#include 
using namespace std;
int main() {
    char a[20], s[20];
    gets(a);
    int sum = 0;
    for(int i=0; i中,typename1为键(相当于数组的下标),typename2为值(相当于数组下标所存(对应)的值),
		当typename1为数字时(即map数字到数字的映射),整个等价于一个数组。
		当typename1为字符时,可使用map,也可使用map用ACII码。
		当typename1为字符串时,需要用string类型map,不能用字符数组map(看着就别扭)。
		当typename1需要为结构体时,也有定义,但一般不推荐,而一般用map和数组结合的方式。(见:PATA180318C)
二维数组
	其实,二维数组就扯远了,他虽能达到和使用Map相同的效果,但效率上并没什么意义。
【例1】----------------------------------
Sample Input 1:
7 5 31 5 88 67 88 17
Sample Output 1:
31  //第一个投注唯一数字的人获胜
Sample Input 2:
5 888 666 666 888 888
Sample Output 2:
None
//代码1-哈希散列实现
#include 
int main() {
	int HashTable[150], num[150], N;
	scanf("%d",&N);
	int x;
	for(int i=0; i
#include 
using namespace std;
int main() {
	int N, tag[1010];
	map mapp;
	scanf("%d",&N);
	for(int i=0; i
#include 
using namespace std;
int main() {
	bool HashTable[10010];
	char a[1010], b[1010];
	gets(a);
	gets(b);
	for(int i=0; i
#include 
#include 
using namespace std;
int main() {
	mapmapp;
	char strA[1010], strB[1010];
	gets(strA);
	gets(strB);
	for(int i=0; i
#include 
using namespace std;
int main() {
	int M, N;
	map count;
	scanf("%d%d",&M,&N);
	for(int i=0; i::iterator it = count.begin(); it != count.end(); it++) {
		if(it->second > max) {
			max = it->second;
			k = it->first;
		}
	}
	printf("%d",k);
	return 0;
}
【例4】----------------------------------
模拟散列的冲突解决(二次探测,仅正增量)
Sample Input:
4 4
10 6 4 15
Sample Output:
0 1 4 -
//哈希散列实现,因为要模拟散列的冲突解决
#include 
#include 
#include 
#include 
using namespace std;
const int MAX = 100010;
bool isPrime(int x) {
	if(x<=1) return false;
	for(int i=2; i<=sqrt(x); i++) {  //<= <= <= !!!
		if(x % i == 0) return false;
	}
	return true;
}
int main() {
	int Tsize, N, HashTable[MAX];
	scanf("%d%d",&Tsize,&N);
	memset(HashTable,-1,MAX);
	while(isPrime(Tsize) == false) {
		Tsize++;
	}
	int key;
	for(int i=0; i= Tsize) printf("-");
		}
		if(i != N-1) printf(" ");
	}
	return 0;
}
第二遍代码-----------------
#include 
#include 
using namespace std;
bool isPrime(int x) {
	if(x <= 1) return false;
	for(int i=2; i<=sqrt(x); i++)  //<=  <=  <=  4!!
		if(x % i == 0)
			return false;
	return true;
}
int main() {
	int MSize, N, HashTable[1010];
	 scanf("%d%d",&MSize, &N);
	 while(!isPrime(MSize)) MSize++;
	 for(int i=0; i= MSize) {
	 			flag = 1;
	 			break;	
	 		}
	 	}
	 	if(flag == 0) {
			printf("%d",pos % MSize);
			HashTable[pos % MSize] = 1;
		} else printf("-");
		if(i < N) printf(" ");
	 }
}
// 并查集 ------------------------------------------
Sample Input:
3 2 3  //城市数目 路的数目 检查的数目
1 2
1 3
1 2 3
Sample Output:
1  //如果城市1沦陷了,需修1条公路才能将其他的城市连起来
0
0
// Thinking:
// 先把路径保存到图里,
// 再根据读取到的删除的结点来把图里的路径相连的结点包含到并查集里的一个集合,
// 然后遍历集合个数。
// 注:(1)为啥不一开始读路径时就直接建并查集呢? 因为之后在并查集里删结点不好操作
// 注:(2)为啥第一步不是把数据读到一个二维数组里,而是读到图里呢? 
// 		因为既然选择了要先存路径相连节点再根据其建立并查集,
// 		所以相比一个随意的存储结构,图更具便利性。
#include 
#include 
using namespace std;
const int MAXN = 1010;
int N, M, K, vis[MAXN];
vector G[MAXN];
int father[MAXN];
void init() {
	for(int i=1; i<=N; i++) {
		father[i] = i;
		vis[i] = false;
	}
}
int findFather(int a) {
	int b = a;
	while(father[a] != a)
		a = father[a];
	while(b != father[b]) {
		int c = b;
		b = father[b];
		father[c] = a;
	}
	return a;
}
void un(int u, int v) {
	int uF = findFather(u);
	int vF = findFather(v);
	if(uF != vF) father[uF] = vF;
}
int main() {
	scanf("%d%d%d",&N,&M,&K);
	int a, b;
	for(int i=0; i G[MAXN]; G[i].size();
.length() 
	String srt; str.length();
strlen()
	char a[20]; strlen(a);
======================================================

 

你可能感兴趣的:(c++)