数据结构
⭐ 和小伙伴们分享,交流,做一名技术极客。🙂
⭐ 不断添加:有趣的知识 😄
⭐ 特别感谢:王道考研(我认识你,但是你不认识我)😁
⭐ 用最少的文字,表达最清楚的含义 🙃
1 线性表的定义
1 顺序表的实现——静态分配:初始化
#define MaxSize 10
typedef struct{
ElemType data[MaxSize];
int length;
}SqList;
void InitList(SqList &L){
for(int i=0;i<MaxSize;i++)
L.data[i]=0;
L.length=0;
}
2顺序表的实现——动态分配:初始化
#define InitSize 10
typedef struct{
ElemType *data;
int MaxSize;
int length;
}SeqList;
void InitList(SeqList &L){
L.data=(int*)malloc(InitSize*sizeof(int));
L.length=0;
L.MaxSize=InitSize;
}
void IncreaseSize(SeqList &L,int len){
int *p=L.data;
L.data=(int*)malloc((L.MaxSize+len)*sizeof(int));
for(int i=0;i<L.length;i++){
L.data[i]=p[i];
}
L.MaxSize=L.MaxSize+len;
free(p);
}
3.顺序表的基本操作——静态分配:插入
bool ListInsert(SqList &L,int i,int e){
if(i<1||i>L.length+1)
return false;
if(L.length>=MaxSize)
return false;
for(int j=L.length;j>=i;j--)
L.data[j]=L.data[j-1];
L.data[i-1]=e;
L.length++;
return true;
}
4. 顺序表的基本操作——静态分配:按位序删除
bool ListDelete(SqList &L,int i,int &e){
if(i<1||i>L.length)
return false;
e=L.data[i-1];
for(int j=i;j<L.length;j++)
L.data[j-1]=L.data[j];
L.length--;
return true;
}
5.顺序表的按位查找
ElemType GetElem(SqList L,int i){
return L.data[i-1];
}
6. 顺序表按值查找
int LocatELem(SeqList L,ElemType e){
for(int i=0;i<L.length;i++){
if(L.data[i]==e)
return i+1;
}
return 0;
}
2. 线性表的链式表示
struct LNode{
ElemType data;
struct LNode* next;
}LNode,*LinkList;
- 小坑:
- 强调返回一个结点:LNode*
- 强调这是一个单链表:LinkList
LNode* GetElem(LinkList L,int i){
int j=1;
LNode *p=L->next;
if(i==0)
return L;
if(i<1)
return NULL;
while(p!=NULL && j<i){
p=p->next;
j++;
}
return p;
}
2.1 不带头结点的单链表:初始化+判空
bool InitList(LinkList &L){
L=NULL;
return true;
}
bool Empty(LinkList L){
if(L==NULL)
return true;
else
return false;
}
2.2 按位序插入——带头结点
bool ListInsert(LinkList &L,int i,ElemType e){
if(i<1)
return false;
LNode *p;
int j=0;
p=L;
while(p!=NULL && j<i-1){
p=p->next;
j++;
}
if(p==NULL)
return false;
LNode *s=(LNode*)malloc(sizeof(LNode));
s->data=e;
s->next=p->next;
p->next=s;
return true;
}
2.3 按位序插入——不带头结点
bool ListInsert(LinkList& L,int i,ElemType e){
if(i<1)
return false;
if(i==1){
LNode* s=(LNode*)malloc(sizeof(LNode));
s->data=e;
s->next=L;
L=s;
return true;
}
LNode*p;
int j=1;
p=L;
while(p!=NULL && j=i-1){
p=p->next;
j++;
}
if(p==NULL)
return false;
LNode *s=(LNode*)malloc(sizeof(LNode));
s->data=e;
s->next=p->next;
p->next=s;
return true;
}
2.4 指定结点——后插操作
bool InsertNextNode(LNode*p,ElemType e){
if(p==NULL)
return false;
LNode*s=(LNode*)malloc(sizeof(LNode));
if(s==NULL)
return false;
s->data=e;
s->next=p->next;
p->next=s;
return true;
}
2.4.1 模块化
bool ListInsert(LinkList &L,int i,ElemType e){
if(i<1)
return false;
LNode*p;
int j=0;
p=L;
while(p!=NULL && j<i-1){
p=p->next;
j++;
}
return InsertNextNode(p,e);
}
2.5 指定结点——前插操作
bool InsertPriorNode(LNode*p,ElemType e){
if(p==NULL)
return false;
LNode* s=(LNode*)malloc(sizeof(LNode));
if(s==NULL)
return false;
s->next=p->next;
p->next=s;
s->data=p->data;
p->data=e;
return true;
}
2.6 按位序删除——带头结点
bool ListDelete(LinkList &L,int i,ElemType &e){
if(i<1)
return false;
LNode *p;
int j=0;
p=L;
while(p!=NULL && j<i-1){
p=p->next;
j++;
}
if(p==NULL)
return false;
if(p->next==NULL)
return false;
LNode* q=p->next;
e=q->data;
p->next=q->next;
free(q);
return true;
}
2.7 指定结点——删除——带头结点
bool DeleteNode(LNode *p){
if(p==NULL)
return false;
LNode *q=p->next;
p->data=p->next->data;
p->next=q->next;
free(q);
return true;
}
2.8 按位序查找
LNode *GetElem(LinkList L,int i){
if(i<0)
return NULL;
LNode *p;
int j=0;
p=L;
while(p!=NULL && j<i){
p=p->next;
j++;
}
return p;
}
2.8.1 模块化
bool ListInsert(LinkList &L,int i,ELemType e){
if(i<1)
return false;
LNode*p=GetElem(L,i-1);
return InsertNextNode(p,e);
}
bool ListDelete(LinkList &L,int i,ElemType &e){
LNode *p=GetElem(L,i-1);
}
2.9 按指定查找
LNode * LocateElem(LinkList L,ElemType e){
LNode* p=L->next;
while(p!=NULL && P->data!=e){
p=p->next;
}
return p;
}
3.双链表
3.1 双链表 V.S 单链表
typedef struct DNode{
ElemType data;
struct DNode *prior,*next;
}DNode,*DLinklist;
3.2 插入
bool InsertNextDNode(DNode *p,DNode *s){
if(p==NULL || s==NULL)
return false;
s->next=p->next;
if(p->next!=NULL)
p->next->prior=s;
s->prior=p;
p->next=s;
return true;
}
3.3 删除
bool DeleteNextDNode(DNode *p){
if(p==NULL) return false;
DNode *q=p->next;
if(q==NULL) return false;
p->next=q->next;
if(q->next!=NULL)
q->next->prior=p;
free(q);
return true;
}
3.3.1 销毁
void DestoryList(DLinklist &L){
while(L->next!=NULL)
DeleteNextDNode(L);
free(L);
L=NULL;
}
4.循环链表
4.1 循环单链表
typedef struct LNode{
ElemType data;
struct LNode *next;
}LNode,*LinkList;
bool InitList(LinkList &L){
L=(LNode*)malloc(sizeof(LNode));
if(L==NULL)
return false;
L->next=L;
return true;
}
bool Empty(LinkList L){
if(L->next==L)
return true;
else
return false;
}
4.2 循环双链表
typedef struct DNode{
ElemType data;
struct DNode* prior,*next;
}DNode,*DLinkList;
1.初始化
bool InitLinkList(DLinkList &L){
L=(DNode*)malloc(sizeof(DNode));
if(L==NULL)
return false;
L->prior=L;
L->next=L;
return true;
}
2. 判空
bool Empty(DLinkList L){
if(L->next==L)
return true;
else
return false;
}
3.插入
bool InsertNextDNode(DNode *p,DNode *s){
s->next=p->next;
p->next->prior=s;
s->prior=p;
p->next=s;
}
4.删除
p->next=q->next;
q->next->prior=p;
free(q);
5. 顺序栈的定义
1.顺序栈的实现
#define MaxSize 10
typedef struct{
ElemType data[MaxSize];
int top;
}SqStack;
2.顺序栈——判空——top=-1
bool StackEmpty(SqStack S){
if(S.top==-1)
return true;
else
return false;
}
3.顺序栈——进栈——top=-1
bool Push(SqStack &S,ElemType x){
if(S.top==MaxSize-1)
return false;
S.top=S.top+1;
S.data[S.top]=x;
return true;
}
4.顺序栈——出栈——top=-1
bool Pop(SqStack &S,ElemType &x){
if(S.top==-1)
return false;
x=S.data[S.top];
S.top=S.top-1;
return true;
}
4.1 读栈顶元素——top=-1
bool GetTop(SqStack S,ElemType &x){
if(S.top==-1)
return false;
x=S.data[S.top];
return true;
}
5.顺序栈——判空——top=0
bool StackEmpty(SqStack S){
if(S.top==0)
return true;
else
return false;
}
6.顺序栈——进栈——top=0
bool Push(SqStack &S,ElemType x){
if(S.top==MaxSize)
return false;
S.data[S.top]=x;
S.top=S.top+1;
return true;
}
6. 栈的链式存储结构
1.链栈的定义
typedef struct Linknode{
ElemType data;
struct Linknode *next;
}*LiStack;
2. 链栈的初始化——不带头结点
bool InitStack(LiStack S){
S=NULL;
return true;
}
3.链栈的判空——不带头结点
bool Empty(LiStack S){
return S==NULL;
}
4. 按值进栈(插入)——不带头结点
bool InsertNode(LiStack& L,ElemType x){
if(L==NULL)
return false;
(LiStack*)p=(LiStack*)malloc(sizeof(LiStack));
if(p==NULL)
return false;
p->data=x;
p->next=s->next;//p->next=top
s=p; //top=p;
return true;
}
5. 按值出栈(删除)——不带头结点
bool DeleteNode(LiStack&S){
if(s==NULL){
return false;
}
LiStack* q=S->next;
S->next=q->next;
free(q);
return true;
}
6. 获取栈顶元素
7.顺序队列的定义
1.顺序队列的实现
#define MaxSize 10
typedef struct{
ElemType data[MaxSize];
int front,rear;
}SqQueue;
2. 顺序队列——初始化
void InitQueue(SqQueue &Q){
Q.rear=Q.front=0;
}
3. 顺序队列——判空
bool QueueEmpty(SqQueue Q){
if(Q.rear==Q.front)
return true;
else
return false;
}
4. 顺序队列—>循环队列—入队
bool EnQueue(SqQueue &Q,ElemType x){
if((Q.rear+1)%MaxSize==Q.front)//判断队列满的方式1
return false;
Q.data[Q.rear]=x;
Q.rear=(Q.rear+1)%MaxSize;
return true;
}
5.顺序队列—>循环队列—出队
bool DeQueue(SqQueue &Q,ElemType &x){
if(Q.rear==Q.front)
return false;
x=Q.data[Q.front];
Q.front=(Q.front+1)%MaxSize;
return true;
}
6.获得队头元素的值,用x返回
bool GetHead(SqQueue Q,ElemType &x){
if(Q.rear==Q.front)
return false;
x=Q.data[Q.front];
return true;
}
7. 判断队列已满/已空
-
#define MaxSize 10 typedef struct{ ElemType data[MaxSize]; int front ,rear; int size; }SqQueue; //初始化 rear=front=0; size=0; //队满 size==MaxSize; //队空 size==0;
-
#define MaxSize 10 typedef struct{ ElemType data[MaxSize]; int front ,rear; int tag; }SqQueue; //初始化 rear=front=0; tag=0; //队满 front==rear&&tag==1; //队空 front==rear&&tag==0;
8. 队列的链式实现
1.链式队列—初始化—带头结点
typedef struct LinkNode{
ElemType data;
struct LinkNode *next;
}LinkNode;
typedef struct{
LinkNode*front,*rear;
}LinkQueue;
void InitQueue(LinkQueue &Q){
Q.front=Q.rear=(LinkNode*)malloc(sizeof(LinkNode));
Q.front->next=NULL;
}
2.链式队列—判空—带头结点
bool IsEmpty(LinkQueue Q){
if(Q.front == Q.rear)
return true;
else
return false;
}
3. 初始化——不带头结点
void InitQueue(LinkQueue &Q){
Q.front = NULL;
Q.rear=NULL;
}
4.判空—不带头结点
bool IsEmpty(LinkQueue Q){
if(Q.front==NULL)
return true;
else
return false;
}
5. 入队——带头结点
void EnQueue(LinkQueue &Q,ElemType x){
LinkNode *s=(LinkNode*)malloc(sizeof(LinkNode));
s->data=x;
s->next=NULL;
Q.rear->next=s;
Q.rear=s;
}
6. 入队——不带头结点
void EnQueue(LinkQueue &Q,ElemType x){
LinkNode *s=(LinkNode *)malloc(sizeof(LinkNode));
s->data=x;
s->next=NULL;
if(Q.front==NULL){
Q.front=s;
Q.rear=s;
}else{
Q.rear->next=s;
Q.rear=s;
}
}
7. 出队——带头结点
bool DeQueue(LinkQueue &Q,ElemType &x){
if(Q.front == Q.rear)
return false;
LinkNode *p=Q.front->next;
x=p->data;
Q.front->next=p->next;
if(Q.rear==p)
Q.rear=Q.front;
free(p);
return true;
}
8.出队——不带头结点
bool DeQueue(LinkQueue &Q,ElemType &x){
if(Q.front==NULL)
return false;
LinkNode *p=Q.front;
x=p->data;
Q.front=p->next;
if(Q.rear==p){
Q.front=NULL;
Q.rear=NULL;
}
free(p);
return true;
}
9.双端队列
10.特殊矩阵的压缩存储
9.串的顺序存储和链式存储
1.串的顺序存储——静态数组实现(定长顺序存储)
#define MAXLEN 25
typedef struct{
char ch[MAXLEN];
int length;
}SString;
2. 串的顺序存储——动态数组实现(堆分配存储)
typedef struct{
char *ch;
int length;
}HString;
HString S;
S.ch=(char*)malloc(MAXLEN*sizeof(char));
S.length=0;
3. 串的链式存储
typedef struct StringNode{
char ch;
struct StringNode * next;
}StringNode,*String;
typedef struct StringNode{
char ch[4];
struct StringNode *next;
}StringNode,*String;
4. 基本操作的实现——求子串
- 用Sub返回串S的第pos个字符起长度为len的子串
#define MAXLEN 25
typedef struct{
char ch[MAXLEN];
int length;
}SString;
bool SubString(SString &Sub,SString S,int pos,int len){
if(pos+len-1>S.length)
return false;
for(int i=pos;i<pos+len;i++)
Sub.ch[i-pos+1]=S.ch[i];
Sub.length=len;
return true;
}
5. 基本操作的实现——比较操作
//比较操作。若S>T ,则返回值>0;若S=T,则返回值=0;若S<T,则返回值<0
int StrCompare(SString S,SString T){
for(int i=1;i<=S.length&&i<=T.length;i++){
if(S.ch[i]!=T.ch[i])
return S.ch[i]-T.ch[i];
}
return S.length-T.length;
}
6. 基本操作的实现——定位操作
int Index(SString S,SString T){
int i=1,n=StrLength(S),m=StrLength(T);
SString sub;
while(i<=n-m+1){
SubString(sub,S,i,m);
if(StrCompare(sub,T)!=0)++i;
else return i;
}
return 0;
}
7. 朴素模式匹配算法
int Index(SString S,SString T){
int k=1;
int i=k,j=1;
while(i<=S.length&&j<=T.length){
if(S.ch[i]==T.ch[j]){
++i;
++j;
}else{
k++;
i=k;
j=1;
}
}
if(j>T.length)
return k;
else
return 0;
}
8. KMP算法
int Index_KMP(SString S,SString T,int next[]){
int i=1,j=1;
int next[T.length+1];
get_next(T,next);
while(i<=S.length&&j<=T.length){
if(j==0||S.ch[i]==T.ch[j]){
++i;
++j;
}
else
j=next[j];
}
if(j>T.length)
return i-T.length;
else
return 0;
}
9. 求模式串T的next数组
void get_next(SString T,int next[]){
int i=1,j=0;
next[1]=0;
while(i<T.length){
if(j==0||T.ch[i]==T.ch[j]){
++i;++j;
next[i]=j;
}
else
j=next[j];
}
}
10.nextval数组
nextval[1]=0;
for(int j=2 ;j<=T.length;j++){
if(T.ch[next[j]]==T.ch[j])
nextval[j]=nextval[next[j]];
else
nextval[j]=next[j];
}
10.二叉树的存储
1. 二叉树的顺序存储
#define MaxSize 100
struct TreeNode{
ElemType value;
bool isEmpty;
};
TreeNode t[MaxSize];
for(int i=0;i<MaxSize;i++){
t[i].isEmpty=true;
}
2. 二叉树的链式存储
typedef struct BiTNode{
ElemType data;
struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;
//定义一棵空树
BiTree root=NULL;
//插入根节点
root=(BiTree)malloc(sizeof(BiTNode));
root->data={1};
root->lchild=NULL;
root->rchild=NULL;
//插入新结点
BiTNode *p =(BiTNode*)malloc(sizeof(BiTNode));
p->data={2};
p->lchild=NULL;
P->rchild=NULL;
root->lchild=p;
3. 二叉树的遍历—先序遍历
typedef struct BiTNode{
ElemType data;
struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;
void PreOrder(BiTree T){
if(T!=NULL){
visit(T);
PreOrder(T->lchild);
PreOrder(T->rchild);
}
}
4.二叉树的遍历—中序遍历
void InOrder(BiTree T){
if(T!=NULL){
InOrder(T->lchild);
visit(T);
InOrder(T->rchild);
}
}
5. 二叉树的遍历—后序遍历
void PostOrder(BiTree T){
if(T!=NULL){
PostOrder(T->lchild);
PostOrder(T->rchild);
visit(T);
}
}
6.应用:树的深度
int treeDepth(BiTree T){
if(T==NULL){
return 0;
}
else{
int l=treeDepth(T->lchild);
int r=treeDepth(T->rchild);
return l>r?l+1:r+1;
}
}
7.层序遍历——链式队列
void LevelOrder(BiTree T){
LinkQueue Q;
InitQueue(Q); //初始化辅助队列
BiTree p;
EnQueue(Q,T);
while(!IsEmpty(Q)){
DeQueue(Q,p);
visit(p);
if(p->lchild!=NULL)
EnQueue(Q,p->lchild);
if(p->rchild!=NULL)
EnQueue(Q,p->rchild);
}
}
typedef struct BiTNode{ //二叉树的结点(链式存储)
char data;
struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;
typedef struct LinkNode{ //链式队列结点
BiTNode *data;
struct LinkNode*next;
}LinkNode;
typedef struct{
LinkNode *front,*rear; //队头队尾
}LinkQueue;
8. 线索二叉树的存储结构
typedef struct BiTNode{
ElemType data;
struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;
typedef struct ThreadNode{
ElemType data;
struct ThreadNode *lchild,*rchild;
int ltag,rtag;
} ThreadNode,*ThreadTree;
9.找中序前驱
9. 中序线索化
//中序遍历二叉树,一遍遍历一遍线索化
void InThread(ThreadTree T){
if(T!=NULL){
InThread(T->lchild);
visit(T);
InThread(T->rchild);
}
}
void visit(ThreadNode *q){
if(q->lchild==NULL){
q->lchild=pre;
q->ltag=1;
}
if(pre!=NULL && pre->rchild==NULL){
pre->rchild =q; //建立前驱结点的后继线索
pre->rtag=1;
}
pre = q;
}
//全局变量pre,指向当前访问结点的前驱
ThreadNode * pre =NULL;
10. 先序线索化
//中序遍历二叉树,一遍遍历一遍线索化
void PreThread(ThreadTree T){
if(T!=NULL){
visit(T);
if(T->ltag==0)
PreThread(T->lchild);
PreThread(T->rchild);
}
}
void visit(ThreadNode *q){
if(q->lchild==NULL){
q->lchild=pre;
q->ltag=1;
}
if(pre!=NULL && pre->rchild==NULL){
pre->rchild =q; //建立前驱结点的后继线索
pre->rtag=1;
}
pre = q;
}
//全局变量pre,指向当前访问结点的前驱
ThreadNode * pre =NULL;
11. 后序遍历
void PostThread(ThreadTree T){
if(T!=NULL){
PostThread(T->lchild);
PostThread(T->rchild);
visit(T);
}
}
void visit(ThreadNode *q){
if(q->lchild==NULL){
q->lchild=pre;
q->ltag=1;
}
if(pre!=NULL && pre->rchild==NULL){
pre->rchild =q; //建立前驱结点的后继线索
pre->rtag=1;
}
pre = q;
}
//全局变量pre,指向当前访问结点的前驱
ThreadNode * pre =NULL;
12. 中序线索二叉树找中序后继
//找到以P为根的子树中,第一个被中序遍历的结点
ThreadNode *Firstnode(ThreadNode *p){
//循环找到最左下结点(不一定是叶节点)
while(p->ltag==0) p=p->lchild;
return p;
}
//在中序线索二叉树中找到结点p的后继结点
ThreadNode *NextNode(ThreadNode *p){
//右子树中最左下结点
if(p->rtag==0) return Firstnode(p->rchild);
else return p->rchild;
}
void Inorder(ThreadNode* T){
for(ThreadNode*p=Firstnode(T);p!=NULL;p=NextNode(p))
visit(p);
}
13.中序线索二叉树找中序前驱
ThreadNode* Lastnode(ThreadNode*p){
while(p->rtag==0) p=p->rchild;
return p;
}
ThreadNode*Prenode(ThreadNode*p){
if(p->ltag==0) return Lastnode(p->lchild);
else return p->lchild;
}
void RevInorder(ThreadNode*T){
for(ThreadNode *p=Lastnode(T);p!=NULL;p=Prenode(p))
visit(p);
}
14. 树的先根遍历
void PreOrder(TreeNode *R){
if(R!=NULL){
visit(R);
while(R还有下一个子树T)
PreOrder(T);
}
}
15. 树的后根遍历
void PostOrder(TreeNode *R){
if(R!=NULL){
while(R还有下一个子树T)
PostOrder(T);
visit(R);
}
}
11. 二叉排序树的定义
typedef struct BSTNode{
int key;
struct BSTNode *lchild,*rchild;
}BSTNode,*BSTree;
1.二叉树排序树的查找——非递归
BSTNode *BST_Search(BSTree T, int key){
while(T!=NULL&&key!=T->key){
if(key<T->key) T=T->lchild;
else T=T->rchild;
}
return T;
}
2. 二叉排序树的插入—递归实现
int BST_Insert(BSTree &T,int k){
if(T==NULL){
T=(BSTree)malloc(sizeof(BSTNode));
T->key=k;
T->lchild=T->rchild=NULLL;
return 1;
}
else if(k==T->key)
return 0;
else if(k<T->key)
return BST_Insert(T->lchild,k);
else
return BST_Insert(T->rchild,k);
}
3. 二叉排序树的构造
void Creat_BST(BSTree &T,int str[],int n){
T=NULL;
int i=0;
while(i<n){
BST_Insert(T,str[i]);
i++;
}
}
12 .平衡二叉树
1. 平衡二叉树的定义
typedef struct AVLNode{
int key;
int balance;
struct AVLNode *lchild,*rchild;
}AVLNode,*AVLTree;
2. 调整最小不平衡树——RR
f->lchild=p->rchild;
p->lchild=f;
gf->lchild/rchild=p;
13. 图
1. 图的存储——邻接矩阵法
#define MaxVertexNum 100
#define INFINITY 最大的int值
#define char VertexType;
#define int EdgeType;
typedef struct{
VertexType Vex[MaxVertexNum];
EdgeType Edge[MaxVertexNum][MaxVertexNum];
int vexnum,arcnum;
}MGraph;
2. 图的存储——邻接表法——顺序+链式存储
//用邻接表存储的图
typedef struct{
AdjList vertices;
int vexnum,arcnum;
}ALGraph;
//"顶点"
typedef struct VNode{
VertexType data;
ArcNode *first;
}VNode,AdjList[MaxVertexNum];
//“边/弧”
typedef struct ArcNode{
int adjvex;
struct ArcNode *next;
}ArcNode;
3. 广度优先搜索——无向、非连通图
bool visited[MAX_VERTEX_NUM];//访问标记数组
void BFSTraverse(Graph G){
for(i=0;i<G.vexnum;++i)
visited[i]=FALSE;
InitQueue(Q);
for(i=0;i<G.vexnum;++i)
if(!visited[i])
BFS(G,i);
}
void BFS(Graph G,int v){
visit(v);
visited[v]=TRUE;
Enqueue(Q,V);
while(!isEmpty(Q)){
DeQueue(Q,v);
for(w=FirstNeughbor(G,v);w>=0;w=NextNeighbor(G,v,w)){
if(!visited[w]){
visit(w);
visited[w]=TRUE;
EnQueue(Q,w);
}//if
}
}//while
}
4. 深度优先搜索——无向、非连通图
bool visited[MAX_VERTEX_NUM];
void DFSTraverse(Graph G){
for(i=0;i<G.vexnum;++v)
visited[v]=FALSE;
for(v=0;v<G.vexnum;++v)
if(!visited[v])
DFS(G,v);
}
void DFS(Graph G,int v){
visit(v);
visited[v]=TRUE;
for(w=FirstNeighbor(G,v);w>=0;w=NextNeighbor(G,v,w))
if(!visited[w]){
DFS(G,w);
}
}
5.最小生成树——Prim算法
void Prim(Graph g,int v){
int lowcost[MAXV];
boolean isJoin[MAXV];
int i,min,j,k;
isJoin[v]=true;
for(i=0;i<g.n;i++){
lowcost[i]=g.edges[v][i];
}
for(i=1;i<g.n;i++){
min=INF;
for(j=0;j<g.n;j++){
if(lowcost[j]!=0 && lowcost[j]<min){
min=lowcost[j];
k=j;
}
}
printf("边:(%d,%d),权值为:%d\n",isJoin[k],k,min);
for(j=0;j<g.n;j++){
if(g.edges[k][j]!=0&&g.edges[k][j]<lowcost[j]){
lowcost[j]=g.edges[k][j];
}
}
}
}
6. 最小生成树——Kruskal算法
// 边的结构体
private static class EData {
char start; // 边的起点
char end; // 边的终点
int weight; // 边的权重
public EData(char start, char end, int weight) {
this.start = start;
this.end = end;
this.weight = weight;
}
};
public class MatrixUDG {
private int mEdgNum; // 边的数量
private char[] mVexs; // 顶点集合
private int[][] mMatrix; // 邻接矩阵
private static final int INF = Integer.MAX_VALUE; // 最大值
}
/*
* 克鲁斯卡尔(Kruskal)最小生成树
*/
public void kruskal() {
int index = 0; // rets数组的索引
int[] vends = new int[mEdgNum]; // 用于保存"已有最小生成树"中每个顶点在该最小树中的终点。
EData[] rets = new EData[mEdgNum]; // 结果数组,保存kruskal最小生成树的边
EData[] edges; // 图对应的所有边
// 获取"图中所有的边"
edges = getEdges();
// 将边按照"权"的大小进行排序(从小到大)
sortEdges(edges, mEdgNum);
for (int i=0; i<mEdgNum; i++) {
int p1 = getPosition(edges[i].start); // 获取第i条边的"起点"的序号
int p2 = getPosition(edges[i].end); // 获取第i条边的"终点"的序号
int m = getEnd(vends, p1); // 获取p1在"已有的最小生成树"中的终点
int n = getEnd(vends, p2); // 获取p2在"已有的最小生成树"中的终点
// 如果m!=n,意味着"边i"与"已经添加到最小生成树中的顶点"没有形成环路
if (m != n) {
vends[m] = n; // 设置m在"已有的最小生成树"中的终点为n
rets[index++] = edges[i]; // 保存结果
}
}
// 统计并打印"kruskal最小生成树"的信息
int length = 0;
for (int i = 0; i < index; i++)
length += rets[i].weight;
System.out.printf("Kruskal=%d: ", length);
for (int i = 0; i < index; i++)
System.out.printf("(%c,%c) ", rets[i].start, rets[i].end);
System.out.printf("\n");
}
7.无权图的单源最短路径——BFS算法
bool visited[MAX_VERTEX_NUM];
//广度优先遍历
void BFS_MIN_Distance(Graph G,int v){
for(i=0;i<G.vexnum;++i){
d[i]=∞;
path[i]=-1;
}
d[u]=0;
visited[v]=TRUE;
Enqueue(Q,v);
while(!isEmpty(Q)){
Dequeue(Q,V);
for(w=FirstNeighbor(G,v);w>=0;w=Nextghbor(G,v,w))
if(!visited[w]){
d[w]=d[u]+1;
path[w]=u;
visited[w]=TRUE;
EnQueue(Q,w);
}//if
}//while
}
8. 最短路径——Dijkstra算法:不能解决负权值
void Dijkstra(AMGraph G,int v,int dist[],int path[])
{
int i,j,u,Min;
bool final[MaxSize];
for(i=0; i<G.n; i++)
{
dist[i] = G.arcs[v][i]; //初始化权值,v到i如果有边,则权值置权值,若无,则为MaxInt
final[i] = false; //初始集合为空
if(G.arcs[v][i]<MaxInt) //将与v有连接的顶点的前驱置为v,无连接的置为-1
path[i] = 0;
else
path[i] = -1;
}
final[v] = true;
path[v] = -1;
for(i=0; i<G.n-1; i++) //n-1轮
{
Min = MaxInt;
for(j=0; j<G.n; j++) //选出所有连接节点中权值最小的节点
{
if(final[j]==false&&dist[j]<Min)
{
u = j;
Min = dist[j];
}
}
final[u] = true;
for(j=0; j<G.n; j++) //判断u的加入是否会出现通往顶点j的更短的路径,若出现,则更新权值
{
if(final[j]==false&&dist[u]+G.arcs[u][j]<dist[j])
{
dist[j] = dist[u]+G.arcs[u][j];
path[j] = u;
}
}
}
}
9. 负权图-最短路径——Floyd算法——动态规划
- 不能解决有负权值的边组成的回路
for(int k=0;k<n;k++){
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(A[i][j]>A[i][k]+A[k][j]){
A[i][j]=A[i][k]+A[k][j];
path[i][j]=k;
}
}
}
}
10.拓扑排序——有回路的图
bool TopologicalSort(Graph G){
InitStack(S);
for(int i=0;i<G.vexnum;i++){
if(indegree[i]==0)
Push(S,i);
}
int count=0;
while(!IsEmpty(S)){
Pop(S,i);
print[count++]=i;
for(p=G.vertices[i].firstarc;p;p=p->nextarc){
v=p->adjvex;
if(!(--indegree[v]))
Push(S,v);
}
}//while
if(count<G.vexnum)
return false;
else
return true;
}
11.逆拓扑排序——DFS算法
void DFSTraverse(Graph G){
for(v=0;v<G.vexnum;++v)
visited[v]=false;
for(v=0;v<G.vexnum;++v)
if(!visited[v])
DFS(G,V);
}
void DFS(Graph G,int v){
visit(v);
visited[v]=TRUE;
for(w=FirsrNeighbor(G,v);w>=0;w=NextNeighbor(G,v,w))
if(!visited[w]){
DFS(G,w);
}
print(v);
}
14.查找
1. 顺序查找
typedef struct{
ElemType *elem;
int TableLen;
}SSTable;
int Search_Seq(SSTable ST,ElemType key){
int i;
for(i=0;i<ST.TableLen&&ST.elem[i]!=key;++i);
return i==ST.TableLen?-1:i;
}
2. 顺序查找(哨兵)
typedef struct{
ElemType *elem;
int TableLen;
}SSTable;
int Search_Seq(SSTable ST,ElemType key){
ST.elem[0]=key;
int i;
for(i=ST.TableLen;ST.elem[i]!=key;--i);
return i;
}
3. 折半查找:判定查找树
typedef struct{
ElemType *elem;
int TableLen;
}SSTable;
int Binary_Search(SSTable L,ElemType key){
int low=0,high=L.TableLen-1,mid;
while(low<=high){
mid=(low+high)/2;
if(L.elem[mid]==key)
return mid;
else if(L.elem[mid]>key)
high=mid-1;
else
low=mid+1;
}
return -1;
}
4. 分块查找,又叫,索引顺序查找
typedef struct{
ElemType maxValue;
int low,high;
}Index;
ElemType List[100];
5. B树和B+树
6. 哈希查找,又叫散列查找
15. 排序
1.插入排序——直接插入排序
void InsertSort(int A[],int n){
int i,j,temp;
for(i=1;i<n;i++)
if(A[i]<A[i-1]){
temp=A[i];
for(j=i-1;j>=0&&A[j]>temp;--j)
A[j+1]=A[j];
A[j+1]=temp;
}
}
1.2 插入排序——直接插入排序—哨兵
- 不推荐使用
void InsertSort(int A[],int n){
int i,j;
for(i=2;i<=n;i++){
if(A[i]<A[i-1]){
A[0]=A[i];
for(j=i-1;A[0]<A[j];--j)
A[j+1]=A[j];
A[j+1]=A[0];
}
}
}
2. 折半插入排序
void InsertSort(int A[],int n){
int i,j,low,high,mid;
for(i=2;i<=n;i++){
A[0]=A[i];
low=1;high=i-1;
while(low<=high){
mid=(low+high)/2;
if(A[mid]>A[0]) high=mid-1;
else low=mid+1;
}
for(j=i-1;j>=high+1;--j)
A[j+1]=A[j];
A[high+1]=A[0];
}
}
3. 希尔排序
void ShellSort(int A[],int n){
int d,i,j;
for(d=n/2;d>=1;d=d/2)
for(i=d+1;i<=n;++i)
if(A[i]<A[i-d]){
A[0]=A[i];
for(j=i-d;j>0&&A[0]<A[j];j-=d)
A[j+d]=A[j];
A[j+d]=A[0];
}//if
}
4. 冒泡排序
void BubbleSort(int A[],int n){
for(int i=0;i<n-1;i++){
bool flag=false;
for(int j=n-1;j>i;j--)
if(A[j-1]>A[j]){
swap(A[j-1],A[j]);
flag=true;
}
if(flag==false)
return ;
}
}
void swap(int &a,int &b){
int temp =a;
a=b;
b=temp;
}
5. 快速排序
int Partition(int A[],int low,int high){
int pivot=A[low];
while(low<high){
while(low<high&&A[high]>=pivot) --high;
A[low]=A[high];
while(low<high&&A[low]<=pivot) ++low;
A[high]=A[low];
}
A[low]=pivot;
return low;
}
void QuickSort(int A[],int low,int high){
if(low<high){
int pivotpos=Partition(A,low,high);
QuickSort(A,low,pivotpos-1);
QuickSort(A,pivotpos+1,high);
}
}
6. 选择排序——简单选择排序
void SelectSort(int A[],int n){
for(int i=0;i<n-1;i++){
int min=i;
for(int j=i+1;j<n;j++)
if(A[j]<A[min]) min=j;
if(min!=i)swap(A[i],A[min]);
}
}
7. 选择排序——堆排序——大根堆
//建立大根堆
void BuildMaxHeap(int A[],int len){
for(int i=len/2;i>0;i--)
HeadAdjust(A,i,len);
}
void HeadAdjust(int A[],int k, int len){
A[0]=A[k];
for(int i=2*k;i<=len;i*=2){
if(i<len && A[i]<A[i+1])
i++;
if(A[0]>=A[i]) break;
else{
A[k]=A[i];
k=i;
}
}
A[k]=A[0];
}
void HeadSort(int A[],int len){
BuildMaxHeap(A,len);
for(int i=len;i>i;i--){
swap(A[i],A[1]);
HwadAdjust(A,1,i-1);
}
}
8. 归并排序
int *B=(int *)malloc(n*sizeof(int));//辅助数组B
void Merge(int A[],int low,int mid,int high){
int i,j,k;
for(k=low;k<=high;k++)
B[k]=A[k];
for(i=low,j=mid+1,k=i;i<=mid&&j<=high;k++){
if(B[i]<B[j])
A[k]=B[i++];
else
A[k]=B[j++];
}
while(i<mid) A[k++]=B[i++];
while(j<high) A[k++]=B[j++];
}
void MergeSort(int A[],int low,int high){
if(low<high){
int mid=(low+high)/2;
MergeSort(A,low,mid);
MergeSort(A,mid+1,high);
Merge(A,low,mid,high);
}
}