数据结构与算法基础笔记

这篇笔记详细介绍了数据结构中的链表、顺序栈、链栈、循环队列、双向链表等操作,包括创建、合并、遍历和删除等。此外,还涵盖了二叉树的各种遍历方法以及哈夫曼树的构造。同时,讲解了图的邻接矩阵和邻接表表示,并实现了深度优先搜索和广度优先搜索。这些内容对于理解数据结构与算法的基础至关重要。
摘要由CSDN通过智能技术生成
以下是本人在学习数据结构与算法时的笔记
//数据结构与算法基础
-------------------------------------------------------
链表
struct Ploy{
    int m_coe = 0;
    int m_index = 0;
};

typedef struct LNode{
    Ploy date;
    LNode *prior = NULL;
    LNode *next = NULL;
}LNode,*LinkList;
//建立链表
void setLinkList(LinkList &L){
    LNode *p,*q;
    q = L;
    int coe,index,n;
    cout << "输入n:";
    cin >> n;
    while (n--){
        cin>>coe>>index;
        if (index<0) break;
        p = new LNode;
        p->date.m_coe = coe;
        p->date.m_index = index;
        q->next = p;
        q = q->next;
    }
}
//合并链表
void combine(LinkList &L,LinkList &S,LinkList &T){
    LNode *p,*q,*r;
    p = L->next,q = S->next,r = T;
    while (p && q){
        if (p->date.m_index < q->date.m_index){
            r ->next= p;
            p = p->next;
            r = r->next;
        }else if (p->date.m_index > q->date.m_index){
            r ->next= q;
            q = q->next;
            r = r->next;
        }else{
            p->date.m_coe+=q->date.m_coe;
            if (p->date.m_coe==0){
                LNode *s,*t;
                s = p,t = q;
                p = p->next;
                q = q->next;
                delete s;
                delete t;
            }else {
                r->next = p;
                LNode *s;
                s = q;
                q = q->next;
                p = p->next;
                r = r->next;
                delete s;
            }

        }
    }
    r->next= p?p:q;
    delete S;
    S = NULL;
}
//打印链表
void printLinkList(LinkList &L){
    LNode *p;
    p = L->next;
    while (p){
        cout<<p->date.m_coe<<" "<<p->date.m_index<<" ";
        p = p->next;
    }
}
//尾指针循环链表
void CircleLinkList(LinkList &L){
    LNode *p,*q;
    q = L;
    int n;
    cout <<"输入尾指针循环链表长度n:";
    cin >> n;
    while (n--){
        p = new LNode;
        cin >> p->date.m_coe >> p->date.m_index;
        q->next = p;
        q = p;
    }
    q->next = L;
    L = q;
}

//循环链表合并
void CombineCircleLinkList(LinkList &L,LinkList &S){
    LNode *r;
    r = L->next;
    L->next = S->next->next;
    S->next = r;
    delete S->next;
}
//双向链表
void DoLinkList(LinkList &L){
    LNode *p,*q;
    q = L;
    q->prior = NULL;
    int n;
    cout << "输入双向链表的长度n:";
    cin >> n;
    while (n--){
        p = new LNode;
        cin >> p->date.m_coe >> p->date.m_index;
        p->prior = q;
        q->next = p;
        q = p;
    }
//循环双向链表
//    q->next = L;
//    L->prior = q;
}
//------------------------------------------------------
//顺序栈
#define MAXSIZE 100
typedef struct {
    int *base = NULL;
    int *top = NULL;
    int stackSize = 0;
}SqStack;
//初始化空栈
void initStack(SqStack &S){
    S.base = new int[MAXSIZE];
    if(S.base == NULL){
        cout <<"内存分配失败!"<<endl;
        exit(-1);
    }
    S.top = S.base;
    S.stackSize = MAXSIZE;
}
//判断栈是否为空,空则返回1,否则返回0;
int StackEmpty(SqStack &S){
    return S.base==S.top;
}
//栈的长度
int StackLength(SqStack &S){
    return S.top-S.base;
}
//清空栈
void ClearStack(SqStack &S){
    if (S.base) S.top = S.base;
}
//销毁栈
void DestroyStack(SqStack &S){
    if (S.base){
        delete []S.base;
        S.stackSize = 0;
        S.base = S.top = NULL;
    }
}
//入栈
void Push(SqStack &S,int e){
    if (S.top-S.base == S.stackSize){
        cout<< "栈已满"<<endl;
        exit(-1);
    }
    *S.top++ = e;
}
//出栈
void Pop(SqStack &S,int &e){
    if (S.top==S.base){
        cout <<"栈已空"<<endl;
        exit(-1);
    }
    e = *--S.top;
}
//---------------------------------------------------
//链栈 运算受限的链表 只能在链表头部操作
typedef struct StackNode{
    int date;
    StackNode *next;
}StackNode,*LinkStack;
//链栈初始化
void initLinkStack(LinkStack &S){
    S = NULL;
}
//判断链栈是否为空
int StackEmpty(LinkStack &S){
    return S==NULL;
}
//链栈的入栈
void Push(LinkStack &S,int e){
    StackNode *p;
    p = new StackNode;
    p->date = e;
    p->next = S;
    S = p;
}
//链栈的出栈
void Pop(LinkStack &S,int &e){
    if (S == NULL){
        cout << "链栈已空,无法出栈"<<endl;
        exit(-1);
    }
    StackNode *p;
    e = S->date;
    p = S;
    S = S->next;
    delete p;
}
//取栈顶元素
int GetTop(LinkStack &S){
    if (S==NULL){
        cout << "栈为空"<<endl;
        exit(-1);
    }else return S->date;
}
//--------------------------------------------------------------
//循环队列
#define QUEUEMAXSIZE 100

