数据结构 考研 代码总结 【基本完善】

Note:本文旨在后期自己复习方便所纪录。部分代码不保证可运行行,有问题欢迎指出。

文章目录

  • 1.线性表
    • 1.1 线性表链式存储
    • 1.2线性表的顺序存储
    • 1.3 顺序栈
    • 1.4 链队
    • 1.5 循环队列
    • 1.6 KMP and BF
  • 2 树
    • 2.1 树的存储结构
      • 2.1.1 顺序存储
      • 2.1.2 链式结构
    • 2.2 各种遍历
      • 2.2.1 前中后 + 层次
      • 2.2.2 前 中 后 非递归
    • 2.3 中序线索化二叉树
    • 2.4 幷查集
  • 3 图
    • 3.1 图的存储结构
      • 3.1.1 邻接表
      • 3.1.2 十字链表
      • 3.1.3 邻接多重表
    • 3.2 图的遍历
      • 3.2.1 深度优先遍历 dfs
    • 3.3 topo 排序
    • 3.4 双连通分量
      • 3.4.1 点双联通分量BCC
      • 3.4.2 边双联通分量EBC
    • 3.5 强联通分量 SCC
    • 3.6 最小生成树 krus
    • 3.7 最短路 djk
  • 6 查找
    • 6.1 折半查找
    • 6.3 串的模式匹配
      • 6.4 KMP
    • 6.5 散列表 拉链法
    • 6.6 BST 二叉搜索树
    • 6.7 AVL 平衡二叉树
    • 6.8 键树(字典树)
  • 7 排序
    • 7.2 插入排序
      • 7.2.1 简单插入排序
      • 7.2.2 折半插入排序
      • 7.2.3 希尔排序
    • 7.3 交换排序
      • 7.3.1 冒泡排序
      • 7.3.2 快速排序
    • 7.4 选择排序
      • 7.4.1 简单选择排序
      • 7.4.2 堆排序
    • 7.4 归并排序

1.线性表

1.1 线性表链式存储

#include 
#include 

typedef char ElemType;

typedef struct LinkNode{
    ElemType data;
    struct LinkNode *next;
}LinkNode, *LinkList;

// 下面是带头节点的链表

bool InitList(LinkList& L){
    if(!(L = (LinkNode* )malloc(sizeof(LinkNode)))) { // 没创建成功
        printf("it is not enough space.\n");
        return false;
    }
    L->next = NULL;
    return true;
}
bool DestroyList(LinkList& L){
    free(L);
}
bool ClearList(LinkList& L){
    L->next = NULL;
}
bool ListEmpty(LinkList L){
    return (L->next == NULL) ? true : false;
}
int ListLength(LinkList L){
    int length = 0;
    LinkNode *p = L->next;
    while(p){ 
        length++; p = p->next;
    }
    
    return length;
}

bool GetElem(LinkList L, int i, ElemType &e){
    if(i < 1 || i > ListLength(L)) return false;
    int cnt = 1;
    LinkNode *p = L->next;
    while(p){
        if(cnt == i) {
            e = p->data;
            return true;
        }
        p = p->next;
        cnt++;
    }
}
bool Compare(ElemType a, ElemType b){
    if(a == b) return 0;
    if(a > b) return 1;
    else return -1;
}
 // 传参 函数指针 确定比较方式
int LocateElem(LinkList L, ElemType e, bool (*Compare)(ElemType, ElemType)){
    LinkNode *p = L->next;
    int pos = 1;
    while(p){
        if(!Compare(p->data, e))  
            return pos;
        ++pos;
        p = p->next;
    }
    return 0; // 0 表示没找到
}
bool ListInsert(LinkList& L, int i, ElemType e){
    if(i < 1 || i > ListLength(L) + 1) return false;
    LinkNode *p = L->next, *fa = L;
    LinkNode *cur = (LinkNode *) malloc(sizeof(LinkNode));
    cur->data = e; cur->next = NULL;
    int pos = 1;
    while(p){
        if(pos == i)  break; 
        ++pos;
        p = p->next; fa = p->next;
    }

    fa->next = cur;
    cur->next = p;
}

bool LinkDelete(LinkList &L, int i){
    if(i < 1 || i > ListLength(L)) return false;
    LinkNode *p = L->next, *fa = L;
    int pos = 1;
    while(p){
        if(pos == i){
            fa->next = p->next;
            return true;
        }
        ++pos;
        p = p->next;
        fa = fa->next;
    }
}

bool LinkTraverse(LinkList L){
    L = L->next;
    while(L){
        printf("%c ", L->data);
        L = L->next;
    }
    puts(""); // 换行
}


// test ..
int main(){ 
   
    LinkList L;
    InitList(L);
    ElemType tmp = 'a';
    ListInsert(L, 1, 'a');
    LinkTraverse(L);
    tmp = 'c';
    ListInsert(L, 1, tmp);
    LinkTraverse(L);
    LinkDelete(L, 2);
    LinkTraverse(L);

    return 0;
}

1.2线性表的顺序存储

#include 
#include 

typedef char ElemType;
#define LIST_INIT_SIZE  100 // 线性表存储空间的初始分配量
#define LISTINCRMENT 10  // 线性表存储空间的分配增量
typedef enum {OK, OVERFLOW, ERROR} Status;

typedef struct{
    ElemType  *elem;
    int length;    //当前线性表长度
    int listsize;  // 当前分配的存储容量
}SqList;

Status InitList_Sq(SqList &L){
    L.elem = (ElemType *) malloc(sizeof(ElemType) * LIST_INIT_SIZE);
    if(!L.elem) return OVERFLOW;
    L.listsize = LIST_INIT_SIZE;
    L.length = 0;
    return OK;
}

Status ListInsert_Sq(SqList &L,int i, ElemType e){
    if(i < 1 || i > L.length + 1) return ERROR;
    if(L.length >= L.listsize) { // 容量满了,扩孔容量
        ElemType *base = (ElemType *) realloc(L.elem, (L.listsize + LISTINCRMENT) * sizeof(ElemType));
        if(!base) exit(OVERFLOW);
        L.elem = base;
        L.listsize += LISTINCRMENT;
    }
    ElemType *q = &(L.elem[i - 1]);
    for(ElemType *p = &(L.elem[L.length - 1]); p >= q; p--) 
        *(p + 1) = *p;
    *q = e;
    ++L.length;
    return OK;
}   

Status ListDelete_Sq(SqList &L, int i){
    if(i < 1 || i > L.length) return ERROR;
    ElemType *p, *q;
    q = &(L.elem[L.length - 1]);
    for(p = &(L.elem[i - 1]); p < q; ++p) 
        *p = *(p + 1);
    --L.length;
    return OK;
}

