复习
合并:
这个比较简单,就大概的说下,先把两个序列合并,然后对序列进行len-1次相互元素的比较,即冒泡,最后得出一个有序序列
我觉得这种思想挺重要的,很多问题你可以用分治法去解决,但是中间过程步骤你可能先整体考虑,然后进行局部处理。
Node *Sort_Elem(Node *head) { Node p; //p变量主要是在冒泡里面做临时变量 Node *q; int i=1,len; len=List_length(head); //cout<<len<<" "; q=new Node; q=head; //Out_list(p); p.data=0; p.next=NULL; cout<<head->next->data<<endl; while(true) //这里我用了冒泡排序,其他排序你们可以自己尝试下 { while(head->next!=NULL) //这里要从head->next开始判断,和普通的冒泡排序类似 { if((head->data) > (head->next->data)) { p.data=head->next->data; head->next->data=head->data; head->data=p.data; } head=head->next; } i++; if(i==len) return q; //循环跳出条件 head=q; //q主要是在一次冒泡过后,将头指针复位 } } void Combine_list(Node *head1,Node *head2) { Node *p; p=new Node; p=head1; //先将头指针赋给p while(head1=head1->next) if(head1->next==NULL) { head1->next=head2; p=Sort_Elem(p); Out_list(p); return; } }
栈:(记住头尾指针和栈长度)
栈这个东西,其实会用就行,毕竟STL里面有类模板,个人认为代码越简单越好,因为有些特殊的情况不是每个人都能考虑到的
用的多了,自然就会,所以把大致的思想理清楚就可以了。
下面是精简了很多的代码,基本上是主要内容都有了。
void Init_stack(Stack &S) { S.base = new int[Max]; S.top = S.base; S.length = Max; } void Push(Stack &S,int e) { if(S.top - S.base == S.length) { printf("栈已满!\n"); return; } *S.top = e; S.top++; } void Pop(Stack &S,int &e) //STL里面的stack出栈只是Pop(); 后面一个参数作用不大 { if(S.top == S.base) printf("栈已空\n"); S.top--; e = *S.top; } int Gettop(Stack &S) { if(S.top == S.base) printf("栈已空!\n"); return (*(S.top-1)); } int Stack_length(Stack &S) { Stack flag; flag.top = S.top; int k=0; while(flag.top--) { k++; if(flag.top == S.base) return k; } } void Out_stack(Stack &S) { Stack flag; flag.top = S.top; while(flag.top--) { printf("%d ",*flag.top); if(flag.top == S.base) { printf("\n"); return; } } }
进制转换的函数:
这个希望都能记住,因为这种取模求余的思想在很多题目上都会有体现,像大数问题,某些字符串问题和欧几里德类的问题。
void change(Stack S,int a,int b) { int s=0,c,k; k=a; while(a) { Push(S,a%b); a/=b; } while(S.base != S.top) { s += Gettop(S); s *= 10; Pop(S,c); } cout<<"十进制数 "<<k<<" 转换为 "<<b<<" 进制数为: "<<s/10<<endl; }
括号匹配源代码:
括号匹配只是栈里面的一个简单的运用,帮助你理解栈的实质思想吧,自我感觉没什么技巧可言
void Kuo_hao(Stack &S) { char c[101]; int flag = 1,i,e; cin>>c; //读入数据 for(i=0;c[i]!='\0';i++) { if(c[i] == '(' || c[i] == '[') Push(S,(int)c[i]); //压栈 if(c[i] == ')') //如果匹配,弹出,标记,break用不用无所谓 { if( (char)Gettop(S) == '(' ) Pop(S,e); else flag = 0; } if(c[i] == ']') { if( (char)Gettop(S) == '[' ) Pop(S,e); else flag = 0; } } if(S.top == S.base && flag) cout<<"所输入的括号匹配成功!"<<endl; else cout<<"所输入的括号匹配失败!"<<endl; }
//这里的链式队列步骤基本是按照书本上的,可以自己尝试不加头结点,如何构造链式队列,并且基本操作可以执行
这里的链式队列操作无非就是创建,销毁,增加(减少),查找,更新这些操作
所以你基本记住一个头指针和一个尾指针,剩下的就是移动这些指针来操作,中间步骤无非就是临时创建一个指针或者一个存储单位
有些时候,你要先想下如果插入是否会溢出,主函数传递过来的能不能在调用的函数里面进行操作,头指针和尾指针什么时候相遇。。。
大概就是这些内容
void Init_queue(LinkQueue &Q) { Q.front=Q.rear=new QNode; Q.front->next=NULL; // 头结点的next域为空 } void Destroy_queue(LinkQueue &Q) { while(Q.front) // Q.front不为空 { Q.rear=Q.front->next; // Q.rear指向Q.front的下一个结点 delete Q.front; // 释放Q.front所指结点 Q.front=Q.rear; // Q.front指向Q.front的下一个结点 } } bool Queue_empty(LinkQueue Q) { if(Q.front->next==NULL) return true; else return false; //return !(Q.front->next); 精简 } int Queue_length(LinkQueue Q) { int i=0; QueuePtr p=Q.front; // 临时指针p指向头结点 while(Q.rear!=p) { i++; p=p->next; // p指向下一个结点 } return i; } int Get_head(LinkQueue Q,QElemType &e) { QueuePtr p; if(Q.front==Q.rear) return 0; p=Q.front->next; e=p->data; return 1; } void En_queue(LinkQueue &Q,QElemType e) { QueuePtr p; p=new QNode; // 动态生成新结点 if(!p) exit(1); p->data=e; p->next=NULL; Q.rear->next=p; // 原队尾结点的指针指向新结点 Q.rear=p; // 尾指针指向新结点 } int De_queue(LinkQueue &Q,QElemType &e) { QueuePtr p; if(Q.front==Q.rear) return 0; p=Q.front->next; // p指向队头结点 e=p->data; Q.front->next=p->next; // 头结点指向下一个结点 if(Q.rear==p) // 删除的是队尾结点 Q.rear=Q.front; // 修改队尾指针指向头结点(空队列) delete p; return 1; } void Queue_traverse(LinkQueue Q,void(*visit)(QElemType)) //从队头到队尾依次对队列Q中每个元素调用函数visit() { QueuePtr p; p=Q.front->next; // p指向队头结点 while(p) // p指向结点 { visit(p->data); // 对p所指元素调用visit() p=p->next; // p指向下一个结点 } printf("\n"); }
下面的是二叉树的构建,遍历,计数,复制的基本操作
二叉树,首先你要想到,它要有左右孩子,所以这个时候,你要选择递归的方式来解决问题
上面的这些操作都用到了递归,构建无非就是开辟一个节点,然后左右递归,遍历类似
计数和复制 你要先判断树有没有构建,然后进行操作
关于递归的技巧 多敲敲就会了
BiTNode *CreateBiTree(){ char ch; BiTNode *T; scanf("%c",&ch); if(ch=='#')T=NULL; else{ T = new BiTNode; T->data = ch; T->lchild = CreateBiTree(); T->rchild = CreateBiTree(); } return T;//返回根节点 } int Depth(BiTNode *T) { if(T == NULL) return 0; else return Depth(T->lchild)>Depth(T->rchild)?Depth(T->lchild)+1:Depth(T->rchild)+1; } int NodeCount(BiTNode *T,int &Yezi,int &flag) { if(T == NULL) return 0; else { if(T->lchild == NULL && T->rchild == NULL) Yezi++; if(T->lchild != NULL && T->rchild != NULL) flag++; return NodeCount(T->lchild,Yezi,flag) + NodeCount(T->rchild,Yezi,flag) + 1; } } //先序遍历二叉树 void PreOrderTraverse(BiTNode *T){ if(T){ printf("%c",T->data); PreOrderTraverse(T->lchild); PreOrderTraverse(T->rchild); } } //中序遍历 void InOrderTraverse(BiTNode *T){ if(T){ PreOrderTraverse(T->lchild); printf("%c",T->data); PreOrderTraverse(T->rchild); } } //后序遍历 void PostOrderTraverse(BiTNode *T){ if(T){ PreOrderTraverse(T->lchild); PreOrderTraverse(T->rchild); printf("%c",T->data); } } void Copy(BiTNode *T,BiTNode *(&TT)) // 囧(/ □ \),这个地方指针问题调试了好久,各种情况都试了一下,最后终于OK了! { if(T == NULL) { TT = NULL; return; } else { TT = new BiTNode; TT->data = T->data; Copy(T->lchild,TT->lchild); Copy(T->rchild,TT->rchild); } }
顺序查找 没什么说的,遍历就行
二分查找里面,你要知道的就是一个low,一个high下标
因为你每次都是二分,直到不能再分为止,所以一个while循环,里面就是结束的临界点
然后while循环里面你要操作,这个时候你就判断如果找到了,直接跳出。
int Search_Seq(SSTable ST,int x,int &k) { int i; for(i = 1; i <= ST.length; i++,k++) { if(ST.R[i].key == x) return i; } return -1; } int Search_Bin(SSTable ST,int x,int &k) { int i; int low,high; low = 1; high = ST.length; while(low<=high) { k++; int mid = (low+high)/2; if(ST.R[mid].key == x) return mid; else if(ST.R[mid].key < x) low = mid + 1; else high = mid - 1; } return -1; }
图里面有很多算法,dfs和bfs是比较简单基础的
那么怎么来记呢
dfs就是创建好了一个邻接矩阵后,对里面的元素先for循环遍历,对于每遍历一个元素
此时你要标记它访问过,然后再访问和这个元素有关的其他元素,并且其他元素也是没有标记的
这里就有点像栈的形式,不断向下搜索
void DFS(AMGraph &G,int k) { int j; visited[k]=true; cout<<G.vexs[k]<<" "; for(j=0;j<G.vexnum;j++) { if(!visited[j]&&G.arcs[k][j]!=MaxInt) DFS(G,j); } }
而对于bfs来说,就类似于先找出一个点,然后把与这个点有关的所有点都遍历完
全部存放到队列里面,所以while循环里面你要先从队列里面弹出一个元素,进行操作,这个操作就会把所有有关的点全部压入队列
所以不断重复操作,直到队列非空
大概思路就是这样的
和bfd有关的题目主要是迷宫之类的
void BFS(ALGraph &G,char v) { cout<<v<<" "; visited[v]=true; char flag,k; queue<char>q; q.push(v); while(!q.empty()) { flag=q.front();//cout<<flag; q.pop(); ArcNode *pp; pp = new ArcNode; pp=G.vertices[LocateVex(G,flag)].firstarc; //cout<<pp->adjvex<<endl; //k=G.vertices[pp->adjvex]; for(;pp!=NULL;pp=pp->nextarc) { k=G.vertices[pp->adjvex].data; //cout<<visited[k]; if(!visited[k]) { cout<<k<<" "; //cout<<q.empty(); visited[k]=true; q.push(k); } } }//cout<<"nihao"; }
二叉排序树:
主要是构建,查找,插入,删除操作
构建这里就是不断调用插入函数来实现,while循环建议用9999999这种大数形式
因为书上给的伪代码在数据类型上不同,所以导致用#这种会错
然后是插入函数里面无非就是递归插入(因为二叉树嘛!),在查找函数上,也主要是递归形式吧
删除函数上面,因为要删的是参数的节点,所以你首先要查找到这个节点,定位好后,你要根据中序遍历的结果
删除相应的节点,并且保证操作后的中序序列仍能保持原来的序(貌似老师上课是这样说的),不过我觉的你按照代码的步骤
在纸上画画,大概也就是删节点,孩子节点替代。。
BSTree SearchBST(BSTree T,int key) { if(!T || key == T-> data.key){ //cout<<1; return T;} else if(key < T-> data.key) return SearchBST(T-> lchild,key); else return SearchBST(T-> rchild,key); } void InsertBST(BSTree &T,ElemType E) { if(!T) //这个地方不能把if的顺序放到后面,我调试了下,貌似是优先判断是否为空,然后在操作...... { BSTree s; s = new BSTNode; s ->data = E; s -> lchild = s -> rchild = NULL; T = s; } else if(E.key < T-> data.key) InsertBST(T-> lchild,E); else if(E.key > T-> data.key) InsertBST(T-> rchild,E); } void CreatBST(BSTree &T) { ElemType e; T = NULL; cin>>e.key; while(e.key<999999) { InsertBST(T,e); cin>>e.key; } } void DeleteBST(BSTree &T,int key)//delete函数没有调试,书上代码全都给出来了 { BSTree f=NULL,p=T,s,q; while(p) { if(p->data.key == key) break; else if(p->data.key>key) p = p -> lchild; else p = p -> rchild; } if(!p) return; if(p -> lchild && p -> rchild) { q = p; s = p -> lchild; while(p -> lchild) { q = s; s = s -> rchild; } if(q != p) //这个地方按照书上给的那个图,可能会产生疑惑 //书上给出的只是中序遍历后节点刚好是右子树的,还有一种就是没有右子树的情况...... q -> rchild = s -> rchild; else q -> lchild = s -> lchild; delete s; return; } else if(!p -> rchild) { q = p; p = p ->lchild; } else if(!p ->lchild) { q = p; p = p -> rchild; } if(!f) T = p; else if(q == f ->lchild) f ->lchild = p; else f ->rchild = p; delete q; }
后面的四种排序是最近讲的,这里就不提了
原理自己看看就明白
后面我推荐一片文章:数据结构心得
链接
http://blog.csdn.net/k183000860/article/details/42101783