struct SqQueue{
    int *base = NULL;
    int front = 0;
    int rear = 0;
};
//初始化队列
void initQueue(SqQueue &Q){
    Q.base = new int[QUEUEMAXSIZE];
    if (Q.base==NULL){
        cout<<"内存分配失败"<<endl;
        exit(-1);
    }
    Q.front = Q.rear = 0;
}
//判断队是否为空
int QueueEmpty(SqQueue &Q){
    return Q.front==Q.rear;
}
//求队列长度
int QLength(SqQueue &Q){
    return (Q.rear-Q.front+QUEUEMAXSIZE)%QUEUEMAXSIZE;
}
//循环队列入队
void EnQueue(SqQueue &Q,int e){
    if ((Q.rear+1)%QUEUEMAXSIZE == Q.front){
        cout << "队列已满,入队失败"<< endl;
        exit(-1);
    }
    Q.base[Q.rear] = e;
    Q.rear = (Q.rear+1)%QUEUEMAXSIZE;
}
//循环队列出队
void DeQueue(SqQueue &Q,int &e) {
    if (Q.front == Q.rear) {
        cout << "队列已空,出队失败" << endl;
        exit(-1);
    }
    e = Q.base[Q.front];
    Q.front = (Q.front + 1) % QUEUEMAXSIZE;
}
//取循环队列首元素
int GetHead(SqQueue &Q){
    if (Q.front == Q.rear){
        cout << "队列已空,取首元素失败" << endl;
    }
    return Q.base[Q.front];
}
//---------------------------------------------------------
//链队
typedef struct QNode{
    int date = 0;
    QNode *next = NULL;
}QNode,*QueuePtr;
//链队头指针 尾指针
typedef struct{
    QueuePtr front = NULL;
    QueuePtr rear = NULL;
}LinkQueue;
//初始化链队
void initLinkQueue(LinkQueue &Q){
    Q.front = Q.rear = new QNode;
    if (Q.front == NULL){
        cout << "内存分配失败" << endl;
        exit(-1);
    }
    Q.front->next = NULL;
}
//销毁链队
void DestroyLinkQueue(LinkQueue &Q){
    while (Q.front){
        Q.rear = Q.front->next;
        delete Q.front;
        Q.front = Q.rear;
    }
}
//入队
void EnLinkQueue(LinkQueue &Q,int e){
    QNode *p;
    p = new QNode;
    if (p == NULL){
        cout << "内存分配失败" << endl;
        exit(-1);
    }
    p->date = e;
    p->next = NULL;
    Q.rear->next= p;
    Q.rear = p;
}
//出对
void DeLinkQueue(LinkQueue &Q,int &e){
    if (Q.front == Q.rear){
        cout << "队列已空,出队失败" << endl;
        exit(-1);
    }
    QNode *p;
    p = Q.front->next;
    e = p->date;
    Q.front->next = p->next;
    if (p == Q.rear) Q.rear = Q.front;  //删除的是最后节点
    delete p;
}
//取队列首元素
void GetHead(LinkQueue &Q,int &e){
    if (Q.front == Q.rear){
        cout << "队列已空,取元失败" << endl;
        exit(-1);
    }
    e = Q.front->next->date;
}
//---------------------------------------------------------------
//串
//串的顺序储存结构
#define MAXLENGTH 255
typedef struct{
    char ch[MAXLENGTH+1];
    int length;
}SString;
//串的链式储存结构--块链
#define CHUNKSIZE 80
typedef struct Chunk{
    char ch[CHUNKSIZE];
    struct Chunk *next;
}Chunk;