void Traverse(SqList L){
    for(int i = 0; i < L.length; i++){
        printf("%c ", L.elem[i]);
    }
    puts("");
}
int main(){
    SqList L;
    InitList_Sq(L);
    ElemType e = 'a';
    ListInsert_Sq(L, 1, e);
    e = 'c';
    ListInsert_Sq(L, 1, e);
    Traverse(L);
    ListDelete_Sq(L, 2);
    Traverse(L);
    return 0;
} 

1.3 顺序栈

#include 
#include 

typedef enum{OK, ERROR, OVERFLOW}Status;
#define STACK_INIT_SIZE 100    // 栈的初始容量
#define STACKINCREMENT  10     // 每次扩充的容量
typedef char ElemType;

typedef struct{
    ElemType *base;
    ElemType *top;
    int stacksize;
}SeqStack;

Status InitStack(SeqStack &S){
    S.base = (ElemType *)malloc(sizeof(ElemType) * STACK_INIT_SIZE);
    if(!S.base) exit(OVERFLOW  );
    S.top = S.base;
    S.stacksize = STACK_INIT_SIZE;
    return OK;
}
Status GetTop(SeqStack S, ElemType &e){
    if(S.top == S.base) return ERROR;
    e = *(S.top - 1);
    return OK;  
}
Status Push(SeqStack &S, ElemType e){
    if(S.top - S.base >= S.stacksize) {// 栈满 扩充栈
        ElemType *base = (ElemType*) realloc(S.base, 
            (S.stacksize + STACKINCREMENT) * (ElemType));
        if(!base) exit(OVERFLOW);
        S.top = S.base + S.stacksize;
        S.stacksize += STACKINCREMENT;
    }
    *S.top++ = e;
    return OK;
}
bool StackEmpty(SeqStack S){
    return S.top == S.base;
}
void StackClear(SeqStack &S){
    S.top = S.base;
}
Status Pop(SeqStack &S, ElemType &e){
    if(S.top == S.base) return ERROR;
    e = *--S.top;
    return OK;
}


// TEST
int main(){
    SeqStack S;
    InitStack(S);
    ElemType c = 'c';
    Push(S, c);

    Push(S, c);
    c = 'a';
    Push(S, c);
    while(!StackEmpty(S)) {
        ElemType t;
        GetTop(S, t);
        printf("%c ", t);
        Pop(S, t);
    }

    return 0;
} 

1.4 链队

#include 
#include 

typedef char ElemType;
typedef struct QNode{
    ElemType data;
    struct QNode *next;
}QNode, *QueuePtr;
typedef struct {
    QueuePtr front, rear;
}LinkQueue;

typedef enum{OK, ERROR, OVERFLOW} Status;

Status InitQueue(LinkQueue &Q){
    Q.front = Q.rear = (QNode*) malloc (sizeof(QNode));
    if(!Q.front)exit(OVERFLOW);
    return OK;    
}
bool QueueEmpty(LinkQueue Q){
    return Q.front == Q.rear;
}
Status DestroyQueue(LinkQueue &Q){
    ElemType *p;
    while(!QueueEmpty(Q)){
        
    }
}
Status EnQueue(LinkQueue &Q, ElemType e){
    QNode *p = (QNode*) malloc(sizeof(QNode));
    if(!p) exit(OVERFLOW);
    p->data = e; p->next = NULL;
    Q.rear->next = p;
    Q.rear = p;
    return OK;
}

Status DeQueue(LinkQueue &Q, ElemType &e){
    if(Q.front == Q.rear) return ERROR;
    QNode *p;
    p = Q.front->next;
    e = p->data;
    Q.front->next = p->next;
    if(p == Q.rear) Q.rear = Q.front;
    free(p);
    return OK;
}
Status GetHead(LinkQueue Q, ElemType &e){
    if(Q.front == Q.rear) return ERROR;
    e = Q.front->next->data;
    return OK;
}


int main(){


    return 0;
}

1.5 循环队列

#include 
#include 

typedef char ElemType;
typedef enum{OK, ERROR, OVERFLOW} Status;

#define MAXQSIZE 1000
typedef struct {
    ElemType *que;
    int front, rear;
} SeqQueue;   // 通过浪费一个存储单元 来区分满还是空

Status InitQueue(SeqQueue &Q){
    Q.que = (ElemType*) malloc (sizeof(ElemType) * MAXQSIZE);
    Q.front = Q.rear = 0;
}
Status ClearQueue(SeqQueue &Q){
    Q.front = Q.front = 0;
}

bool QueueEmpty(SeqQueue Q){
    return Q.front == Q.rear; 
}
Status EnQueue(SeqQueue& Q, ElemType e){
    if((Q.rear + 1) % MAXQSIZE == Q.front) return ERROR;
    Q.que[Q.rear] = e;
    Q.rear = (Q.rear + 1) % MAXQSIZE;
    return OK;
}
Status DeQueue(SeqQueue&Q, ElemType &e){
    if(Q.rear == Q.front) return ERROR;
    e = Q.que[Q.front];
    Q.front = (Q.front + 1) % MAXQSIZE;
    return OK;
}
int QueueLength(SeqQueue Q){
    return (Q.rear - Q.front + MAXQSIZE) % MAXQSIZE;
}

int main(){


    return 0;
}

#include 
#include 

typedef char ElemType;
typedef enum{OK, ERROR, OVERFLOW} Status;

#define MAXQSIZE 1000
typedef struct {
    ElemType *que;
    int front, rear;
    bool flag; // 通过flag来区分满还是空
} SeqQueue;
/*
    if front == rear 
        if flag == 1  空
        if flag == 0  满
         
    */
Status InitQueue(SeqQueue &Q){
    Q.que = (ElemType*) malloc (sizeof(ElemType) * MAXQSIZE);
    Q.front = Q.rear = 0;
    Q.flag = 1;
}
Status ClearQueue(SeqQueue &Q){
    Q.front = Q.front = 0;
    Q.flag = 1;
}

bool QueueEmpty(SeqQueue Q){
    return (Q.front == Q.rear) && Q.flag; 
}
Status EnQueue(SeqQueue& Q, ElemType e){
    if((Q.front == Q.rear) && !Q.flag) return ERROR;
    Q.que[Q.rear] = e;
    Q.rear = (Q.rear + 1) % MAXQSIZE;
    Q.flag = 0; 
    return OK;
}
Status DeQueue(SeqQueue&Q, ElemType &e){
    if((Q.rear == Q.front) && Q.flag) return ERROR;
    e = Q.que[Q.front];
    Q.front = (Q.front + 1) % MAXQSIZE;
    Q.flag = 1;
    return OK;
}
int QueueLength(SeqQueue Q){
    return (Q.rear - Q.front + MAXQSIZE) % MAXQSIZE;
}

