|
2011-7-18:
基础数据结构——栈、队列
2011-7-19:
二叉排序树代码,弄完栈和队列的同学可以看一下——指针实现
2011-7-20:
快速排序+归并排序
Merge.cpp
1 void Merge( DataType a[], int n, DataType swap[], int k ) 2 { 3 int m = 0, u1, u2, i, j, l2; 4 int l1 = 0; 5 6 while ( l1 + k <= n -1 ) 7 { 8 l2 = l1 + k; 9 u1 = u2 - 1; 10 u2 = ( l2 + k - 1 <= n - 1)? l2 + k - 1: n - 1; 11 12 //两个有序子数组的合并 13 for ( i = l1, j = l2; i <= u1 && j <= u2; m ++ ) 14 { 15 if ( a[i].key <= a[j].key ) 16 { 17 swap[a] = a[i]; 18 i ++; 19 } 20 else 21 { 22 swap[m] = a[j]; 23 j ++; 24 } 25 } 26 27 //子数组2已归并完,将子数组1中剩余元素存放到数组swap中 28 while ( i <= u1 ) 29 { 30 swap[m] = a[i]; 31 m ++; 32 i ++; 33 } 34 35 //子数组1已归并完,将子数组2中剩余元素存放到数组swap中 36 while( j <= u2 ) 37 { 38 swap[m] = a[j]; 39 m ++; 40 j ++ 41 } 42 43 l1 = u2 + 1; 44 } 45 46 //将原始数组中只够一组的数据元素顺序存放到数组swap中 47 for ( i = l1; i < n; i ++, m ++) 48 { 49 swap[m] = a[i]; 50 } 51 }
 MergeSort.cpp
1 void MergeSort( DataType a[], int n ) 2 { 3 int i, k = 1; 4 DataType *swap = new DataType[n]; 5 6 while ( k < n ) 7 { 8 Merge(a, n, swap, k); 9 for (i = 0; i < n; i ++) 10 { 11 a[i] = swap[i]; 12 } 13 14 k = 2 * k 15 } 16 17 delete []swap; 18 }
2011-7-21:
高精度计算
 View Code
#include <iostream> #include <string> using namespace std;
inline int compare(string str1, string str2) { if(str1.size() > str2.size()) //长度长的整数大于长度小的整数 return 1; else if(str1.size() < str2.size()) return -1; else return str1.compare(str2); //若长度相等,从头到尾按位比较,compare函数:相等返回0,大于返回1,小于返回-1 } //高精度加法 string ADD_INT(string str1, string str2) { string MINUS_INT(string str1, string str2); int sign = 1; //sign 为符号位 string str; if(str1[0] == '-') { if(str2[0] == '-') { sign = -1; str = ADD_INT(str1.erase(0, 1), str2.erase(0, 1)); }else { str = MINUS_INT(str2, str1.erase(0, 1)); } }else { if(str2[0] == '-') str = MINUS_INT(str1, str2.erase(0, 1)); else { //把两个整数对齐,短整数前面加0补齐 string::size_type l1, l2; int i; l1 = str1.size(); l2 = str2.size(); if(l1 < l2) { for(i = 1; i <= l2 - l1; i++) str1 = "0" + str1; }else { for(i = 1; i <= l1 - l2; i++) str2 = "0" + str2; } int int1 = 0, int2 = 0; //int2 记录进位 for(i = str1.size() - 1; i >= 0; i--) { int1 = (int(str1[i]) - 48 + int(str2[i]) - 48 + int2) % 10; //48 为 '0' 的ASCII 码 int2 = (int(str1[i]) - 48 + int(str2[i]) - 48 +int2) / 10; str = char(int1 + 48) + str; } if(int2 != 0) str = char(int2 + 48) + str; } } //运算后处理符号位 if((sign == -1) && (str[0] != '0')) str = "-" + str; return str; }
//高精度减法 string MINUS_INT(string str1, string str2) { string MULTIPLY_INT(string str1, string str2); int sign = 1; //sign 为符号位 string str; if(str2[0] == '-') str = ADD_INT(str1, str2.erase(0, 1)); else { int res = compare(str1, str2); if(res == 0) return "0"; if(res < 0) { sign = -1; string temp = str1; str1 = str2; str2 = temp; } string::size_type tempint; tempint = str1.size() - str2.size(); for(int i = str2.size() - 1; i >= 0; i--) { if(str1[i + tempint] < str2[i]) { str1[i + tempint - 1] = char(int(str1[i + tempint - 1]) - 1); str = char(str1[i + tempint] - str2[i] + 58) + str; } else str = char(str1[i + tempint] - str2[i] + 48) + str; } for(i = tempint - 1; i >= 0; i--) str = str1[i] + str; } //去除结果中多余的前导0 str.erase(0, str.find_first_not_of('0')); if(str.empty()) str = "0"; if((sign == -1) && (str[0] != '0')) str = "-" + str; return str; }
//高精度乘法 string MULTIPLY_INT(string str1, string str2) { int sign = 1; //sign 为符号位 string str; if(str1[0] == '-') { sign *= -1; str1 = str1.erase(0, 1); } if(str2[0] == '-') { sign *= -1; str2 = str2.erase(0, 1); } int i, j; string::size_type l1, l2; l1 = str1.size(); l2 = str2.size(); for(i = l2 - 1; i >= 0; i --) { //实现手工乘法 string tempstr; int int1 = 0, int2 = 0, int3 = int(str2[i]) - 48; if(int3 != 0) { for(j = 1; j <= (int)(l2 - 1 - i); j++) tempstr = "0" + tempstr; for(j = l1 - 1; j >= 0; j--) { int1 = (int3 * (int(str1[j]) - 48) + int2) % 10; int2 = (int3 * (int(str1[j]) - 48) + int2) / 10; tempstr = char(int1 + 48) + tempstr; } if(int2 != 0) tempstr = char(int2 + 48) + tempstr; } str = ADD_INT(str, tempstr); } //去除结果中的前导0 str.erase(0, str.find_first_not_of('0')); if(str.empty()) str = "0"; if((sign == -1) && (str[0] != '0')) str = "-" + str; return str; } //高精度除法 string DIVIDE_INT(string str1, string str2, int flag) { //flag = 1时,返回商; flag = 0时,返回余数 string quotient, residue; //定义商和余数 int sign1 = 1, sign2 = 1; if(str2 == "0") { //判断除数是否为0 quotient = "ERROR!"; residue = "ERROR!"; if(flag == 1) return quotient; else return residue; } if(str1 == "0") { //判断被除数是否为0 quotient = "0"; residue = "0"; } if(str1[0] == '-') { str1 = str1.erase(0, 1); sign1 *= -1; sign2 = -1; } if(str2[0] == '-') { str2 = str2.erase(0, 1); sign1 *= -1; } int res = compare(str1, str2); if(res < 0) { quotient = "0"; residue = str1; }else if(res == 0) { quotient = "1"; residue = "0"; }else { string::size_type l1, l2; l1 = str1.size(); l2 = str2.size(); string tempstr; tempstr.append(str1, 0, l2 - 1); //模拟手工除法 for(int i = l2 - 1; i < l1; i++) { tempstr = tempstr + str1[i]; for(char ch = '9'; ch >= '0'; ch --) { //试商 string str; str = str + ch; if(compare(MULTIPLY_INT(str2, str), tempstr) <= 0) { quotient = quotient + ch; tempstr = MINUS_INT(tempstr, MULTIPLY_INT(str2, str)); break; } } } residue = tempstr; } //去除结果中的前导0 quotient.erase(0, quotient.find_first_not_of('0')); if(quotient.empty()) quotient = "0"; if((sign1 == -1) && (quotient[0] != '0')) quotient = "-" + quotient; if((sign2 == -1) && (residue[0] != '0')) residue = "-" + residue; if(flag == 1) return quotient; else return residue; }
//高精度除法,返回商 string DIV_INT(string str1, string str2) { return DIVIDE_INT(str1, str2, 1); } //高精度除法,返回余数 string MOD_INT(string str1, string str2) { return DIVIDE_INT(str1, str2, 0); } int main() { char ch; string s1, s2, res; while(cin >> ch) { cin >> s1 >> s2; switch(ch) { case '+': res = ADD_INT(s1, s2); break; //高精度加法 case '-': res = MINUS_INT(s1, s2); break; //高精度减法 case '*': res = MULTIPLY_INT(s1, s2); break; //高精度乘法 case '/': res = DIV_INT(s1, s2); break; //高精度除法, 返回商 case 'm': res = MOD_INT(s1, s2); break; //高精度除法, 返回余数 default : break; } cout << res << endl; } return(0); }
2011-7-22:
贪心算法
堆排序代码
有个牛人讲的很好可以直接去他那看:http://www.wutianqi.com/?p=1820
 View Code
// array是待调整的堆数组,i是待调整的数组元素的位置,length是数组的长度 void HeapAdjust(int array[], int i, int nLength) { int nChild, nTemp;
for (nTemp = array[i]; 2 * i + 1 < nLength; i = nChild) { // 子结点的位置是 父结点位置 * 2 + 1 nChild = 2 * i + 1; // 得到子结点中较大的结点 if (nChild != nLength - 1 && array[nChild + 1] > array[nChild]) ++nChild; // 如果较大的子结点大于父结点那么把较大的子结点往上移动,替换它的父结点 if (nTemp < array[nChild]) { array[i] = array[nChild]; } else // 否则退出循环 { break; } } // 最后把需要调整的元素值放到合适的位置 array[i] = nTemp; }
// 堆排序算法 void HeapSort(int array[], int length) { // 调整序列的前半部分元素,调整完之后第一个元素是序列的最大的元素 for (int i = length / 2 - 1; i >= 0; --i) { HeapAdjust(array, i, length); } // 从最后一个元素开始对序列进行调整,不断的缩小调整的范围直到第一个元素 for (int i = length - 1; i > 0; --i) { // 把第一个元素和当前的最后一个元素交换, // 保证当前的最后一个位置的元素都是在现在的这个序列之中最大的 Swap(&array[0], &array[i]); // 不断缩小调整heap的范围,每一次调整完毕保证第一个元素是当前序列的最大值 HeapAdjust(array, 0, i); } }
2011-7-23:
哈希表
 方法
哈希表的设计主要是设计哈希函数
哈希函数:将关键字映射到哈希表的位置
哈希函数的建立有五种常见方法:
1. 除余法
2.折叠法
3.平方取中法
4.提取法
5. 基数转换法
哈希冲突解决方法
1. 开放定址法
开放定址法又分为线性探查法,二次探查法,双散列函数探查法
2.再哈希法
3.链地址法
4.建立一个公共溢出区
可扩展文件的散列函数
1.可扩展散列
2.线性散列
哈希程序示例:
冲突解决方法为:双散列函数探查法
哈希函数关键字为:人名字母ASCII相加
哈希函数为:关键字%M,从而映射到哈希表中的位置
 代码
#include<stdio.h> #include<conio.h> #define HASH_LEN 50 //哈希表的长度 #define M 47 //随机数 #define NAME_NO 30 //人名的个数 typedef struct
{ char *py; //名字的拼音 int k; //拼音所对应的整数 }NAME;
NAME NameList[HASH_LEN]; //全局变量NAME
typedef struct //哈希表 { char *py; //名字的拼音 int k; //拼音所对应的整数 int si; //查找长度 }HASH;
HASH HashList[HASH_LEN]; //全局变量HASH void InitNameList() //姓名(结构体数组)初始化 {
char *f; int r,s0,i; NameList[0].py="wanghui"; NameList[1].py="mayuelong"; NameList[2].py="chenzhicheng"; NameList[3].py="sunpeng"; NameList[4].py="zengqinghui"; NameList[5].py="liqingbo"; NameList[6].py="liujunpeng"; NameList[7].py="jiangquanlei"; NameList[8].py="xingzhengchuan"; NameList[9].py="luzhaoqian"; NameList[10].py="gaowenhu"; NameList[11].py="zhuhaoyin"; NameList[12].py="chenlili"; NameList[13].py="wuyunyun"; NameList[14].py="huangjuanxia"; NameList[15].py="wangyan"; NameList[16].py="zhoutao"; NameList[17].py="jiangzhenyu"; NameList[18].py="liuxiaolong"; NameList[19].py="wangziming"; NameList[20].py="fengjunbo"; NameList[21].py="lilei" NameList[22].py="wangjia"; NameList[23].py="zhangjianguo"; NameList[24].py="zhuqingqing"; NameList[25].py="huangmin"; NameList[26].py="haoyuhan"; NameList[27].py="zhoutao"; NameList[28].py="zhujiang"; NameList[29].py="lixiaojun"; for (i=0;i<NAME_NO;i++) { s0=0; f=NameList[i].py; for (r=0;*(f+r)!='\0';r++) s0=*(f+r)+s0; NameList[i].k=s0;
} }
void CreateHashList() //建立哈希表
{ int i; for (i=0; i<HASH_LEN;i++) { HashList[i].py=""; HashList[i].k=0; HashList[i].si=0; }
for (i=0;i<HASH_LEN;i++) { int sum=0; int adr=(NameList[i].k)%M; //哈希函数 int d=adr; if(HashList[adr].si==0) //如果不冲突 { HashList[adr].k=NameList[i].k; HashList[adr].py=NameList[i].py; HashList[adr].si=1; } else //冲突 { do { d=(d+NameList[i].k%10+1)%M; //伪随机探测再散列法处理冲突 sum=sum+1; //查找次数加1 }while (HashList[d].k!=0); HashList[d].k=NameList[i].k; HashList[d].py=NameList[i].py; HashList[d].si=sum+1; } } }
void FindList() //查找 { char name[20]={0}; int s0=0,r,sum=1,adr,d; printf("\n请输入姓名的拼音:"); scanf("%s",name); for (r=0;r<20;r++) //求出姓名的拼音所对应的整数(关键字) s0+=name[r]; adr=s0%M; //使用哈希函数 d=adr; if(HashList[adr].k==s0) //分3种情况进行判断 printf("\n姓名:%s 关键字:%d 查找长度为: 1",HashList[d].py,s0); else if (HashList[adr].k==0) printf("无此记录!"); else { int g=0; do { d=(d+s0%10+1)%M; //伪随机探测再散列法处理冲突 sum=sum+1; if (HashList[d].k==0) { printf("无此记录! "); g=1; } if (HashList[d].k==s0) { printf("\n姓名:%s 关键字:%d 查找长度为:%d",HashList[d].py,s0,sum); g=1; }
}while(g==0);
} }
void Display() // 显示哈希表 { int i; float average=0; printf("\n\n地址\t关键字\t\t搜索长度\tH(key)\t 姓名\n"); //显示的格式 for(i=0; i<50; i++) { printf("%d ",i); printf("\t%d ",HashList[i].k); printf("\t\t%d ",HashList[i].si); printf("\t\t%d ",HashList[i].k%M); printf("\t %s ",HashList[i].py); printf("\n"); } for (i=0;i<HASH_LEN;i++) average+=HashList[i].si; average/=NAME_NO; printf("\n\n平均查找长度:ASL(%d)=%f \n\n",NAME_NO,average);
}
void main()
{ char ch1; printf("\n 哈希表的建立和查找\n"); printf(" *-------------------------------------------*\n"); printf(" | D. 显示哈希表 |\n"); printf(" | F. 查找 |\n"); printf(" | Q. 退出 |\n"); printf(" *-------------------------------------------*\n"); InitNameList(); CreateHashList ();
while(1) { printf("\n Option-:"); fflush(stdin); ch1=getchar(); if (ch1=='D'||ch1=='d') Display(); else if (ch1=='F'||ch1=='f') FindList(); else if (ch1=='Q'||ch1=='q') return; else { printf("\n请输入正确的选择!"); } } }
2011-7-24:
休息
2011-7-25:
并查集
 View Code
#include <stdio.h> #include <stdlib.h> #include <string.h> struct road { int st; int ed; int w; }; road all[900]; int A[30]; int cmp(const void *a,const void *b) { return (*(road *)a).w - (*(road *)b).w; } int find(int x) { if (x != A[x]) A[x] = find(A[x]); return A[x]; } int main() { int i,j,k,q,p,m,n,sum; char s,e; while (scanf("%d",&n) != EOF) { if (n == 0) break; memset(A,0,sizeof(int)); for (i = 1;i <= n;i++) A[i] = i; m = 0; for (i = 1;i < n;i++) { scanf(" %c%d",&s,&p); while (p--) { scanf(" %c%d",&e,&q); all[m].st = s - 'A'; all[m].ed = e - 'A'; all[m].w = q; m++; } } qsort(all,m,sizeof(all[0]),cmp); k = 0;sum = 0; while (k < m) { all[k].st = find(all[k].st); all[k].ed = find(all[k].ed); if (all[k].st != all[k].ed) { sum += all[k].w; A[all[k].st] = all[k].ed; } k++; } printf("%d\n",sum); } system("pause"); return 0; }
 View Code
//【模板】并查集模板(经典应用——最小生成树)
//根采用数字本身和使用递归实现
int father[MAX]; //father[x]表示x的父节点 int num[MAX]; //num[x]表示x的秩,即x所在集合的元素个数
//初始化集合 void Make_Set(int x) { father[x] = x; //根据实际情况指定的父节点可变化 num[x] = 1; //根据实际情况初始化秩也有所变化 }
//查找x元素所在的集合,回溯时压缩路径 int Find_Set(int x) { if (x != father[x]) { father[x] = Find_Set(father[x]); //回溯时的压缩路径 }//从x结点搜索到祖先结点所经过的结点都指向该祖先结点 return father[x]; }
//按秩合并x,y所在的集合,按秩合并,实时更新秩。 void Union(int a, int b) { int x = Find_Set(a); int y = Find_Set(b); if(x == y) { return; } if(num[x] <= num[y]) { father[x] = y; num[y] += num[x]; } else { father[y] = x; num[x] += num[y]; } }
//采用-1做根和使用非递归实现
void Make_Set(int n) { for(i = 0; i < n; i++) { father[i] = -1; num[i] = 1; } }
//非递归实现,没有路径压缩 int Find_Set(int x) { while(father[x] != -1) //根为-1 { x = father[x]; } return x; }
2011-7-26:
Trie树
 基本实现
#include<algorithm> #include<iostream> using namespace std;
const int sonnum=26,base='a'; struct Trie { int num;//to remember how many word can reach here,that is to say,prefix bool terminal;//If terminal==true ,the current point has no following point struct Trie *son[sonnum];//the following point }; Trie *NewTrie()// create a new node { Trie *temp=new Trie; temp->num=1;temp->terminal=false; for(int i=0;i<sonnum;++i)temp->son[i]=NULL; return temp; } void Insert(Trie *pnt,char *s,int len)// insert a new word to Trie tree { Trie *temp=pnt; for(int i=0;i<len;++i) { if(temp->son[s[i]-base]==NULL)temp->son[s[i]-base]=NewTrie(); else temp->son[s[i]-base]->num++; temp=temp->son[s[i]-base]; } temp->terminal=true; } void Delete(Trie *pnt)// delete the whole tree { if(pnt!=NULL) { for(int i=0;i<sonnum;++i)if(pnt->son[i]!=NULL)Delete(pnt->son[i]); delete pnt; pnt=NULL; } } Trie* Find(Trie *pnt,char *s,int len)//trie to find the current word { Trie *temp=pnt; for(int i=0;i<len;++i) if(temp->son[s[i]-base]!=NULL)temp=temp->son[s[i]-base]; else return NULL; return temp; }
 another
//字典树模板 #include <iostream> using namespace std; const int kind=26; struct node { int i,count; node *next[kind]; node() { count=1; for(i=0;i<kind;i++) next[i]=NULL; } }; void insert(node *root,char *word) { int i=0,branch; node *local=root; if(local==NULL) { local=new node(); root=local; } while(word[i]) { branch=word[i]-'a'; if(local->next[branch]) local->next[branch]->count++; else local->next[branch]=new node(); i++; local=local->next[branch]; } } int search(node *root,char *word) { int i=0,branch,ans; node *local=root; if(local==NULL) return 0; while(word[i]) { branch=word[i]-'a'; if(!local->next[branch]) return 0; i++; local=local->next[branch]; ans=local->count; } return ans; } int main() { char str[12]; node *root=new node; while(gets(str) && strcmp(str,"")) insert(root,str); while(scanf("%s",str)!=EOF) printf("%d\n",search(root,str)); return 0; }
相关知识:自动机(hdu 2222,附代码见下面)(矩阵快速幂、容斥原理,KMP)
 自己写的太乱,还是放个思路比较清晰的吧
#include <iostream> using namespace std; const int size = 26; struct node { int count; node *son[size]; node *fail; node() { count = 0; fail = NULL; for (int i = 0; i < size; i ++){ son[i] = NULL; } } }*q[10000];
void insert(char *a, node *root)//建立字典树 { int len =strlen(a); node *p = root; for (int i = 0; i < len; i ++){ int k = a[i] - 'a'; if (p -> son[k] == NULL){ p -> son[k] = new node; } p = p -> son[k]; } p -> count ++; }
void build_ac_automation(node *root)//建立AC自动机 { int head = 0, tail = 0; root->fail = NULL; q[tail ++] = root; while (head != tail){ node *temp = q[head ++]; node *p = NULL; for (int i = 0; i < 26; i ++){ if (temp -> son[i] != NULL){//如果字母('a'+i)存在于单词中 if (temp == root){ temp -> son[i] -> fail = root;//如果为根结点,则fail指向root } else {//如果不存在,则依次取当前字母(temp)和其父节点字母(p) p = temp -> fail; while (p != NULL){//当前字母的父节点存在 if (p -> son[i] != NULL){//遍历看其父节点中有无同样的字母'a'+i temp -> son[i] -> fail = p -> son[i];//如果有,则改变当前temp的fail指针使其指向父节点的('a'+i)字母 break; } p = p -> fail;//继续向上探询父节点 } if (p == NULL)temp -> son[i] -> fail = root; //如果遍历到最上层都没有找到则将fail指向root } q[tail ++] = temp -> son[i];//当前点继续入队实现BFS; } } } }
int find(node *root, char *a) { int ans = 0, len = strlen(a); node *p = root; for (int i = 0; i < len; i ++){ int k = a[i] - 'a'; //如果当前字母没有匹配项则匹配其下一个fail指向的字母,如果都没有则回到根结点 while (p -> son[k] == NULL && p != root)p = p -> fail; //匹配当前字母 p = p -> son[k]; //如果当前没有字母,则回到根节点 p = (p == NULL)? root : p; node *temp = p; //如果当前存在字母(但是不知道是否相同)且没有被匹配过,则查找能够匹配的字母个数 while (temp != root && temp -> count != -1){ ans += temp -> count; temp -> count = -1; temp = temp -> fail; } } return ans; } char word[51], word1[1000010]; int main() { int t, n; scanf("%d", &n); while (n --){ scanf("%d", &t); node *root; root = new node; while (t --){ scanf("%s", word); insert(word, root); } build_ac_automation(root); scanf("%s", word1); printf("%d\n", find(root, word1)); } return 0; }
2011-7-27:
图的深度遍历
 BFS+DFS
#include<stdio.h> #include<stdlib.h> #define Max 10 #define FALSE 0 #define TRUE 1 #define Error printf #define QueueSize 30
typedef struct { char vexs[Max]; int edges[Max][Max]; int n,e; }MGraph;
int visited[Max];
typedef struct { int front; int rear; int count; int data[QueueSize]; }CirQueue;
//初始化队列 void InitQueue(CirQueue *Q) { Q->front=Q->rear=0; Q->count=0; }
//队列空 int QueueEmpty(CirQueue *Q) { return Q->count=QueueSize; }
//队列满 int QueueFull(CirQueue *Q) { return Q->count==QueueSize; }
//进队 void EnQueue(CirQueue *Q,int x) { if(QueueFull(Q)) { Error("Queue overflow"); } else { Q->count++; Q->data[Q->rear]=x; Q->rear=(Q->rear+1)%QueueSize; } }
//出队 int DeQueue(CirQueue *Q) { int temp; if(QueueEmpty(Q)) { Error("Queue underflow"); } else { temp=Q->data[Q->front]; Q->count--; Q->front=(Q->front+1)%QueueSize; return temp; } }
//建立图矩阵 void CreateMGraph(MGraph *G) { int i,j,k; char ch1,ch2; printf("\n\t\t请输入顶点数,边数并按回车键(格式:3,4):"); scanf("%d,%d",&(G->n),&(G->e)); for(i=0;i<G->n;i++) { getchar(); printf("\n\t\t请输入第%d个顶点序号并按回车键",i+1); scanf("%c",&(G->vexs[i])); } for(i=0;i<G->n;i++) { for(j=0;j<G->n;j++) { G->edges[i][j]=0; } } for(k=0;k<G->e;k++) { getchar(); printf("\n\t\t请输入第%d条边的顶点序号并按回车键(格式:i,j):",k+1); scanf("%c,%c",&ch1,&ch2); for(i=0;ch1!=G->vexs[i];i++); for(j=0;ch2!=G->vexs[j];j++); G->edges[i][j]=1; } }
//深度优先遍历递归 void DFSM(MGraph *G,int i) { int j; printf("\n\t\t深度遍历序列:%c\n",G->vexs[i]); visited[i]=TRUE; for(j=0;j<G->n;j++) { if(G->edges[i][j]==1&&!visited[j]) { DFSM(G,j); } } }
//广度优先遍历递归 void BFSM(MGraph *G,int k) { int i,j; CirQueue Q; InitQueue(&Q); printf("\n\t\t广度优先遍历序列:%c\n",G->vexs[k]); visited[k]=TRUE; EnQueue(&Q,k); while(!QueueEmpty(&Q)) { i=DeQueue(&Q); for(j=0;j<G->n;j++) { if(G->edges[i][j]==1 &&! visited[j]) { visited[j]=TRUE; EnQueue(&Q,j); } } } }
//深度优先遍历 void DFSTraverseM(MGraph *G) { int i; for(i=0;i<G->n;i++) { visited[i]=FALSE; } for(i=0;i<G->n;i++) { if(!visited[i]) { DFSM(G,i); } } }
//广度优先遍历 void BFSTraverseM(MGraph *G) { int i; for(i=0;i<G->n;i++) { visited[i]=FALSE; } for(i=0;i<G->n;i++) { if(!visited[i]) { BFSM(G,i); } } }
main() { MGraph *G,a; char ch1; int i,j,ch2; G=&a; printf("\n\t\t建立一个图矩阵\n"); CreateMGraph(G); printf("\n\t\t已建立图的矩阵\n"); for(i=0;i<G->n;i++) { printf("\n\t\t "); for(j=0;j<G->n;j++) { printf("%5d",G->edges[i][j]); } } getchar(); ch1='y'; while(ch1=='y'||ch1=='Y') { printf("\n"); printf("\n\t\t 图子系统 \n"); printf("\n\t\t***************************************\n"); printf("\n\t\t* 1--------更新矩阵 *\n"); printf("\n\t\t* 2--------深度优先遍历 *\n"); printf("\n\t\t* 3--------广度优先遍历 *\n"); printf("\n\t\t* 0--------退出 *\n"); printf("\n\t\t***************************************\n"); printf("\n\t\t请选择菜单号(0~3):"); scanf("%d",&ch2); getchar(); switch(ch2) { case 1: CreateMGraph(G); printf("\n\t\t图建立完毕!\n"); break; case 2: DFSTraverseM(G); break; case 3: BFSTraverseM(G); break; case 0: ch1='n'; break; default: system("cls"); printf("\n\t\t输入有误!\n"); break; } if(ch2==1||ch2==2||ch2==3) { printf("\n\n\t\t "); system("pause"); system("cls"); } } }
2011-7-28:
休息
最小生成树
 介绍
(1) 克鲁斯卡尔算法 图的存贮结构采用边集数组,且权值相等的边在数组中排列次序可以是任意的.该方法对于边相对比较多的不是很实用,浪费时间. (2) 普里姆算法 图的存贮结构采用邻接矩阵.此方法是按各个顶点连通的步骤进行,需要用一个顶点集合,开始为空集,以后将以连通的顶点陆续加入到集合中,全部顶点加入集合后就得到所需的最小生成树 . 具体介绍:http://www.wutianqi.com/?p=1284
 prim代码
#include <stdio.h> //#include <limits.h> #define INT_MAX 0x7fffffff #define N 100
int p[N], key[N], tb[N][N];
void prim(int v, int n) { int i, j; int min;
for (i = 1; i <= n; i++) { p[i] = v; key[i] = tb[v][i]; } key[v] = 0; for (i = 2; i <= n; i++) { min = INT_MAX; for (j = 1; j <= n; j++) if (key[j] > 0 && key[j] < min) { v = j; min = key[j]; } printf("%d%d ", p[v], v); key[v] = 0; for (j = 1; j <= n; j++) if (tb[v][j] < key[j]) p[j] = v, key[j] = tb[v][j]; } }
int main() { int n, m; int i, j; int u, v, w; while (scanf("%d%d", &n, &m)) { for(i = 1; i <= n; i++) { for (j = 1; j <= n; j++) tb[i][j] = INT_MAX; }
while (m--) { scanf("%d%d%d", &u, &v, &w); tb[u][v] = tb[v][u] = w; } prim(1, n); printf("\n"); } return 0; }
其他算法可以去下面的连接,讲的很好:
最短路径算法---Dijkstra(迪杰斯特拉)算法分析与实现(C/C++) 最短路径算法—Bellman-Ford(贝尔曼-福特)算法分析与实现(C/C++) 最短路径算法—SPFA(Shortest Path Faster Algorithm)算法分析与实现(C/C++)
2011-7-29:
拓扑排序
 暂时没找到很好的
//拓扑排序的模板 #include <iostream> using namespace std;
struct data { int in; // 某点的入度 int out; // 某点的出度 }s[];
int a,b,n,stk[]; bool visited[]; bool map[][];
int calc() { int i,j; for(i=0;i<n;i++) { for(j=0;j<n;j++) { if(map[i][j]) { s[i].out++; s[j].in++; } } }
for(i=0;i<n;i++) if( s[i].in + s[i].out != n-1 ) return 0;
return 1; }
void push(int k); { stk[++top] = k; }
void toplogical_sort() { int i,j; bool flg = 1; int zerop; for(i=1;i<=n;i++) { if(!s[i].in) { zerop = i; break; } } memset(visited,false,sizeof(visited)); while(flg) { flg = 0; for(i=1;i<=n;i++) { if ( !visited[i] ) { if (map[zerop][i]) { s[i].in--; } if ( s[i].in == 0 ) { zerop = i; flg = 1; } } } } }
void Output() //输出拓扑排序的结果 { int i; for(i=1;i<=top;i++) cout << stk[i] << " "; cout << endl; }
int main() { memset(map,0,sizeof(map)); memset(s,0,sizeof(s)); for(i=1;i<=n;i++) { cin >> a >> b; s[a].out++; s[b].in++; map[a][b] = 1; } top = 0; calc(); toplogical_sort(); Output();
return 0; }
2011-7-30:
字符串匹配(KMP)
 好像有点问题,大体思路对
#include<stdio.h> #include<string.h> #include<stdlib.h> FILE *fin=fopen("test.in","r"); FILE *fout=fopen("test.out","w"); char s1[200],s2[200]; int next[200];
int max(int a,int b) { if(a>b) return a; return b; }
void getnext() { memset(next,0,sizeof(next)); int i=-1,j=0; next[0]=-1; while(j<strlen(s2)) { if(i==-1||s2[i]==s2[j]) { i++;j++; next[j]=i; } else i=next[i]; } }
int KMP() { int i=0,j=0,len1=strlen(s1),len2=strlen(s2); while((i<len1)&&(j<len2)) { if(j==-1||s1[i]==s2[j]) {j++;i++;} else j=next[j]; } if(j==len2) return i-len2; else return -1; }
int index_KMP() { int i=0,j=0,len1=strlen(s1),len2=strlen(s2),re=0; while(i<len1&&j<len2) { if(j==-1||s1[i]==s2[j]) {i++;j++;} else j=next[j]; re=max(re,j); } return re; }
int main() { fscanf(fin,"%s",s1); for(int i=1;i<=3;i++) { fscanf(fin,"%s",s2); getnext(); fprintf(fout,"%d %d\n",KMP(),index_KMP()); } return 0; }
2011-7-31:
休息
|