复习
合并:
这个比较简单,就大概的说下,先把两个序列合并,然后对序列进行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

浙公网安备 33010602011771号