int main(){


    return 0;
}



1.6 KMP and BF

#include 
#include 

bool BF(char *s, char *t){
    int i, j, k;
    i = 0, j = 0;
    int lens = strlen(s), lent = strlen(t);
    while(i < lens){
        while(i < lens && j < lent && s[i] == t[j]) ++i, ++j;
        if(j >= lent) return true;
        j = 0; i = i - j + 1;
    }
}


const int N = 1000; // 模式串的最长长度

int next[N];
void getnext(char *s, int len){
    next[0] = -1;
    int i, j;
    i = 0; j = -1;
    while(i < len){
        if(j == -1 || s[i] == s[j] )
            next[++i] = ++j;
        else 
            j = next[j];
    }
}
bool Kmp(char *s, char *t){
    int lens = strlen(s), lent = strlen(t);

    getnext(t, lent);
    int i, j;
    i = j = 0; 
    while(i < lens){
        if(j == -1 || s[i] == t[j]) {
            ++i, ++j;
            if(j >= lent) return true;
        }            
        else 
            j = next[j];
    }
}

int main(){


    return 0;
}


2 树

2.1 树的存储结构

2.1.1 顺序存储


#include 
#include 


#define MAX_TREE_SIZE 100
typedef char ElemType; 
typedef ElemType SqBiTree[MAX_TREE_SIZE];

// 适合存完全二叉树或者满二叉树
// 举个例子: 给完全二叉树上的两个节点的序号,求其最近公共祖先(LCA)

ElemType solve(SqBiTree T, int a, int b){
    while(a != b){
        if(a > b) b /= 2;
        else a /= 2;
    }
    return T[a];
}


int main(){


    return 0;
}

2.1.2 链式结构

#include 
#include 


#define MAX_TREE_SIZE 100
typedef char ElemType; 
typedef struct BNode{
    ElemType data;
    struct BNode *lchild;
    struct BNode *rchild;
}BNode, *BiTree;

void Inorder(BiTree T){
    if(T == NULL) return ;
    Inorder(T->lchild);
    // visit(T->data);
    printf("%c ", T->data);
    Inorder(T->rchild);
}
void preorder(BiTree T){
    if(T == NULL) return ;
    // visit(T->data);
    printf("%c ", T->data);
    
    Inorder(T->lchild);
    Inorder(T->rchild);
}

void postorder(BiTree T){
    if(T == NULL) return ;
    Inorder(T->lchild);
    Inorder(T->rchild);
    // visit(T->data);
    printf("%c ", T->data);
}

#define MAX 200
void leverorder(BiTree T){
    BiTree queue[MAX]; 
    int front , rear;
    front = rear = 0;
    queue[rear++] = T;
    while(front < rear){
        BiTree p = queue[front++];
        printf("%c ", p->data);
        if(p->lchild) queue[rear++] = p->lchild;
        if(p->rchild) queue[rear++] = p->rchild;
    }   
}

int main(){


    return 0;
}

2.2 各种遍历

2.2.1 前中后 + 层次

#include 
#include 


#define MAX_TREE_SIZE 100
typedef char ElemType; 
typedef struct BNode{
    ElemType data;
    struct BNode *lchild;
    struct BNode *rchild;
}BNode, *BiTree;

void Inorder(BiTree T){
    if(T == NULL) return ;
    Inorder(T->lchild);
    // visit(T->data);
    printf("%c ", T->data);
    Inorder(T->rchild);
}
void preorder(BiTree T){
    if(T == NULL) return ;
    // visit(T->data);
    printf("%c ", T->data);
    
    Inorder(T->lchild);
    Inorder(T->rchild);
}

void postorder(BiTree T){
    if(T == NULL) return ;
    Inorder(T->lchild);
    Inorder(T->rchild);
    // visit(T->data);
    printf("%c ", T->data);
}

#define MAX 200
void leverorder(BiTree T){
    BiTree queue[MAX]; 
    int front , rear;
    front = rear = 0;
    queue[rear++] = T;
    while(front < rear){
        BiTree p = queue[front++];
        printf("%c ", p->data);
        if(p->lchild) queue[rear++] = p->lchild;
        if(p->rchild) queue[rear++] = p->rchild;
    }   
}

int main(){


    return 0;
}

2.2.2 前 中 后 非递归

#include 
#include 
#define MAX_TREE_SIZE 100
typedef char ElemType; 
typedef struct BNode{
    ElemType data;
    struct BNode *lchild;
    struct BNode *rchild;
}BNode, *BiTree;

void inorder(BiTree T){
    InitStack(S);
    BNode *p = T;
    while(!StackEmpty(S) || p){
        if(!p) {
            Push(S, p);
            p = p->lchild;
        }else {
            Pop(S, p);
            printf("%c ", p->data);
            p = p->rchild;
        }
    }
}
void postorder(BiTree T){
    InitStack(S);
    BNode *p = T, *last = NULL;
    while(!StackEmpty(S) || p){
        if(p){
            Push(S, p);
            p = p->lchild;
        }
        else {
            GetTop(S, p);
            if(p->rchild && p == last){ // 向右子树 递归
                Pop(S, p);
                printf("%c ", p->data);
                last = p;
                p = NULL;
            }else {
                p = p->rchild;
            }
        }
    }
}

int main(){
    

    return 0;
}



2.3 中序线索化二叉树

#include 
#include 


#define MAX_TREE_SIZE 100
typedef char ElemType; 
typedef struct BNode{
    ElemType data;
    bool ltag, rtag;
    struct BNode *lchild;
    struct BNode *rchild;
}BNode, *BiTree;

void DFS(BiTree T, BiTree &pre){
    if(T == NULL) return ;
    T->ltag = T->rtag = 0;
    DFS(T->lchild, pre);
     
    if(!T->lchild) {
        T->ltag = 1;
        T->lchild = pre;
    }
    if(!pre->rchild) {
        pre->rtag = 1;
        pre->rchild = T;
    }
    pre = T;
    DFS(T->rchild, pre);
}

// 构造 中序线索化二叉树
void BinaryTree_Thread_Inorder(BiTree T){
    BiTree pre = NULL;
    DFS(T, pre);
    pre->rtag = 0;
    pre->rchild = NULL;
}

BiTree First(BiTree T){
    while(!T->ltag) {
        T = T->lchild;
    }
    return T;
}

