数据结构

数据结构

⭐ 和小伙伴们分享,交流,做一名技术极客。🙂
⭐ 不断添加:有趣的知识 😄
⭐ 特别感谢:王道考研(我认识你,但是你不认识我)😁
⭐ 用最少的文字,表达最清楚的含义 🙃

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);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值