前言
本文总结了《数据结构与算法》中核心代码,可用作考前复习,但禁止任何个人或集体利用本文进行作弊或商用,一经发现将追究其法律责任。未经允许,禁止转载!
若您在阅读过程中发现任何格式或内容上的错误,望您能发送邮件至yc_ent@163.com反馈,我将及时修正相关内容!非常感谢每一位读者的支持。
第一部分 线性表
顺序存储
存储结构
//静态分配
typedef struct
{
ElemType elem[MAXSIZE];
int length;//顺序表当前长度
} SqList;
//动态分配
typedef struct
{
ElemType *elem;
int length;
int listsize;
}SqList;
SqList L;
基本操作
//按位置插入
Status ListInsert(SqList &L,int i,ElemType e)
{
if(i>L.length+1 or L.length>=100 or i<1) return 0;
L.length++;
int temp;
int j=L.length;
while(j>=i)
{
L.elem[j]=L.elem[j-1];
j--;
}
L.elem[i-1]=e;
return 1;
}
//按位置删除
Status ListDelete(SqList &L,int i)
{
if(i>L.length or i<1) return 0;
L.length--;
i--;
while(i<L.length)
{
L.elem[i]=L.elem[i+1];
i++;
}
return 1;
}
链式存储(单链表)
存储结构
//单链表结点结构定义
typedef struct LNode
{
ElemType data;//数据域,存放数据元素
struct LNode *next;//指针域,指向后继元素
}LNode,*LinkList;//单链表的类型名
//生成一个LNode型新结点
LNode p=(LNode *)malloc(sizeof(LNode));
//回收结点
free(p);
基本操作
//初始化
void InitList(SqList &L)
{
L=(LNode *)malloc(sizeof(LNode));
L->next=NULL;
return OK;
}
//插入
struct LNode *insertFromHead(struct LNode *head,LNode *p) //头插法处理函数
{
if(p == NULL) head=p; //判断head是否创建有节点
else
{
p->next=head;//将头节点,赋值给新创建的下一个节点
head=p;//将新创建的结点的地址赋给头指针的结点
}
return head;//返回头节点
}
struct LNode *insertFromTail(struct LNode *head,LNode *p) //尾插法处理函数
{
LNode *point;
point=(LNode *)malloc(sizeof(LNode));
point=NULL;
if(head==NULL)
{
head=p;
point=p;
}
else
{
while(point->next!=NULL) point=point->next;//让point指针指向下一个结点,保证它指向链表尾部
point->next=p;//让point指针指向的结点的next成员指向新建结点p
}
return head;
}
//查询
Status Get_LinkList(LinkList H, ElemType key)
{
int index;
LNode *p=(LNode *)malloc(sizeof(LNode));
p=H->next;
index=1;
while(p->next!=NULL and p->data!=key)
{
p=p->next;
index++;
}
if(p->next==NULL) return -1;
else return index;
}
//取值
Status GetElem_L(LinkList L,int i,ElemType &e)
{
LNode *p=(LNode *)malloc(sizeof(LNode));
p=L->next;
int j=1;//初始化
while(p&&j<i)//向后扫描,直到p指向第i个元系
{
p=p->next;
++j;
}
if(!p||j>i) return ERROR;//第i个元素不存在
e=p->data;//取第i个元素
return OK;
}
//删除
Status ListDelete(LinkList &L,char name[])
{
LNode *p,*q;
p=(LNode *)malloc(sizeof(LNode));
q=(LNode *)malloc(sizeof(LNode));
p=L;
if(p->next==NULL) return ERROR;
while(p->next!=NULL&&strcmp(name,p->next->data.name)!=0) p=p->next;
if(p->next==NULL) return ERROR;
q=p->next;//为释放节点做准备
p->next=p->next->next;
free(q);
return OK;
}
拓展
循环链表的合并:
Void merge(LinkList La, LinkList &Lb)
{
p=Lb->next;
Lb->next=La->next;
La->next=Lb->next->next;
free(p);
}
循环链表的插入:
Status ListInsert_DuL(DuLinkList &L,int i,ElemType e)
{
LNode *p=(LNode *)malloc(sizeof(LNode));
p=L->next;
int j=1;
while (p!=L&&j<i) //双向循环链表
{
p=p->next;
j++;
}
if ((p==L&&j<i)||j>i) return ERROR;
s=(DuLNode *)malloc(sizeof(DuLNode));
s->data=e;
s->prior=p->prior;
p->prior->next=s;
s->next=p;
p->prior=s;
return OK;
}
双向链表的存储实现:
typedef struct DuLNode
{
ElemType data;
struct DuLNode *prior;
struct DuLNode *next;
}DuLNode,*DuLinkList
双向链表的删除:
Status ListDelete_DuL(DuLinkList &L,int i,ElemType &e)
{
LNode *p=(LNode *)malloc(sizeof(LNode));
p=L->next;
int j=1;
while (p!=L&&j<i)
{
p=p->next;
j++;
}
if (p==L||j>i) return ERROR;
e=p->data;
p->prior->next=p->next;
p->next->prior=p->prior;
free(p);
return OK;
}
第二部分 栈和队列
顺序栈
存储结构
//方法一
typedef struct
{
SElemType *base;//栈底指针
SElemType *top;//栈顶指针
int stacksize;//栈空间
}Sqstack;
//方法二
#define stacksize 100
typedef struct
{
SElemType base[stacksize];
int top;
}SqStack;
基本操作
//初始化
#define M 10
void InitStack(Sqstack &S)
{
S.base=(SElemType *)malloc(M*sizeof(SElemType));
S.top=S.base;
S.StackSize=M;
}
//入栈
Status Push(Sqstack &S, SElemType x)
{
if(S.top-S.base==S.stacksize)
{
S.base=(SElemType *)realloc(S.base,(S.stacksize+3)*sizeof(SElemType));
S.top=S.base+S.stacksize;
S.stacksize+=3;
}
/*if(S.top-S.base==S.stacksize) return ERROR;*/
*S.top=x;
S.top++;
return OK;
}
//出栈
Status Pop(Sqstack &S, SElemType &e)
{
if(S.base==S.top) return ERROR;
S.top--;
e=*S.top;
return OK;
}
链栈
存储结构
typedef struct StackNode
{
SElemType data;
struct StackNode *next;
}StackNode,*LinkStack;
基本操作
//初始化
void InitStack(LinkStack &S)
{
S=NULL;
}
//入栈
Status Push(LinkStack &S , SElemType e)
{
StackNode*p=(StackNode *)malloc(sizeof(StackNode));//生成新结点p
if(!p) return OVERFLOW;
p->data=e;
p->next=S;
S=p;
return OK;
}
//出栈
Status Pop(LinkStack &S,SElemType &e)
{
if(S==NULL) return ERROR;
e=S->data;
p=S;
S=S->next;
free(p);
return OK;
}
链队列
存储结构
//链队列结构
typedef struct Queue
{
QucuePtr front; //队首指针
QueuePtr rear; //队尾指针
}LinkQueue;
//结点
typedef Struct QNode
{
QElemType data;//元素
Struct QNode *next;//指向下一结点的指针
}QNode, *QueuePtr;
基本操作
//初始化
Status InitQueue(LinkQueue &Q)
{
Q.front=Q.rear=(QNode *)malloc(sizeof(QNode));
if(!Q.front) return OVERFLOW;
Q.front->next=NULL;
return OK;
}
//入队
Status EnLinkQueue(LinkQueue &Q,QElemType e)
{
QNode *newNode=(QNode *)malloc(sizeof(QNode));
if(newNode!=NULL)
{
newNode->data=e;
newNode->next=NULL;
Q.rear->next=newNode;
Q.rear=newNode;
return OK;
}
else return ERROR;
}
//出队
Status DeLinkQueue(LinkQueue &Q,QElemType &e)
{
QNode *p=(QNode *)malloc(sizeof(QNode));
if(Q.front==Q.rear) return ERROR;
p=Q.front->next;
Q.front->next=p->next;
if(Q.rear==p) Q.rear=Q.front;
e=p->data;
free(p);
return OK;
}
//队判空
Status QueueEmpty(LinkQueue Q)
{
if(Q.front==Q.rear) return TRUE;
else return FALSE;
}
循环队列(顺序队列)
存储结构
typedef struct
{
int *base;
int front;//队头
int rear;//队尾
}SqQueue;
基本操作
//初始化
void InitQ(SqQueue &Q,int N)
{
Q.base=(int *)malloc(sizeof(int)*N);
Q.front=Q.rear=0;
}
//入队
Status AddQ(SqQueue &Q, int x)
{
if((Q.rear+1)%N==Q.front) return ERROR;
else
{
Q.base[Q.rear]=x;
Q.rear=(Q.rear+1)%N;
}
return OK;
}
//出队
Status DeleteQ(SqQueue &Q,int &e)
{
if(Q.front==Q.rear)
{
printf("Queue Empty\n");
return ERROR;
}
else
{
e=Q.base[Q.front];
Q.front=(Q.front+1)%N;
return OK;
}
}
第三部分 串、数组和广义表
串
串的运算
#include<string.h>
strcmp(char s1,char s2) //比较
strcpy(char to,char from) //复制
strcat(char to,char from) //连接
strlen(char s) //串长
存储结构
//定长顺序储存
#define MAXLEN 255
typedef struct
{
char ch[MAXLEN+1];//0号单元不用
int length;//串长度
}SString;
//堆式顺序储存
typedef struct
{
char *ch;//若串非空,则按串长分配存储区,否则ch为NULL
int length;//串长度
}HString;
基本操作
//定长顺序存储串的联接
Status Concat(SString &T,SString S1,SString S2)
{
if(S1.length+S2.length<=MAXLEN)//不截断
{
for(i=1;i<=S1.length;i++) T.ch[i]=S1.ch[i];
for(i=1;i<=S2.length;i++) T.ch[i+S1.length]=S2.ch[i];
T.length=S1.length+S2.length;
uncut=TRUE;
}
else //截断
{
for(i=1;i<=S1.length;it+) T.ch[i]=S1.ch[i];
for(i=1;i<=MAXLEN-S1.length;i++) T.ch[i+S1.length]=S2.ch[i];
T.length = MAXLEN;
uncut=FALSE;
}
return uncut;
}
//堆式顺序存储串的联接
Status Concat(HString &T, HString S1, HString S2)//用T返回由S1和S2联接而成的新串
{
if (T.ch) free(T.ch);//释放旧空间
T.ch =(char *)malloc((S1.length+S2.length)*sizeof(char));
if(!T.ch) return OVERFLOW;
T.length = S1.length + S2.length;
for(i=1;i<=S1.length;i++) T.ch[i]=S1.ch[i];
for(i=1;i<=S2.length;i++) T.ch[i+S1.length]=S2.ch[i];
return OK;
}
串的模式匹配算法——BF算法
int Index(Sstring S,Sstring T,int pos)
{
int i=pos,j=1;
while(i<=S.length && j <=T.length)
{
if(S.ch[i]==T.ch[j])
{
++i;
++j;
}
else
{
i=i-j+2;
j=1;
}
if(j>T.length) return i-T.length;
else return 0;
}
}
数组
三元组存储结构
typedef struct
{
int row, col;//行号,列号
ElemType item;//非零元素值
}Triple;
typedef struct
{
Triple data[MAXSIZE];//存储非零元素
int mu, nu, tu;//行数,列数,非零元个数
}TSMatrix;
三元组转置算法
//转置算法1
Status Transpose(TSMatrix A,TSMatrix &B)
{
B.mu=A.nu;
B.nu=A.mu;
B.tu=A.tu;
if(B.tu)
{
int q=0;//q为B.data[]中三元组的下标
for(int col=0;col<A.nu;++col)//扫描A.data[]A.nu遍
for(int p=0;p<A.tu;++p)//p为A.data[]中三元组的下标
{
if (A.data[p].col==col)
{
B.data[q].row=A.data[p].col;
B.data[q].col=A.data[p].row;
B.data[q].item=A.data[p].item;
++q;
}
}
return OK;
}
//转置算法2
Status FasTranspose (TSMatrix A, TSMatrix&B)
{
B.mu=A.nu;
B.nu=A.mu;
B.tu=A.tu;
if(B.tu)
{
for(int col=0;col<A.nu;++col) num[col]=0;
for(int t=0;t<A.tu;++t) ++num[A.data[t].col];
cpot[0]=0;
for(int col=1;col<A.nu;++col) cpot[col]=cpot[col-1]+num[col-1];
for(int p=0;p<A.tu;++p)
{
col=A.data[p].col;
int q=cpot[col];
B.data[q].row=A.data[p].col;
B.data[q].col=A.data[p].row;
B.data[q].item=A.data[p].item;
++cpot[coll];
}
return OK;
}
第五部分 树和二叉树
二叉树
存储结构
//顺序存储
#define MAX_TREE_SIZE 100//二叉树的最大结点数
typedef TElemType SqBiTree[MAX_TREE_SIZE];//0号单元储存根节点
SqBiTree bt;
//二叉链表
typedef struct BiTNode//结点结构
{
TElemTypedata;
struct BiTNode *lchild, *rchild;//左右孩子指针
}BiTNode,*BiTree;
//三叉链表
typedef struct TriTNode
{
TElemType data;
struct TriTNode *lchild,*rchild,*parent;
}TriTNode,*TriTree;
基本操作
//建立
void CreateBiTree(BiTree &T) //先序建立二叉树
{
Elemtype ch;
scanf(&ch);
if(ch=='#') T=NULL;
else
{
T=(BiTree)malloc(sizeof(BiNode));
T->data=ch;
CreateBiTree(T->lchild);
CreateBiTree(T->rchild);
}
}
//先序遍历
void PreOrder(BiTree T)
{
if(T)//递归出口
{
printf(T->data);//访问根节点
PreOrder(T->lchild);//递归遍历左子树
PreOrder(T->rchild);//递归遍历右子树
}
}
//中序遍历
void InOrderTraverse(BiTree T)
{
if(T)
{
InOrderTraverse(T->lchild);
printf(T->data);
InOrderTraverse(T->rchild);
}
}
//后序遍历
void PostOrderTraverse(BiTree T)
{
if(T)
{
PostOrderTraverse(T->lchild);
PostOrderTraverse(T->rchild);
printf(T->data);
}
}
//结点计数
int NodeCount(BiTree T)
{
if(T==NULL) return 0;
else return NodeCount(T->lchild)+NodeCount(T->rchild)+1;
}
//叶子计数
int LeadCount(BiTree T)
{
if(T==NULL) return 0;//如果是空树返回0
if(T->lchild==NULL && T->rchild==NULL) return 1;//如果是叶子结点返回1
else return LeafCount(T->lchild)+LeafCount(T->rchild);
}
//计算深度
int Depth(BiTree T)
{
if(T==NULL) return 0;
else
{
m=Depth(T->lchild);
n=Depth(T->rchild);
if(m>n) return (m+1);
else return (n+1);
}
}
//查找
BiTree search(BiTree T, ElemType x)
{
if(T==NULL) return NULL;
else
{
if(T->data==x) return T;
if(p=search(T->lchild,x)) return p;//在左子树中查找
return search(T->rchild,x);//在右子树中查找
}
}
哈夫曼树(最优二叉树)
哈夫曼算法
typedef struct
{
int weght;
int parent,lchild,rchild;
}HTNode,*HuffmanTree;
void Select(HuffmanTree HT,int len,int &s1,int &s2)
{
int i,min1=32767,min2=32767;
for(i=1;i<=len;i++)
{
if(HT[i].weight<min1&&HT[i].parent==0)
{
s2=s1;
min2=min1;
min1=HT[i].weight;
s1=i;
}
else if(HT[i].weight<min2&&HT[i].parent==0)
{
min2=HT[i].weight;
s2=i;
}
}
}
void CreateHuffmanTree(HuffmanTree & HT,int n)//构造哈夫曼树HT
{
if (n<=1) return;
int m=2*n-1;
HT=(HuffmanTree)malloc((m+1)*sizeof(HTNode));
for(int i=1;i<=n;i++) scanf(HT[i].weight);
for(int i=1;i<=m;++i)
{
HT[i].parent=0;
HT[i].lchild=0;
HT[i].rchild=0;
}
//初始化工作结束,下面开始创建哈夫曼树
for(int i=n+1;i<=m;++i)
{
Select(HT,i-1,s1,s2);
//在HT[1..i-1]选择parent为0且weight
//最小的两个结点,其序号分别为s1和s2
HT[s1].parent=i;
HT[s2].parent=i;
HT[i].lchild=s1;
HT[i].rchild=s2;
HT[i].weight=HT[s1].weight+ HT[s2].weight;
}
}
typedef char **HuffmanCode;
void CreateHuffmanCode(HuffmanTree HT,HuffmanCode &HC,int n)//从叶子到根逆向求每个字符的哈夫曼编码
{
char *cd=(char*)malloc(n*sizeof(char));
cd[n-1]='\0';
HC=(HuffmanCode)malloc((n+1)*sizeof(char*));
for(int i=1;i<=n;++i)
{
int start=n-1;
int c=i;
int f=HT[i].parent;
while(f!=0)
{
--start;
if(HT[f].lchild==c) cd[start]='0';
else cd[start]='1';
c=f;
f=HT[f].parent;
}
HC[i]=(char*)malloc((n-start)*sizeof(char))
strcpy(HC[i],&cd[start]);
}
free(cd);
}
第六部分 图
图的建立
邻接矩阵存储
//用两个数组分别存储顶点表和邻接矩阵
#define MaxInt 32767 //表示极大值,即∞
#define MVNum 100//最大顶点数
typedef char VerTexType;//假设顶点的数据类型为字符型
typedef int ArcType;//假设边的权值类型为整型
typedef struct
{
VerTexType vexs[MVNum];//顶点表
ArcType arcs[MVNum][MVNum];//邻接矩阵
int vexnum,arcnum;//图的当前点数和边数
}AMGraph;
//采用邻接矩阵表示法,创建无向网(UDN算法)
Status CreateUDN(AMGraph &G)
{
scanf(&G.vexnum,&G.arcnum);
getchar()//吃回车
for(int i=0;i<G.vexnum;++i) scanf("%c",&G.vexs[i]);
getchar()//吃回车
for(int i=0;i<G.vexnum;++i) for(int j=0; j<G.vexnum;++j) G.arcs[i][j]=MaxInt;//初始化所有位置为极大值
for(int k=0;k<G.arcnum;++k)//构造邻接矩阵
{
char v1,v2;
int w;
scanf("%c %c %d",&v1,&v2,&w);//输入一条边依附的顶点及权值
getchar()//吃回车
//若无边权,则w=1
int i=LocateVex(G,v1);
int j=LocateVex(G,v2);//确定v1和v2在G中的位置
G.arcs[i][j]=w;//边<v1,v2>的权值置为w
G.arcs[j][i]=G.arcs[i][j];//置<vl, v2>的对称边<v2,v1>的权值为w
}
return OK;
}
int LocateVex(MGraph G,VertexType u)
{
//存在则返回u在顶点表中的下标,否则返回-1
for(int i=0;i<G.vexnum;++i) if(u==G.vexs[i]) return i;
return -1;
}
邻接表存储
#define MVNum 100
typedef struct ArcNode
{
int adjvex;//该边所指向的顶点的位置
struct ArcNode *nextarc; //指向下一条边的指针
InfoType info;//该边相关信息
}ArcNode;
typedef struct VNode
{
VerTexType data;//顶点信息
ArcNode *firstarc;//指向第一条依附该顶点的边的指针
}VNode,AdjList[MVNum]//AdjList表示邻接表类型
typedef struct
{
AdjList vertices; //邻接表
int vexnum,arcnum;//图的当前顶点数和边数
}ALGraph;
Status CreateUDG(ALGraph &G)//采用邻接表表示法,创建无向图G
{
scanf("%d%d",&G.vexnum,&G.arcnum);//输入总顶点数,总边数
for(int i=0;i<G.vexnum;++i)//输入各点,构造表头结点表
{
scanf("%d",&G.vertices[i].data);//输入顶点值
G.vertices[i].firstarc=NULL;//初始化表头结点的指针域为NULL
}
for(int k=0;k<G.arcnum;++k)//输入各边,构造邻接表
{
int v1,v2;
scanf("%d %d",&v1,&v2);//输入一条边依附的两个顶点
int i=LocateVex(G,v1);
int j=LocateVex(G,v2);
ArcNode *p1=(ArcNode *)malloc(sizeof(ArcNode));
p1->adjvex=j;//邻接点序号为j
p1->nextarc= G.vertices[i].firstarc;
G.vertices[i].firstarc=p1;//将新结点*p1插入顶点vi的边表头部
ArcNode *p2=(ArcNode*)malloc(sizeof(ArcNode));
p2->adjvex=i;//邻接点序号为i
p2->nextarc=G.vertices[j].firstarc;
G.vertices[j].firstarc=p2;//将新结点*p2插入顶点vj的边表头部
}
return OK;
}
图的遍历
深度优先遍历算法
//邻接矩阵
int visited[MVNum];
void DFSTraver(AMGraph G)//非连通图的遍历
{
//初始化顶点访问标志数组
for(int i=0; i<G.vexnum;i++) visited[i]=0;
//反复调用DFS过程,遍历图
for(int i=0; i<G.vexnum;i++) if(visited[i]==0) DFS(G,i);
}
void DFS(AMGraph G,int v)//图G为邻接矩阵类型
{
printf("%c ",G.vexs[v]);
visited[v]=1;//访问第v个顶点
for(int w=0; w< G.vexnum; w++)//依次检查邻接矩阵v所在的行
if((G.arcs[v][w]!=0)&&(!visited[w])) DFS(G, w);//w是v的邻接点,如果w未访问,则递归调用DFS
}//时间复杂度为O(n²)
//邻接表
void DFS(ALGraph G,int v)//图G为邻接表类型
{
printf("%d ",G.vertices[v].data);
visited[v]=1;//访问第v个顶点
ArcNode *p=(ArcNode *)malloc(sizeof(ArcNode));
p=G.vertices[v].firstarc;//p指向v的边链表的第一个边结点
ArcNode *w=(ArcNode *)malloc(sizeof(ArcNode));
while(p!=NULL)//边结点非空
{
w=p->adjvex;//表示w是v的邻接点
if(!visited[w]) DFS(G, w);//如果w未访问,则递归调用DFS
p=p->nextarc;//p指向下一个边结点
}
}//时间复杂度O(n+e)
广度优先遍历算法
//邻接矩阵
void BFSTraverse(Graph G)//非连通图
{
for(int v=0;v<G.vexnum;++v) visited[v]=0;//初始化访问标志
for(int v=0;v<G.vexnum;++v) if(!visited[v]) BFS(G,v);
}
void BFS(Graph G,int v)//按广度优先非递归遍历连通图G
{
printf(v);
visited[v]=1;//访问第v个顶点
InitQueue(Q);//辅助队列Q初始化,置空
EnQueue(Q,v);//v进队
while(!QueueEmpty(Q))//队列非空
{
DeQueue(Q,u);//队头元素出队并置为u
for(int w=FirstAdjVex(G,u);w>=0;w=NextAdjVex(G,u,w))
{
if(!visited[w])//w为u的尚未访问的邻接顶点
{
printf(w);
visited[w]= 1;
EnQueue(Q,w); //w进队
}
}
}
}
最小生成树构造算法
Prim算法
//记录从顶点集U到V-U的代价最小的边的辅助数组定义
struct{
VertexType adjvex;//V-U中的某个点到U中最小边的对应邻接点位置
int lowcost;//对应的最小边的权值
}closedge[MAX_VERTEX_NUM];
int Min(AMGraph G)
{
int i;
int index = -1;
int min = MaxInt;
for(i = 0 ; i < G.vexnum ; ++i){
if(min > closedge[i].lowcost && closedge[i].lowcost != 0){
min = closedge[i].lowcost;
index = i;
}
}
return index;
}
void MiniSpanTree_Prim(AMGraph G, char u)
{
int k , j , i;
char u0 , v0;
k =LocateVex(G, u);//辅助数组初始化
for(j = 0; j < G.vexnum; ++j)
{
if(j != k)//起始点V1并入U(={V1})
{
closedge[j].adjvex = u;
closedge[j].lowcost = G.arcs[k][j];
}
}
for(i = 1; i < G.vexnum; ++i)//选择其余顶点的G.vexnum-1个顶点
{
k = Min(G);//求下一个顶点:第k顶点
u0 = closedge[k].adjvex;
v0 = G.vexs[k];
printf("%d %d\n",u0,v0);//输出生成树的边
closedge[k].lowcost = 0; //第k顶点并入U,考虑加入顶点K后closedge数组的变化
for(j = 0; j < G.vexnum; ++j) //重新选择最小边
if(G.arcs[k][j] < closedge[j].lowcost)
{
closedge[j].adjvex = G.vexs[k];
closedge[j].lowcost = G.arcs[k][j];
}
}
}
Kruskal算法
typedef struct{
char vexs[MVNum];
int arcs[MVNum][MVNum];
int vexnum,arcnum;
}AMGraph;
struct Evode{
char Head;
char Tail;
int lowcost;
}Edge[(MVNum * (MVNum - 1)) / 2];
int Vexset[MVNum];
int LocateVex(AMGraph G , char v){
for(int i = 0; i < G.vexnum; ++i)
if(G.vexs[i] == v)
return i;
return -1;
}
void CreateUDN(AMGraph &G){
int i , j , k;
char c;
scanf("%d %d",&G.vexnum,&G.arcnum);
getchar();
for(i = 0; i < G.vexnum; ++i){
G.vexs[i]=getchar();
}
getchar();
for(i = 0; i < G.vexnum; ++i)
for(j = 0; j < G.vexnum; ++j)
G.arcs[i][j] = MaxInt;
for(k = 0; k < G.arcnum;++k){
char v1 , v2;
int w;
scanf("%c %c %d",&v1,&v2,&w);
getchar();
i = LocateVex(G, v1); j = LocateVex(G, v2);
G.arcs[i][j] = w;
G.arcs[j][i] = G.arcs[i][j];
Edge[k].lowcost = w;
Edge[k].Head = v1;
Edge[k].Tail =v2;
}
}
void Sort(AMGraph G){
int m = G.arcnum - 2;
int flag = 1;
while((m > 0) && flag == 1){
flag = 0;
for(int j = 0 ; j <= m ; j++){
if(Edge[j].lowcost > Edge[j+ 1].lowcost){
flag = 1;
struct Evode temp=Edge[j];
Edge[j]=Edge[j + 1];
Edge[j + 1]=temp;
}
}
--m;
}
}
void MiniSpanTree_Kruskal(AMGraph G){
int i , j , v1 , v2 , vs1 , vs2;
Sort(G);
for(i = 0; i < G.vexnum; ++i)
Vexset[i] = i;
for(i = 0; i < G.arcnum; ++i){
v1 =LocateVex(G, Edge[i].Head);
v2 =LocateVex(G, Edge[i].Tail);
vs1 = Vexset[v1];
vs2 = Vexset[v2];
if(vs1 != vs2){
printf("%c->%c\n",Edge[i].Head ,Edge[i].Tail);
for(j = 0; j < G.vexnum; ++j)
if(Vexset[j] == vs2) Vexset[j] = vs1;
}
}
}
最短路径算法
Dijkstra算法
void Dijkstra(Graph G, int v)
{
//初始化
int n = G.vexnum;//n为图的顶点个数
for (int i = 0; i < n; i++)
{
S[i] = false;
D[i] = G.Edge[v][i];
if (D[i] < INF)Pr[i] = v; //v与i连接,v为前驱
else Pr[i] = -1;
}
S[v] = true;
D[v] = 0;
//初始化结束,求最短路径,并加入S集
for (int i = 1; i < n; i++)
{
int min = INF;
int temp;
for (int w = 0; w < n; w++)
if (!S[w] && D[w] < min) //某点temp未加入s集,且为当前最短路径
{
temp = w;
min = D[w];
}
S[temp] = true;
//更新从源点出发至其余点的最短路径 通过temp
for (int w = 0; w < n; w++)
{
if (!S[w] && D[temp] + G.Edge[temp][w] < D[w])
{
D[w] = D[temp] + G.Edge[temp][w];
Pr[w] = temp;
}
}
}
}
拓补排序算法
#include <stdio.h>
//#include "conio.h"
#include <stdlib.h>
#include <string.h>
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define OVERFLOW -1
#define MAXSIZE 30
#define VERTEX_MAX 30 //最大顶点数
#define VEX_NUM 10
typedef int Status;
typedef char Vextype[20]; //顶点类型
typedef int ElemType;
typedef struct //定义顺序栈结构
{
ElemType elem[MAXSIZE];
int top;
}SeqStack;
typedef struct node //边结点定义
{
int adjvex; //邻接点域
struct node *next; //指向下一个边结点的指针域
}EdgeNode;
typedef struct vnode //表头结点定义
{
int Indegree; //顶点入度域
Vextype vertex; //顶点信息
EdgeNode *firstedge;
}VertexNode;
typedef struct //图的邻接表存储
{
VertexNode adjlist[VERTEX_MAX];
int n,e; //顶点数和边数
}ALGraph;
void InitStack_Sq(SeqStack &s) //初始化栈操作
{
s.top=-1;
}
int Empty_Sq(SeqStack s) //判栈是否为空
{
if(s.top==-1) return 1;
else return 0;
}
Status Push_SeqStack(SeqStack &s, ElemType x)
{
if(s.top==MAXSIZE-1) return OVERFLOW; //栈满不能入栈
else
{
s.top++;
s.elem[s.top]=x ;
return OK;
}
}
Status Pop_SeqStack(SeqStack &s,ElemType &y)
{
if(Empty_Sq(s)) return OVERFLOW; //栈空不能出栈
else
{
y=s.elem[s.top];
s.top--;
return OK;
}//栈顶元素存入*y,返回
}
void CreateALGraph(ALGraph &G) //创建有向图的邻接表
{
int i,v,w;
int Indegree[VERTEX_MAX]={0};
EdgeNode *s;
scanf("%d,%d",&(G.n),&(G.e)); //输入顶点数n和弧数m
for (i=0;i<G.n;i++)
{
scanf("%s",G.adjlist[i].vertex);
G.adjlist[i].firstedge=NULL;
}
for(w=0;w<G.e;w++) //建立边表
{
scanf("%d,%d",&i,&v);
s=(EdgeNode*)malloc(sizeof(EdgeNode));
s->adjvex=v;
Indegree[v]++; //统计各顶点的入度
s->next=G.adjlist[i].firstedge; //前插方法
G.adjlist[i].firstedge=s;
}
for(i=0;i<G.n;i++) G.adjlist[i].Indegree=Indegree[i];
}
void topsort( ALGraph &G)
{
int i,v,w;
int cnt=0;//计数器初始化为0
EdgeNode *ptr;
SeqStack st;
InitStack_Sq(st);
for(i=0;i<G.n;i++) if(G.adjlist[i].Indegree==0) Push_SeqStack(st,i);
while(!Empty_Sq(st))
{
Pop_SeqStack(st, v); //出栈一次,出栈元素放在v中
printf("%s ",G.adjlist[v].vertex);
cnt++;
ptr=G.adjlist[v].firstedge; //ptr指向第一个边结点
while(ptr!=NULL) //只要有边
{
w=ptr->adjvex;
G.adjlist[w].Indegree--;
if(G.adjlist[w].Indegree==0) Push_SeqStack(st,w);
ptr=ptr->next;
}
}
if(cnt<G.n) printf("后续无法输出!\n");
}
int main()
{
ALGraph g;
CreateALGraph(g);
printf("拓扑序列为:");
topsort(g);
return 0;
}
第七部分 查找
线性表的查找
顺序查找(线性查找)
/*不用监视哨法,在顺序表中查找关键字等于key的元素*/
int SeqSearch (sSTable ST,KeyType key)
{
int i=ST.length;
while (i>=1&&ST.R[i].key!=key) i--;
return i;
}
/*监视哨法*/
int Search_Seq(SSTable ST,KeyType key)
{
ST.R[0].key=key;
for(i=ST.length;ST.R[i].key!=key;--i);
return i;
}
折半查找(二分查找、对分查找)
//非递归算法
int Search_Bin(SSTable ST,KeyType key)//若找到,则函数值为该元素在表中的位置,否则为0
{
low=1;
high=ST.length;
while(low<=high)
{
mid=(low+high)/2;
if(key==ST.R[mid].key) return mid;
else if(key<ST.R[mid].key) high=mid-1;//前一子表查找
else low=mid+1;//后一子表查找
}
return 0;//表中不存在待查元素
}
//递归算法
int Search_Bin (SSTable ST,keyType key,int low,int high)
{
if(low>high) return 0; //查找不到时返回0
mid=(low+high)/2;
if(key=-ST.elem[mid].key) return mid;//查找成功
else if(key<ST.elem[mid].key) return Search_Bin (ST,key,low,mid-1);//递归
else return Search_ Bin(ST,key,mid+1,high);//递归
}
树的查找
二叉排序树的操作
//查找
BSTree SearchBST(BSTree T,KeyType key)
{
if(!T || key=T->data.key) 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)
{
S= (BSTNode *)malloc(sizeof(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);
}
哈希(散列/杂凑)表的查找
除留余数法 Hash(key)=key mod p(p是一个整数)
#define NULLKEY 0
typedef struct
{
int key;
}HashTable[m];
void CreateHash(HashTable HT[],int key)
{
int H0=key%13;
int Hi;
if (HT[H0].key==NULLKEY)
{
HT[H0].key=key;
return;
}
else
{
for(int i=1;i<m;++i)
{
Hi=(H0+i)%m;
if (HT[Hi].key==NULLKEY)
{
HT[Hi].key=key;
return;
}
}
}
}
int SearchHash(HashTable HT,int key)
{
int H0=H(key);//H(key)为哈希函数
if(HT[H0].key==NULLKEY) return -1;
else if(HT[H0].key==key) return H0;
else
{
for(int i=1;i<m;++i)
{
int Hi=(H0+i)%m;//线性探测
if(HT[Hi].key==NULLKEY) return -1;
else if(HT[Hi].key==key) return Hi ;
}
return -1;
}
}
第八部分 排序
直接插入排序
typedef struct
{
ElemType r[MAXSIZE+1];
int length;
}SqList;
void InsertSort (SqList &L)
{
int i,j;
for(i=2;i<=L.length; ++i)
{
if(L.r[i].key<L.r[i-1].key)//注只有当前元素比前一个元素的值小的时候才需要进行移动
{
L.r[0]=L.r[i];//设置“监视哨”同时暂存插入元素值
L.r[i]=L.r[i-1];
for(j=i-2;L.r[0].key<L.r[j].key;j--) L.r[j+1]=L.r[i];//从后向前比较直到发现不比L.r[0]大的元素为止
L.r[j+1]=L.r[0];
}
}
}
冒泡排序
void BubbleSort(SqList &L)
{
for (int i=1;i<L.length;i++)
{
int Exchange=0;
for (int j=1;j<=L.length-i;j++)
{
if (L.r[j+1]<L.r[j])
{
int temp=L.r[j+1]
L.r[j+1]=L.r[i];
L.r[i]=temp;
Exchange=1;
}
}
if(Exchange==0) return;
}
}
快速排序
void QSort (Sqlist &L,int low,int high)
{
if (low<high)
{
int pivotloc=Partition(L,low,high);
QSort(L,low,pivotloc-1);
QSort(L, pivotloc+1, high);
}
}
int partition(sqlist &L,int low,int high) 对从下标low到high的顺序表做一趟快速排序
{
int pivotkey=L.r[low];
while(low<high)//将低下标设置为枢轴
{
while(low<high&&L.r[high]>=pivotkey) --high;
L.r[low]=L.r[high];
while(low<high&&L.r[low]<=pivotkey) ++low;
L.r[high]=L.r[low];
}
L.r[low]=pivotkey;
return low;//返回值是枢轴的排序位置
}
选择排序
void SelectSort (SqList &L)//对顺序表L作简单选择排序
{
for(int i=1;i<L.length;++i)//选择第i小的记录,并交换到位
{
//在L.r[i..L. 1ength]中选择key最小的记录
int min=i ;
for(int j=i+1;j<=L.1ength;j++) if(L.r[j]<L.r[min]) min=j;
if(i!=min)//与第i个记录交换
{
int temp=L.r[i];
L[i]=L.r[min];
L.r[min]=temp;
}
}
}
堆排序
void Sift(int R[],int low,int high)
{
int i=low,j=2*i;
int temp=R[i];
while (j<=high)
{
if (j<high && R[j]<R[j+1])
j++;
if (temp<R[j])
{
R[i]=R[j];
i=j;
j=2*i;
}
else break;
}
R[i]=temp;
}
void HeapSort(int R[],int n)
{
int i,j;
int temp;
for(i=n/2;i>=1;i--)
Sift(R,i,n);
for(i=n;i>=2;i--)
{
swap(R[1],R[i]); //将R[1]与R[i]进行交换。
Sift(R,1,i-1);
}
}