BiTree Next(BiTree T){
    if(T->rtag) return T->rchild;
    else 
        First(T->rchild);
}
// 遍历线索化二叉树
void Traverse_Inorder_Thread(BiTree T){
    BiTree p;
    for(p = First(T); p; p = Next(p)) {
        printf("%c ", p->data);
    }
}

int main(){


    return 0;
}

2.4 幷查集

#include 
#include 
#include 

const int N = 1e5 + 11;

int pre[N];
void Init(int n){ // n 为集合大小
    for(int i = 1; i <= n; i++){
        pre[i] = i; // 每个集合用自己表示自己
    }
}

int Find(int x) { // 寻找元素x属于哪个集合
    while(pre[x] != x) {
        x = pre[x];
    }
    return x;
}

void Join(int x,int y){ // 将x 和 y 集合合并
    int fx = Find(x);
    int fy = Find(y);
    if(fx != fy){
        pre[fx] = fy;
    }
}
// 此为简单 幷查集,幷查集还可以考虑带权幷查集,不过考研用不到。
// 还可以考虑 启发式合并(比如说 结点少的向结点多的合并),防止退化成链

int Find_(int x ) { // 带有路径压缩的 查找
    return (pre[x] == x) ? x : pre[x] = Find(pre[x]);
}
int main(){


    return 0;
}    


3 图

3.1 图的存储结构

3.1.1 邻接表

#include 
#include 

#define InfoType char   
#define VertexType char  // 顶点信息
#define MAX_VERTEX_NUM 100 // 最大顶点数量

typedef struct ArcNode{
    int adjvex; // 邻接顶点
    struct ArcNode *next;
    InfoType *info; // 该弧相关信息的指针
}ArcNode;

typedef struct VNode{
    VertexType data;
    ArcNode *firstarc;
}VNode, AdjList[MAX_VERTEX_NUM];

typedef struct {
    AdjList vertices;
    int vexnum, arcnum;  // 当前顶点数量和弧的数量
    int kind;  // 图的种类标识
}ALGraph;

int main(){
    ALGraph G;
    int n, m; scanf("%d%d", &n, &m);
    ArcNode *arc;
    while(m--){   // 建图
        int a, b, c; 
        scanf("%d%d%d", &a, &b, &c);  // a --> b 的weight为c的无向边
            arc = (ArcNode *) malloc(sizeof(ArcNode));
        arc->next = G.vertices[a].firstarc;   // 头插法
        G.vertices[a].firstarc = arc;

            arc = (ArcNode *) malloc(sizeof(ArcNode));
        arc->next = G.vertices[b].firstarc;   // 头插法
        G.vertices[b].firstarc = arc;
    }

    int u = 1;  // 遍历 所有和u相邻的顶点v
    for(arc = G.vertices[u].firstarc; arc; arc = arc->next){
        int v = arc->adjvex;
            
    }

    return 0;
}

3.1.2 十字链表

#include 
#include 
#include 
/*
    十字链表 用来存储有向图
    其实就是将邻接表和逆邻接表合并一起

    */
#define MAX_VERTEX_NUM 100  // 最多的顶点数

typedef char InfoType;
typedef int ElemType;
typedef struct ArcNode{
    int tailvex, headvex;           // tailvex -> headvex 的一条边
    struct ArcNode *tlink, *hlink;  // 分别为弧尾和弧头相同的弧的链域
    InfoType *info;  // 存储 弧上信息
}ArcNode;
typedef struct VexNode{
    ElemType data;  // 顶点信息
    ArcNode *firstin, *firstout; // 第一个指向当前顶点和第一个当前顶点指向的弧链
}VexNode;
typedef struct {
    VexNode xlist[MAX_VERTEX_NUM];
    int vexnum, arcnum;  
}OLGraph;


int main(){
    OLGraph olg;
    int n, m; scanf("%d%d", &n, &m);
    olg.arcnum = m; olg.vexnum = n;
    for(int i = 0; i <= olg.vexnum; i++){
        olg.xlist[i].firstin = olg.xlist[i].firstout = NULL;
    }

    for(int i = 0; i < m; i++){
        int a, b; // a->b 的有向弧
        scanf("%d%d%d", &a, &b, &c);
        ArcNode *p = (ArcNode *) malloc(sizeof(ArcNode));
        *p = {a, b, olg.xlist[a].firstout, olg.xlist[b].firstin, NULL};  // 都采用头插入法
            //{tailvex, headvex, tlink, hlink, info}         
        olg.xlist[a].firstout = olg.xlist[b].firstin = p;

    }
    return 0;
}

3.1.3 邻接多重表

#include 
#include 

/*
    邻接多重表 用来存无向图

    */

typedef char ElemType;
#define MAX_VEX_NUM 10000
typedef struct ArcNode{
    int ivex, jvex;   
    struct ArcNode *ilink, *jlink;
    // 可以再保存一个 弧上的信息
}ArcNode;
typedef struct VNode{
    ElemType data; // 顶点信息
    ArcNode *firstout;
}VNode;

typedef struct {
    VNode adjmulist[MAX_VEX_NUM];
    int vexnum, arcnum;
}AMLGraph;

int main(){
    AMLGraph G;
    int n, m; scanf("%d%d", &n, &m);
    G.vexnum = n; G.arcnum = m;
    for(int i = 0; i <= G.vexnum; i++){ // 清空
        G.adjmulist[i].firstout = NULL;
    }

    while(m--){
        int a, b; // a->b的一个无向弧
        scanf("%d%d", &a, &b);
        ArcNode *p = (ArcNode *) malloc (sizeof(ArcNode));
        *p = {a, b, G.adjmulist[a].firstout, G.adjmulist[b].firstout};
        G.adjmulist[a].firstout = G.adjmulist[b].firstout = p;
    }

    int u;  // 遍历所有 和u相邻的顶点v 
    for(ArcNode *p = G.adjmulist[u].firstout; p; p = p->ilink) {
        int v = p->jvex;

    }
    
    return 0;

}

3.2 图的遍历

3.2.1 深度优先遍历 dfs

#include 
#include 
#include 

/*
    生成DFS序列
    存储图用的是邻接表

    */
#define InfoType char   
#define VertexType char  // 顶点信息
#define MAX_VERTEX_NUM 100 // 最大顶点数量

typedef struct ArcNode{
    int adjvex; // 邻接顶点
    struct ArcNode *next;
    InfoType *info; // 该弧相关信息的指针
}ArcNode;

typedef struct VNode{
    VertexType data;
    ArcNode *firstarc;
}VNode, AdjList[MAX_VERTEX_NUM];

typedef struct {
    AdjList vertices;
    int vexnum, arcnum;  // 当前顶点数量和弧的数量
    int kind;  // 图的种类标识
}ALGraph;