typedef struct{
    Chunk *head,*tail;
    int curlen;     //串的当前长度
}LString;
//BF算法----暴力穷举法
int Index_BF(SString S,SString T){  //主串,子串
    int i=1,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;
}
//KMP算法
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];
    }
}

int Index_KMP(SString S,SString T,int pos,const int next[]){
    int i=pos,j=1;  //pos 开始匹配位置
    while (i<=S.length && j<=T.length){
        if (j==0 || S.ch[i]==T.ch[j]) i++,j++;
        else j = next[j]; //i不变,j后退
    }
    if (j>T.length) return i-T.length;
    else return 0;
}
//--------------------------------------------------------------------
//二叉树
//总边数为 B B = n-1 = n2*2+n1*1
// n = n2*2+n1*1+1 又 n = n2+n1+n0
//即n0 = n2+1 叶子数目为度为2的结点数+1

//二叉树顺序储存表示
typedef int SqBiTree[MAXSIZE];
SqBiTree bt;
//二叉树链表储存结构
typedef struct BTNode{
    int data;
    BTNode *LChild,*RChild;//*parent
}BTNode,*BiTree;
//遍历二叉树
void visit(BiTree &T){
    cout << T->data;
}
//先序 DLR 递归
void PreOrderTraverse(BiTree &T){
    if(T==NULL) return;
    else{
        visit(T);
        PreOrderTraverse(T->LChild);
        PreOrderTraverse(T->RChild);
    }
}
//中序 非递归
void InOrderTraverse(BiTree T){
    SqStack S;
    BiTree p,q;
    initStack(S);
    p = T;
    while (p || !StackEmpty(S)){
        if (p){
            Push(S,p); //入栈
            p = p->LChild;
        }else{
            Pop(S,q);  //出栈
            cout << q->data;
            p = q->RChild;
        }
    }
}
//层次遍历
typedef struct{
    BTNode data[MAXSIZE];
    int front,rear;
}TreeSqQueue;
void LevelOrder(BTNode *b){
    BTNode *p;
    TreeSqQueue *qu;
    initQueue(qu);  //初始化队列
    EnQueue(qu,b);  //根结点指针进入队列
    while (!QueueEmpty(qu)) {   //队不为空,则循环
        DeQueue(qu, p); //出队结点p
        cout << p->data;
        if (p->LChild != NULL) EnQueue(qu, p->LChild);
        if (p->RChild != NULL) EnQueue(qu, p->RChild);
    }
}
//建立二叉树
//            A
//        B
//     C     D
//         E   F
//          G
//ABC##DE#G##F###
void CreateBiTree(BiTree &T){
    char ch;
    cin>>ch;
    if (ch == '#') T = NULL;
    else{
        if (!(T = new BTNode)) exit(-1);
        T->data = ch;
        CreateBiTree(T->LChild);
        CreateBiTree(T->RChild);
    }
}
//复制二叉树
int Copy(BiTree T,BiTree &NewT){
    if (T==NULL){
        NewT = NULL;
        return 0;   //如果是空树返回0
    }else{
        NewT = new BTNode;
        NewT->data = T->data;
        Copy(T->LChild,NewT->LChild);
        Copy(T->LChild,NewT->RChild);
        return 1;
    }
}
//计算二叉树深度
//n个结点时间复杂度为log2N+1
//左子树深度 m 与 右子树深度 n 的较大者 +1
int Depth(BiTree T){
    int m,n;
    if (T==NULL) return 0;
    else {
        m = Depth(T->LChild);
        n = Depth(T->RChild);
        return max(m,n)+1;
    }
}
//计算二叉树结点
int NodeCount(BiTree T){
    if (T==NULL) return 0;
    else return NodeCount(T->LChild)+NodeCount(T->RChild)+1;
}
//计算二叉树叶子结点数
int LeadCount(BiTree T){
    if (T==NULL) return 0;
    else if (T->LChild==NULL && T->RChild==NULL) return 1;
    else return LeadCount(T->LChild)+LeadCount(T->RChild);
}
//线索二叉树
//LTag(RTag) == 0 指向该结点的左(右)孩子
//              1           前驱(后继)
typedef struct BiThrNode{
    int data;
    int LTag,RTag;
    BiThrNode *LChild,*RChild;
}BiThrNode,*BiThrTree;
//可增设一个头结点
//其LTag = 0,LChild指向根结点
//其RTag = 0,RChild指向遍历序列中最后一个结点
//遍历序列中第一个结点的LC域和最后一个结点的RC域都指向头结点
//------------------------------------------------------------
//树
//双亲表示法
//每个结点两个域 数据域 双亲域(双亲结点在数组中的位置)
typedef struct PTNode{
    int data;
    int parent;
} PTNode;
#define MAX_TREE_SIZE 100
typedef struct{
    PTNode nodes[MAX_TREE_SIZE];
    int r,n;    //根结点位置和结点个数;
} PTree;
//孩子链表
//孩子结点结构
typedef struct CTNode{
    int child;
    CTNode *next;
} *ChildPtr;
//双亲结点结构
typedef struct{
    int data;
    ChildPtr firstChild;    //孩子链表头指针
} CTBox;
//树结构
typedef struct {
    CTBox nodex[MAX_TREE_SIZE];
    int n,r;
}CTree;     //可增加双亲域
//孩子兄弟表示法(二叉树表示法,二叉树链表表示法)
typedef struct CSNode{
    int data;
    CSNode *firstChild,*nextSibling;
} CSNode,*CSTree;
//将树转换为二叉树
//兄弟相连留长子 去掉原来右孩线
//森林转换为二叉树
//树变二叉根相连
//-------------------------------------
//哈夫曼树(最优二叉树):带权路径长度(WPL)最短的二叉树
//权:树中结点的数值
//结点的带权路径长度:根到该结点的 路径长度 与该结点的 权 的乘积
//数的带权路径长度:树中所有叶子结点的带权路径长度之和
//构造哈夫曼树:1、构造森林全是根 2、选用两小造新树
//           3、删除两小添新人 4、重复2、3剩单根
//哈夫曼构造算法的实现 采用顺序储存结构 共2n-1个结点
typedef struct{
    int weight;
    int parent,lch,rch;
} HTNode,*HuffmanTree;
//构造哈夫曼树
void select(HuffmanTree &HT,int len,int &s1,int &s2){

}
void CreatHuffmanTree (HuffmanTree &HT,int n){
    if (n<=1) return;
    int m = 2*n-1;
    HT = new HTNode[m+1];   //0号单元未用 HT[m]表示根结点
    for (int i = 1; i <= m; ++i) {
        HT[i].lch = 0;
        HT[i].rch = 0;
        HT[i].parent = 0;
    }
    for (int i = 1; i <= n; ++i) {
        cin >> HT[i].weight;    //输入权
    }
    int s1,s2;
    for (int i = n+1; i <= m; ++i) {
        select(HT,i-1,s1,s2); //寻找两个最小结点的下标
        HT[s1].parent = HT[s2].parent = i;
        HT[i].lch = s1,HT[i].rch = s2;
        HT[i].weight = HT[s1].weight + HT[s2].weight;
    }
}
//哈夫曼编码
typedef struct HuffmanCode{
    char data;
    char *code;
}*pHuffmanCode;
void CreatHuffmanCode(HuffmanTree HT,pHuffmanCode &HC,int n){
    HC = new HuffmanCode[n+1];
    char *cd;
    cd = new char[n];
    for (int i = 1; i <= n; ++i) {
        int start = 0,c = i,f = HT[i].parent;
        while (f!=0){
            start++;
            if (HT[i].lch == c) cd[start] = '0';
            else cd[start] = '1';
            c = f,f = HT[f].parent;
        }
        cd[++start] = '\0';
        strrev(cd); //反转编码
        HC[i].code = new char[start];
        strcpy(HC[i].code,cd);
    }
    delete cd;
}
//-----------------------------------------------------------------------
//图
//邻接矩阵
#define MaxInt 32767    //表示极大值,即∞
#define MVNum 100   //最大顶点数
typedef struct{
    char vex[MVNum];    //顶点表
    int arcs[MVNum][MVNum];     //邻接矩阵
    int vexNum,arcNum;      //图的当前点数和边数
} AMGraph;
//创建无向网
int LocateVex(AMGraph &G,char v){
    for (int i = 0; i < G.vexNum; ++i) {
        if (G.vex[i] == v) return i;
    }
    return -1;
}
void CreateUDM(AMGraph &G){
    cin >> G.vexNum >> G.arcNum;    //总点数 总边数
    for (int i = 0; i < G.vexNum; ++i) {
        cin >> G.vex[i];    //输入点的信息
    }
    for (int i = 0; i < G.vexNum; ++i) {
        for (int j = 0; j < G.vexNum; ++j) {
            G.arcs[i][j] = MaxInt;  //所有边的权置为极大值
        }
    }
    char v1,v2;
    int w;
    for (int k = 0; k < G.arcNum; ++k) {
        cin >> v1 >> v2 >> w;   //一条边的两个顶点及边的权值
        int i = LocateVex(G,v1);
        int j = LocateVex(G,v2);
        G.arcs[i][j] = w;
        G.arcs[j][i] = G.arcs[i][j];
    }
}
//------------------------------------------------------------
//邻接表
struct ArcNode{     //边结点
    int adjVex;     //该边所指向的顶点的位置
    ArcNode *nextArc;   //指向下一条边的指针
    int info;       //和边相关的信息
};
typedef struct VNode{
    char data;  //顶点信息
    ArcNode *firstArc;  //指向第一条依附该顶点的边的指针
} VNode,AdjList[MVNum];
typedef struct{
    AdjList vertices;
    int vexNum,arcNum;
} ALGraph;
//创建无向网
int LocateVex(ALGraph &G,char v){
    for (int i = 0; i < G.vexNum; ++i) {
        if (G.vertices[i].data == v) return i;
    }
    return -1;
}
void CreateUDG(ALGraph &G){
    cin >> G.vexNum >>G.arcNum;
    for (int i = 0; i < G.vexNum; ++i) {
        cin >> G.vertices[i].data;
        G.vertices[i].firstArc = NULL;
    }
    char v1,v2;
    for (int k = 0; k < G.arcNum; ++k) {
        cin >> v1 >> v2;
        int i = LocateVex(G,v1);
        int j = LocateVex(G,v2);
        ArcNode *p1,*p2;
        p1 = new ArcNode;
        p1->adjVex = j;
        p1->nextArc = G.vertices[i].firstArc;   //头插法
        G.vertices[i].firstArc = p1;
        p2 = new ArcNode;
        p2->adjVex = i;
        p2->nextArc = G.vertices[j].firstArc;
        G.vertices[j].firstArc = p2;
    }
}
//邻接矩阵多用于稠密图 邻接表多用于稀疏图
//采用 邻接矩阵 表示图的 深度优先 搜索遍历
int visited[100];  //第i个顶点已访问则 visited[i] = 1;否则为0;
void DFS(AMGraph G,int v){
    cout << v;
    visited[v] = true;
    for (int w = 0; w < G.vexNum; ++w) {
        if (G.arcs[v][w]!=0 && visited[w]==0){ //w是v的邻接点且w为2访问
            DFS(G,w);
        }
    }
}
//广度优先
int FirstAdjVex(ALGraph G,int u){
    return G.vertices[u].firstArc->adjVex;
}
int NextAdjVex(ALGraph G,int u,int w){
    ArcNode *p;
    p = G.vertices[u].firstArc;
    while (w != p->adjVex){
        p = p->nextArc;
    }
    if (p->nextArc == NULL) return -1;
    else return p->nextArc->adjVex;
}
void BFS(ALGraph G,int v){
    cout << v;
    visited[v] = true;
    SqQueue Q;
    initQueue(Q);
    EnQueue(Q,v);
    int u;
    while (!QueueEmpty(Q)){
        DeQueue(Q,u);
        for (int w = FirstAdjVex(G,u); w >= 0; w = NextAdjVex(G,u,w)) {
            if (visited[w]==0){
                cout << w;
                visited[w] = true;
                EnQueue(Q,w);
            }
        }
    }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值