线性表
1.将两个递增的有序链表合并,要求结果链表任使用原来两个链表的存储空间,不另外占用其他存储空间。表中不允许有重复的数据。
void MergeList(Linelist &La,Linklist &Lb,LineList &Lc)
{//合并链表La,Lb,合并新的表使用头指针Lc指向
pa=La->next;pb=Lb->next;//pa和pb分别是链表La,Lb的工作指针,初始化为相应的链表的第一个结点
Lc=pc=La;//用La的头结点作为Lc的头结点。
while(pa&&pb){
if(pa->data<pb->data){pc->next=pa;pc=pa;pa=pa->data;}
//取较小者La中的元素,将pa链接在pc的后面,pa指针后移。
else if(pa->data>pb->data){pc->next=pb;pc=pb;pb=pc->data;}
//取较小者Lb中的元素,将pb链接在pc的后面,pb指针后移。
else {pc->next=pa;pc=pa;pa=pa->next;q=pb->next;delete pb;pb=q;}
//相等时取La中的元素,删除Lb中的元素。
}
pc->next=pa?pa:pb;//插入剩余段
delete Lb;//释放Lb的头结点
}
2.将两个递增的无序链表合并,要求结果链表任使用原来两个链表的存储空间,不另外占用其他存储空间。表中不允许有重复的数据。
void MergeList(Linelist &La,Linklist &Lb,LineList &Lc)
{//合并链表La,Lb,合并新的表使用头指针Lc指向
pa=La->next;pb=Lb->next;//pa和pb分别是链表La,Lb的工作指针,初始化为相应的链表的第一个结点
Lc=pc=La;//用La的头结点作为Lc的头结点。
Lc->next=NULL;
while(pa||pb){
if(!pa){q=pb;pb=pb->next;}
else if(!pb){q=pa;pa=pa->next;}
else if(pa->data<=pb->data){q=pa;pa=pa->next;}
//取较小者(相等)La中的元素,用q指向pb,pa指针后移。
else {q=pb;pb=pb->next;}
//取较小者Lb中的元素,用q指向pa,pb指针后移。(pa->data>pb->data)
q->next=Lc->next;Lc->next=q
//将q指向的结点插入Lc表的表头结点之后。
}
delete Lb;//释放Lb的头结点
}
栈和队列
入栈
Status push(LineStack &S,SElemType e)
{//在栈顶插入元素e
p->new StackNode;p->data=e;p->next=s;s=p;return ok;}
出栈
Status pop(LineStack &S,SElemType &e)
{//删除s的栈顶元素,用e返回其值。
if(s==unll)return error;
e=s->data;p=s;s=s->next;delete p;return ok;}
队列
队空:Q.front==Q.rear
队满:(Q.rear+1)%MAXQsize==Q.front
队列长度:(Q.rear-Q.front+MAXQSIZE)%MAXQSIZE
数组A[0...m]中,入队时操作:rear=(rear+1)%(m+1)
1.判断回文
#define StackSize 100;
typedef char DataType;//假定栈元素的数据类型为字节。
typedef struct
{
DataType data[StackSize];
int top;
}SeqStack;
int IShuiwen(char *t)
{
SeqStack s;
int i,len;
char temp;
initStack(&s);
len=Strlen(t);//求向量长度
for(i=0;i<len/2,i++)
Push(&s,t[i]);//将一半的字符入栈
while(!EmptyStack(&s)){
temp=pop(&s);
if(temp!=s[i])return 0;//不等则返回0;
else i++;
}
return 1;//比较完毕后均相等则返回1
}
串,数组和广义表
串是内容受限的线性表,它限定了表中的元素为字符。
串的模式匹配算法
BF算法:最简单直观。好O(n+m) ,坏O(n*m)。
KMP算法:next,nextval。
数组
数组一般不进行插入或删除的操作。
特殊矩阵的压缩存储
- 对称矩阵:n*n,则将n*n个元压缩存储到n(n+1)/2。
- 三角矩阵:可分三角矩阵和下三角矩阵。
- 多对角矩阵
- 稀疏矩阵
广义表
- A=()——A是一个空表,其长度为0;
- B=(e)——B只有一个原子e,其长度为1;
- C=(a,(b,c,d))——C的长度为2,两个元素分别为原子a和子表(b,c,d)。
- D=(A,B,C)——D的长度为3,3个元素都是广义表,显然,将子表的值代入后,则有D=((),(e),(a,(b,c,d)))。
- E=(a,E)——这是一个递归的表,其长度为2,E相当于一个无限的广义表E=(a,(a,(a...)))。
- 取GetHead(LS):取出的表头为非空广义表的第一个元素,它可以是一个单原子,也可以是一个子表。
- 取GetTail(LS):取出的表尾为除去表头之外由其余元素构成的表,即表尾一定是一个广义表。
GetHead(B)=e,GetTail(),
GetHead(D)=A,GetTail(B,C)。
广义表的存储结构:tag=1 | hp | tp (表结点),tag=0 | atom 原子结点
题目:写一个递归算法来实现字符串逆序存储,要求不另设串存储空间。
void Inver(char A[]){
//字符串逆序存储的递归算法
char ch;
static int i=0;//需要使用静态变量
cin>>ch;
if(ch!='.')
{
Inver(A);A[i++]=ch;//字符串逆序存储
}
A[i]='\0';//字符串结尾标记
}
树和二叉树
哈夫曼树:左0,右1。没有度为1的结点。树中两个权值最小的结点一定是兄弟
1.统计二叉树树的叶结点个数
int LeafNodeCount(Bitree T){
if(T==unll)return 0;
else if(T->lchild==null&&T->rchild==null)return 1;
else return LeafNodeCount(T->lchild)+LeafNodeCount(T->rchild);
}
2.判别两棵树是否相等
int Compare(TreeNode*tree1;TreeNode *tree2){
bool tree1isnull=(tree1==null);
bool tree2isnull=(tree2==null);
if(tree1isnull!=tree2isnull){return 1;}
if(tree1isnull&&tree2isnull){return 0;}
if(tree1->c!tree2->c){return 1;}
return Compare(Tree1->left,Tree2->right)&Compare(Tree1->right,Tree2->left)
Compare(Tree1->left,tree2->left)&Compare(Tree1->right,Tree2->right);
}
图
邻接矩阵
一个图的邻接矩阵表示是唯一的。
查找邻接矩阵的所有元素才能统计完毕,时间复杂度为O(n*n)。
邻接表
不是唯一,因各个边结点链入顺序是任意的。
空间效率O(N+e)。统计边的数目O(N+e)。
比较项目 | 邻接矩阵 | 邻接表 | ||
无向图 | 有向图 | 无向图 | 有向图 | |
空间 | 邻接矩阵对称可压缩至n(n-1)/2个单元 | 邻接矩阵不对称可压缩至n*n个单元 | 存储n+2e个单元 | 存储n+e个单元 |
适用情况 | 稠密图 | 稀疏图 |
图的遍历
深度遍历DFS
类似先序遍历,栈结构来实现。
广度遍历BFS
类似层次遍历,队列结构来实现。
最小生成树
普里姆算法:核心思想归并点,时间复杂度为O(n*n),适用于稠密图。
克鲁斯卡尔算法:核心思想归并边,时间复杂度O(elog₂e),适用于稀疏图。
最短路径
迪杰斯特拉:Dijkstra从某个源点到其余各顶点的最短路径。时间复杂度为O(n*n)
费洛伊德算法:每一对顶点之间的最短路径。时间复杂度为O(n*n*n)
拓扑排序
重复选择没有直接前驱的顶点。时间复杂度为O(n+e)
拓扑排序可以判断出一个有向图是否有环。
关键路径
....
题目:
- 具有n个顶点的有向图最多有n(n-1)条边。
- 具有n个顶点的无向图最多有n(n-1)/2条边。
- n个顶点的连通图用邻接矩阵表示时,该矩阵至少有2(n-1)个非零元素。
查找
平衡二叉树:只要二叉树上有一个结点的平衡因子的绝对值大于1,则该二叉树就是不平衡的。
对包含n个元素的表进行顺序查找时,若查找每个元素的概率相等,则平均查找长度为(n+1)/2。-失败(n+1)。
排序
- 堆是一种选择排序。堆的形状是一棵完全二叉树。
- 要求内存最大的是归并排序。(稳定)
- 希尔排序,快速排序,堆排序是不稳定的。
- 快速排序最好在被排序的数据完全无序。最坏是被排序的数据基本有序。
- 对n个关键字进行快速排序,最坏情况,时间复杂度是O(n*n)。