bool vis[MAX_VERTEX_NUM];
void DFS(ALGraph G, int u){
    printf("%d ", u);
    vis[u] = true;
    for(ArcNode *p = G.vertices[u].firstarc; p; p = p->next){
        int v = p->adjvex;
        if(!vis[v]){
            DFS(G, v);
        }
    }
}
int main(){
    ALGraph G;
    int n, m; scanf("%d%d", &n, &m);
    for(int i = 0; i <= n; i++){
        G.vertices[i].firstarc = NULL; // 清空
    }
    
    ArcNode *arc;
    while(m--){   // 建图
        int a, b, c; 
        scanf("%d%d%d", &a, &b, &c);  // a --> b 的weight为c的无向边
        arc = (ArcNode *) malloc(sizeof(ArcNode));
        *arc = {b, G.vertices[a].firstarc, NULL};
        G.vertices[a].firstarc = arc;
    
        arc = (ArcNode *) malloc(sizeof(ArcNode));
        *arc = {a, G.vertices[b].firstarc, NULL};
        G.vertices[b].firstarc = arc;
    }
    // 得到DFS序列
    memset(vis, false, sizeof(vis));   //清空 标记
    for(int i = 1; i <= n; i++){
        if(!vis[i])   // 有可能图不是连通的,所以这样遍历 将所有顶点都访问到
            DFS(G, i);
    }
    return 0;
}

/*
input_sample :
5 3 
1 2 0
1 3 0
4 5 1


    */

3.3 topo 排序


/*
    topo 排序过程中可以 
    1. 判断有向图是否有环
    2. 判断出topo序列是否唯一
    */
void Topo(G, in){  // 图G和顶点的入度in
    int cnt = 0;  // 记录访问了几个顶点
    bool flag = true; // topo是否唯一
    Init(que);
    int cur = 0;
    for(int i = 0; i < G.vexcnt; i++){
        if(!in[i]) {
            print(i);  // 输出顶点
            cnt++;
            cur ++;
            Enqueue(que, i);
        }
    }
    if(cur > 1) flag = 0;
    while(!IsEmpty(que)){
         Dequeue(que, v);
         cur = 0;
         for(w = FirstEdge(G, v); w; w = NextEdge(G, v, w)) {
             if(--in[w] == 0) {
                print(w);  // 输出顶点
                cnt++;
                cur ++;
                Enqueue(que, w);
             }
         }
         if(cur > 1) flag = 0; 
    }

    if(cnt < G.vexcnt) puts("有向图中有环!");  // 有环的话 不会遍历所有的顶点
    else if(!flag) puts("topo序不唯一"); // 每次 只有一个入度为0的 ,这样topo序才唯一
    else puts("topo序唯一");
}

3.4 双连通分量

3.4.1 点双联通分量BCC

#include 
using namespace std;

typedef long long ll;
typedef pair<int, int> pii;

const int N = 1e5 + 11;
const int M = 1e6 + 11;
const int MOD = 1e9 + 7;

vector<int>G[N];
int dfn[N], low[N], clo;
int bcc_cnt, st[N], iscut[N], bccno[N];
void tarjan(int u, int fa){
    dfn[u] = low[u] = ++clo; st[++*st] = u;
    for(int i = 0; i < G[u].size(); i++){
        int v = G[u][i];

        if(!dfn[v] && v != fa){
            tarjan(v, u);
            low[u] = min(low[u], low[v]);
            if(low[v] >= dfn[u]) {
                ++bcc_cnt;
                iscut[u] = true;
                do{
                    bccno[st[*st]] = bcc_cnt;
                 }while(st[st[0]--] != u);

                 st[++*st] = u;  // 割点会属于多个bcc ,所以要再填充进去
            }
        }else 
            low[u] = min(low[u], dfn[v]);
    }
    if(fa == -1 && G[u].size() < 2) iscut[u] = false;
}
void bcc_cut(int n){
    memset(dfn, 0, sizeof(dfn));
    memset(low, 0, sizeof(low));
    memset(iscut, false, sizeof(iscut));
    memset(bccno, 0, sizeof(bccno));
    st[0] = bcc_cnt = clo = 0;
    for(int i = 1; i <= n; i++)
        if(!dfn[i])
            tarjan(i, -1);
}
int main(int argc, char **args){
    int n, m; scanf("%d%d", &n, &m);
    while(m--){
        int a, b; scanf("%d%d",&a, &b);
        G[a].push_back(b);
        G[b].push_back(a);
    }

    bcc_cut(n);
    
    for(int i = 1;i <= n;i ++){
        printf("%d %d %d\n", i, iscut[i], bccno[i]);
    }
return 0;

}
/*
7 8 
1 2
1 3
1 4
1 6
1 7
4 5
3 5
6 7
    */

3.4.2 边双联通分量EBC

#include 
using namespace std;

typedef long long ll;
typedef pair<int, int> pii;

const int N = 1e5 + 11;
const int M = 1e6 + 11;
const int MOD = 1e9 + 7;

vector<int>G[N];
int dfn[N], low[N], clo;
int ebc_cnt, ebcno[N];
int st[N];
void tarjan(int u,int fa){
    low[u] = dfn[u] = ++clo;  st[++*st] = u;
    for(int i = 0; i < G[u].size(); i++){
        int v = G[u][i];
        if(!dfn[v] && v != fa){
            tarjan(v, u);
            low[u] = min(low[u], low[v]);
            if(low[v] > dfn[u]){
                // 当前边是桥
            }
        }else 
            low[u] = min(low[u], dfn[v]);
    }
    if(dfn[u] == dfn[u]){
        ++ebc_cnt;
        do{
            ebcno[st[*st]] = ebc_cnt;
        }while(st[st[0]--] != u);
    }
}

void ebc(vector<int> G, int n ){
    memset(dfn, 0, sizeof(dfn));
    memset(low, 0, sizeof(low));
    clo = ebc_cnt = 0;
    memset(ebcno, 0, sizeof(ebcno));
    for(int i = 1; i <= n; i++){
        if(!dfn[i])
            tarjan(i, -1);
    }
}
int main(int argc, char **args){

return 0;
}

3.5 强联通分量 SCC

#include 
using namespace std;

typedef long long ll;
typedef pair<int, int> pii;

const int N = 1e5 + 11;
const int M = 1e6 + 11;
const int MOD = 1e9 + 7;

vector<int>ve[N];
bool instack[N];
int st[N];
int scc_cnt, sccno[N];
int clo, low[N], dfn[N];
void tarjan(int u){
    low[u] = dfn[u] = ++clo; st[++*st] = u; instack[u] = 1;
    for(int i = 0; i < ve[u].size(); i++){
        int v = ve[u][i];
        if(!dfn[v]){
            tarjan(v);
            if(low[u] > low[v]) low[u] = low[v];
        }else if(instack[v]) {
            if(low[u] > dfn[v]) low[u] = dfn[v];
        }
    }
    if(dfn[u] == low[u]) {  // 发现一个scc
        scc_cnt++;
        do{
            sccno[st[*st]] = scc_cnt;
        }while(st[st[0]--] != u);
    }
}

void scc_cut(int n){
    memset(instack, false, sizeof(bool) * (n + 1));
    memset(dfn, 0, sizeof(int) * (n + 1));    
    memset(low, 0, sizeof(int) * (n + 1));    
    memset(sccno, 0, sizeof(int) * (n + 1));
    st[0] = clo = scc_cnt = 0;

    for(int i = 1; i <= n; i++){
        if(!dfn[i])
            tarjan(i);
    }
}

int main(int argc, char **args){
   
return 0;
}

3.6 最小生成树 krus

#include  
using namespace std;

struct  Edge {
    int from,to,val;
}edge[MAXN];
bool  cmp(Edge  a,Edge b){
    return a.val<b.val;
}
int par[MAXN];
int n,m,k;

int Find(int x){  // 查找 x点所属的集合 ( 同时进行路径压缩)
    return x==par[x] ? x : par[x]=Find(par[x]);
}  

void join(int a,int  b){
    a=Find(a);
    b=Find(b);
    if(a!=b) par[a]=b;
}
 
void krus(){
    int  sum=0;
    sort(edge,edge+m,cmp);  // 排序

    for(int i=0;i<m;i++){ 
        Edge  e=edge[i];
        if(Find(e.from)!=Find(e.to)) {  // 如果该边的两个点分别属于各自连通块,那么这两个连通块就要进行连通,该边就要用上。 
            sum+=e.val;
            join(e.from,e.to);  // 连接 两个连通块
        }
    }
 
    printf("%d\n",sum); // 最小花费
}
int  main(){

    scanf("%d%d%d",&n,&m); // n 个点,m个边
    int a,b,c;
    for(int i=0;i<m;i++)
        scanf("%d%d%d",&edge[i].from,&edge[i].to,&edge[i].val);

    // 初始化 并查集
    for(int i=0;i<=n;i++)
        par[i]=i;
     
    krus();
    return 0;
}

3.7 最短路 djk

 dijkstra
 #include  
#include  
#define INF 0x3f3f3f  
#define max 100+10  

int dist[max],map[max][max],pre[max],visit[max];  
int n,m;  

void dijkstra()  
{  
    int i,j,start=1;  
    int next;   
    int mindist;//找最小的距离   
    memset(visit,0,sizeof(visit));//初始化   
    for(i=1;i<=n;i++)  
    {  
        dist[i]=map[start][i];  
    }  
    visit[1]=1;  
    for(i=2;i<=n;i++)  
    {  
        mindist=INF;  
        for(j=1;j<=n;j++)  
        {  
            if(visit[j]==0&&mindist>dist[j])  
            {  
                mindist=dist[j];  
                next=j;  
            }  
        }  
        visit[next]=1;  
        for(j=1;j<=n;j++)  
        {  
            if(visit[j]==0&&dist[next]+map[next][j]<dist[j])  
            {  
                dist[j]=dist[next]+map[next][j];  
            }  
        }  
    }  
    printf("%d\n",dist[n]);  
}   
int main()  
{  
    int i,j;  
    int x,y,c;  
    while(scanf("%d%d",&n,&m)&&(n!=0||m!=0))  
    {  
        for(i=1;i<=n;i++)  
        {  
            for(j=1;j<=n;j++)  
            {  
                if(i==j)  
                    map[i][j]=0;//这里很重要   
                else  
                     map[i][j]=INF;  
            }  
        }  

        while(m--)  
        {  
            scanf("%d%d%d",&x,&y,&c);  
            if(map[x][y]>c)//建议养成习惯加上可能会有重边的的情况   
            {  
                map[x][y]=map[y][x]=c;  
            }  
        }  
        dijkstra();  
    }  
    return 0;  
}    

6 查找

6.1 折半查找

int binary_search(int A[], int n, int key){ // 0 ~ n-1 
	int low, high, mid;
	low = 0, high = n - 1;
	while(low <= high){
		mid = (low + high) / 2;
		if(A[mid] == key) return mid;
		else if(A[mid] > key) high = mid - 1;
		else low = mid + 1;
	}
	return -1; // 没查到 
} 

6.3 串的模式匹配

int Index(String S,String T, int pos){ // A中pos后第一个与T匹配 
	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;
}

6.4 KMP

 
void getnxt(char *s, int *nxt){
    int i, j;
    j = nxt[0] = -1;
    i = 0; int n = strlen(s);
    while(i < n){
        while(j != -1 && s[i] != s[j]) j = nxt[j];
        ++j; ++i;
        if(s[j] == s[i]) nxt[i] = nxt[j];
        else nxt[i] = j;
    }
}

int kmp(char *s, char *t){
	int n = strlen(s), m = strlen(t);
	getnxt(t, next);
	int i = 0, j = -1;
	while(i < n){
		if(j == -1 || s[i] == t[j]) {
			++i; ++j;
			if(j == m - 1) return i - m + 1; // 找到t串
		}else 
			j = next[j]; 
	} 
	return -1;
}

6.5 散列表 拉链法

#include 
#include 

/*
    散列表的拉链法
    
    散列表 其实常用来 处理对应问题(eg:c++中的map, python中的字典)
    
    */
typedef int ElemType;
#define MAX_KEYS  11000   // 最大的 关键字值
typedef struct ArcNode{
    ElemType value;
    int key;
    struct ArcNode * next;
}ArcNode;


ArcNode *HashTable[MAX_KEYS];

bool search(int key, ElemType &values){
    ArcNode *p = HashTable[key % MAX_KEYS];
    while(p) {
        if(p->key == key) break;
         p = p->next;
    }
    if(p) values = p->value;
    return p != NULL;
}

bool Insert(int key, ElemType values){
    ElemType e;
    if(search(key, e)) return false; // 已经有了,不用插入
    ArcNode *p = (ArcNode*) malloc (sizeof(ArcNode));
    *p = {values, key, HashTable[key % MAX_KEYS]};
    HashTable[key % MAX_KEYS] = p;
}

// 删除 对于拉链法来说,和链表的删除操作一样(不带头节点的 链表删除,还是稍微有些繁琐) 
bool Del(int key){
    ElemType e; 
    if(!search(key, e)) return false; // 没有插入,删除失败
    ArcNode *p = HashTable[key % MAX_KEYS];
    if(p->key == key) HashTable[key % MAX_KEYS] = p->next; // 第一个结点就是要删除的结点,特判
    else{ // 其他情况 ,处理起来都一样(如果是带头节点的 链表,就不用特判了
        ArcNode *fa = p; p = p->next; 
        while(p && p->key != key) {
            p = p->next;
            fa = fa->next;
        }
        fa->next = p->next;
    }
    return true;
}

int main(){
    for(int i = 0; i < MAX_KEYS;i++) HashTable[i] = NULL;
    
     int op; scanf("%d", &op); // 操作的次数
    while(op--){
        int kind;
        scanf("%d", &kind);
        if(kind == 1) { // 插入 操作
            int key;
            ElemType value = 21;
            // scanf("%d %1s", &key, &value);
            scanf("%d %d", &key, &value);
            // printf("insert : %d %c\n", key, value);
            Insert(key, value);

        }else if(kind == 2){//  删除操作
            int key; scanf("%d", &key);
            Del(key);         
        }else {
            int key; scanf("%d", &key);
            ElemType value;
            if(search(key, value))
                printf("%d\n", value);
        }
    }
    return 0;
}
/*
6
1 2 1111
1 3 22222
3 2 
1111
3 3
22222
2 2
3 2
    */

6.6 BST 二叉搜索树

#include 
#include 
/*
    BST (二叉搜索树)
    二叉树形态 会由于插入而导致 退化为链,从而导致
    时间复杂度暴增,所以针对这个问题,后面又提出了AVL,始终保持
    二叉树高度(保持二叉树高度,有很多方法,红黑树、伸展树、平衡树等等
    ,目的都是为了保持二叉树的高度)
    */
typedef char ElemType;
typedef struct BNode{
    ElemType data;
    BNode *lchild, *rchild;
}BNode, *BSTree;

BSTree Insert(BSTree T, ElemType e){
    if(!T) {
        T = (BNode*) malloc (sizeof(BNode));
        *T = {e, NULL, NULL};
        return T;
    }
    if(e < T->data) 
        T->lchild = Insert(T->lchild, e);
    else if(e >T->data) 
        T->rchild = Insert(T->rchild, e);
    else {
        //插入失败
    }
}
bool reseach(BSTree T, ElemType e){
    if(!T) return false;
    if(e <T->data ) 
        return reseach(T->lchild, e );
    else if(e >T->data)
        return reseach(T->rchild, e);
    else 
        return true;
}
BSTree Delete(BSTree T, ElemType e){
    if(!T){
        // 没有 可删除元素
        return NULL;
    }
    if(e < T->data) 
        T->lchild = Delete(T->lchild, e);
    else if(e > T->data)
        T->rchild = Delete(T->rchild, e);
    else {
        if(!T->lchild && !T->rchild)  // 叶子结点
            return NULL;
        else if(!T->lchild)  // 只有右孩子
            return T->rchild;
        else if(!T->rchild)  // 只有左孩子
            return T->lchild;
        else {  // 左右孩子都有

            BNode*p = T->lchild; // 找前驱
            while(p->rchild) p = p->rchild;
            T->data = p->data; // 把值复制过来,继续递归左子树

            return Delete(T->lchild, e); // 问题转化为 前两种情况
        }
    }
}

int main(){
       
    return 0;
}

6.7 AVL 平衡二叉树

#include 
#include 
#include 
#include 
using namespace std;

typedef int ElemType;
typedef struct BNode{
    ElemType data;
    struct BNode *lchild, *rchild;
}BNode, *AVLTree;

int getH(BNode *root){
    if(root == NULL) return 0;
    return max(getH(root->lchild), getH(root->rchild)) + 1;
}
BNode *RR(BNode *root){
    BNode * t = root->rchild;
    root->rchild = t->lchild;
    t->lchild = root;
    return t;
}
BNode *LL(BNode *root){
    BNode *t = root->lchild;
    root->lchild = t->rchild;
    t->rchild = root;
    return t;
}
BNode *LR(BNode *root){
    root->lchild = RR(root->lchild);
    return LL(root);
}
BNode *RL(BNode *root){
    root->rchild = LL(root->rchild);
    return RR(root);
}

BNode *Insert(BNode *root,ElemType e){
    if(root == NULL){
        root = (BNode*) malloc(sizeof(BNode));
        root->lchild = root->rchild = NULL;
        root->data = e;
    }else if(e < root->data){
        root->lchild = Insert(root->lchild, e);
        if((getH(root->lchild) - getH(root->rchild) )== 2) {
            if(e < root->lchild->data)   
                root = LL(root);
            else 
                root = LR(root);
        }
    }else {
        root->rchild = Insert(root->rchild, e);
        if((getH(root->rchild) - getH(root->lchild) )== 2){
            if(e < root->rchild->data)
                root = RL(root);
            else 
                root = RR(root);
        }
    }
    return root;
}
bool Search(AVLTree T, ElemType e){
    if(T == NULL) return false;
    if(e < T->data) 
        return Search(T->lchild, e);
    else if(e >T->data) Search(T->rchild, e);
    else 
        return true;
}
BNode *Delte(AVLTree T, ElemType e){
    if(T == NULL){
        exit(0);
    }
    if(e < T->data){
        T->lchild = Delte(T->lchild, e);
        if(getH(T->rchild) - getH(T->lchild) == 2) {
            BNode *t = T->rchild;
            if(getH(t->rchild) >= getH(t->lchild)) 
                T = RR(T);
            else 
                T = RL(T);
        }
    }else if(e > T->data){
        T->rchild = Delte(T->rchild, e);
        if(getH(T->lchild) - getH(T->rchild) == 2){
            BNode *t = T->lchild;
            if(getH(t->lchild) >= getH(t->rchild)) 
                T = LL(T);
            else 
                T = LR(T);
        }
    }else {
        if(T->lchild == NULL && T->rchild == NULL){
            free(T);
            return NULL;
        }else if(T->lchild == NULL) {
            free(T);
            return T->rchild;
        }else if(T->rchild == NULL) {
            free(T);
            return T->lchild;
        }else {
            BNode *p = T->lchild;
            while(p->rchild) p = p->rchild; // 找到前驱
            swap(T->data,p->data);  // 交换与前驱的值,递归删除左子树,这样就转化为前面三种情况了
            T->lchild = Delte(T->lchild, e); 
        }
    }
    return T;
}

int main(){
    AVLTree avl = NULL;
    int n; scanf("%d", &n);
    int t;
    for(int i = 0; i < n; i++){
        scanf("%d", &t);
        avl = Insert(avl, t);
    }
    printf("%d\n", avl->data);
    int q ; scanf("%d", &q);
    while(q--){
        scanf("%d", &t);
        avl = Delte(avl, t);
        printf("%d\n", avl->data);
    }
    
    return 0;   
}

/*
5
5 4 3 2 1 
4
4 1 2 3 

*/

6.8 键树(字典树)

#include 
#include 
#include 

/*
    键树(字典树)
    
    */

#define MAX 26
typedef struct TNode{
    char ch;  // 存的字符
    bool end; // 是否为一个单词的结尾
    int count; // 有多少个字符串经过这个结点 
    TNode *son[MAX]; // 下属的 MAX个 指针
}TNode, *Trie;

bool research(Trie T, char *s){
    int pos = 0; int len = strlen(s);
    TNode * p = T;
    while(p && pos < len) 
        p = p->son[s[pos++] - 'a']; 
    
    return pos == len;
}

void IninNode(Trie &T){
    T = (Trie) malloc(sizeof(TNode));
    for(int i = 0; i < MAX; i++){
        T->son[i] = NULL;
    }
    T->count = 0;
    T->end = false;
}
void Insert(Trie &T, char *s){
    if(!T){  // 字典树根节点
        IninNode(T);
        T->count = 1;
    }
    
    Trie p = T; int pos = 0; int len = strlen(s);
    while(p && pos < len){
        p = p->son[s[pos++] - 'a'];
        if(!p){  // 新建一个结点
            IninNode(p);
        }
        p->count++;
    } 
    p->end = true;
}
bool Del(Trie T, char *s){
    if(!research(T, s)) return false;

    int pos = 0; int len = strlen(s);
    TNode * p = T, *q;
    while(p && pos < len) {
        if(!p->count) q = p;
        p = p->son[s[pos++] - 'a']; 
        p->count --; 
        free(q);
    }
    return pos == len;
}

int main(){
    

    return 0;
}

7 排序

7.2 插入排序

7.2.1 简单插入排序


void InsertSort(int A[], int n){ // 1 ~ n
	for(int i = 2; i <= n; i++){
		if(A[i] < A[i - 1])
			A[0] = A[i];  // 设置标兵 这样最后一定会中断。 
			for(int j = i - 1; A[j] > A[0]; j--){
				A[j + 1] = A[j];
			A[j + 1] = A[0];
		}
		
	}
} 


7.2.2 折半插入排序

void Insert(int A[], int n ){
	int i, j, low, high, mid;
	for(int 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;
		}
		 // 二分upper_bound   找到位置 (high + 1) 
		for(int j = i - 1; j >= high + 1; j--) // 移位 
			A[j + 1] = A[j];
		A[high + 1] = A[0];
	}
}

7.2.3 希尔排序

void shellSort(int A[], int n){
	int i, j, gap;
	for(gap = n / 2; gap > 0; gap /= 2){ // 增量
	 
		for(i = gap + 1; i <= n; i++){
			A[0] = A[i];
			for(j = i - gap; j > 0 && A[j] > A[0]; j -= gap) // 对同一组的 进行简单插入排序 
				A[j + gap] = A[j];
		}
		A[j + gap] = A[0];
	}
}

7.3 交换排序

7.3.1 冒泡排序


void BubbleSort(int A[], int n){
	bool flag;
	for(int i = 1; i <= n; i++){
		flag = false;
		for(int j = n - 1; j >= i; j--){ // 不断交换 
			if(A[j] > A[j + 1]) {
				swap(A[j], A[j + 1]); 
				flag = true;
			}
		}
		
		if(!flag) break;
	}
}

7.3.2 快速排序

void qsort(int A[], int low, int high){
	if(low < 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;
		
		qsort(A, low, low - 1); // 继续递归 
		qsort(A, low + 1, high);
	}
}

7.4 选择排序

7.4.1 简单选择排序

/*
		第i趟选择i~(n-1)中最小值交换 
	*/
void SelectSort(int A[], int n){  // 0 - (n-1)

	for(int i = 0; i < n; i++){
		int mn = i;
		for(int j = i + 1; j < n; j++){
			if(A[mn] > A[j])
				mn = j;
		}
		if(mn != i) swap(A[i], A[mn]);
	} 
} 

7.4.2 堆排序

/*
	构造 大根堆
	利用完全二叉树的性质
	 
	*/
void BuildMaxHeap(int A[], int len){  // 1 - n
	for(int i = len / 2; i > 0; i--) // 从最后一个结点的父节点开始,不断调整
		AdjustDown(A, i, len);
}

void AdjustDown(int A[], int fa, int len){
	A[0] = A[fa];
	for(int i = fa * 2; i <= len; i *= 2){
		if(i < len && A[i] < A[i + 1])
			i++;                     // 取key较大的子节点 下标 
			
		if(A[0] >= A[i]) break;  // 位置找到 
		else {
			A[fa] = A[i];			// 调整位置 
			fa = i;
		}	
	}
	A[fa] = A[0];
}
void HeapSort(int A[], int len){
	BuildMaxHeap(A, len);
	for(int i = len; i > 1; i--){ // 每次根 是最大值,与A[i]交换后,重新调整即可。 
		swap(A[i], A[1]);
		AdjustDown(A, 1, i - 1);
	}
}
void Delete(int A[], int &len){ // 注意  len 的 &,因为删除后长度要变.
	 swap(A[1], A[len]);   // 与最后一个元素交换 
	 len--;
	 AdjustDown(A, 1, len);	// 重新调整 
}
void insert(int A[],int k){ // A[k] 中存着 新插入的值 
	A[0] = A[k];
	for(int p = k / 2; p > 0 && A[p] < A[0];){ // p 为 k 节点的父节点,  
		A[k] = A[i];    // 不断向上 调整 
		k = i; 
		p = k / 2;
	}
	
	A[k] = A[0];
}

7.4 归并排序


int *B = (int *) malloc(sizeof(int) * (n + 1));  // 辅助数组 
void Merge(int A[], int low, int mid, int high){
	/*
		A[low ~ mid] 和 A[mid+1 ~ high] 合并为一个有序的序列 
	*/
	for(int i = low; i <= high; i++)
		B[i] = A[i];
	int i, j, k;
	for(i = low, j = mid + 1, k = low; i <= mid && j <= high; k++){
		if(B[i] < B[j])
			A[k] = B[i++];
		else 
			A[k] = B[j++];
	} 
	while(i <= mid) A[k++] = A[i++];
	while(j <= mid) A[k++] = A[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);
	}
}

你可能感兴趣的:(结构的模版)