dsa-c/cpp 数组/链表/栈/队列

1. 线性表

顺序表

模板

// 静态数组
#define MaxSize 10
typedef struct{
    ElemType data[MaxSize]; //ElemType表示任意数据类型 
    int length;
}SqList;

例子

// 静态分配
#include <stdio.h>

#define MaxSize 10
typedef struct
{
    int data[MaxSize];
    int length;
}SqList;

void InitList(SqList *L)
{
    for (int i=0;i<MaxSize;i++)
    {
        L->data[i]=0;
    }
    L->length=0;
}

int main()
{
    SqList L; //等价于Struct L
    InitList(&L);

    for (int i=0;i<MaxSize;i++)
    {
       printf("%d\t",L.data[i]);
    }
    printf("\n%d\n",L.length);
    return 0;
}
//动态分配
#define InitSize 10
typedef struct 
{
    int *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)
{
    printf("%p\n",L->data); //00000000006916A0
    int *p=L->data;
    printf("%p\n",p); //00000000006916A0
    L->data=(int*)malloc((L->MaxSize+len)*sizeof(int)); //0000000000691700 ,就把L->data当做一个指针就行了
    printf("%p\n",L->data);
    for (int i=0;i<L->length;i++)
    {
        L->data[i]=p[i];
    }
    L->MaxSize+=len;
    free(p);
}

int main()
{
    SeqList L;
    InitList(&L);
    // for (int i=0;i<InitSize;i++)
    // {
    //    printf("%d\t",L.data[i]);
    // }
    // printf("\n%d\n",L.length);
    IncreaseSize(&L,5);
    return 0;
}

插入/删除

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

#define MaxSize 10

typedef struct
{
    int data[MaxSize];
    int length;
} SqList;

void InitList(SqList *L)
{
    for (int i = 0; i < MaxSize; i++)
    {
        L->data[i] = 0;
        // printf("%d\t",L->data[i]);
    }
    // printf("\n");
    L->length = 0;
}

// void ListInsert(SqList *L,int i,int e)
// {
//     for (int j=L->length;j>=i;j--)
//     {
//         L->data[j]=L->data[j-1];
//     }
//     L->data[i-1]=e;
//     L->length++;
// }

// version 2
// c99支持bool #include <stdbool.h>
bool ListInsert(SqList *L, int i, int e)
{
    if (i < 1 || i > L->length + 1 || 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;
}

bool ListDelete(SqList *L, int i, int *p)
{
    if (i > L->length)
        return false;
    *p = L->data[i - 1];

    int end=L->length-1;

    for (int j = i; j < L->length; j++)
    {
        L->data[j - 1] = L->data[j];
    }
    L->length--;

    L->data[end]=0; // 避免尾部冗余

    return true;
}

int main()
{
    SqList L;

    InitList(&L);

    // some insert code...
    for (int i = 1; i < 8; i++)
    {
        ListInsert(&L, i, i);
    }

    bool flag_insert = true;
    flag_insert = ListInsert(&L, 1, 13);


    if (!flag_insert)
    {
        printf("【error】:insert failed\n");
        return 0;
    }
    else
    {

        for (int i = 0; i < MaxSize; i++)
        {
            printf("%d\t", L.data[i]);
        }
        printf("\n");
    }


    // 返回删除的元素
    int e = -1;
    bool flag_del = true;
    flag_del = ListDelete(&L, 3, &e);

    if (!flag_del)
    {
        printf("【error】:delete failed\n");
        return 0;
    }
    else
    {
        printf("delete item: %d\n", e);
        for (int i = 0; i < MaxSize; i++)
        {
            printf("%d\t", L.data[i]);
        }
        printf("\n");
    }

    return 0;
}

查找

  • 按位查找

静态分配

#define MaxSize 10
typedef struct
{
	int data[MaxSize];
}SqList;

// 指针传递
int GetItem(SqList *L,int i)
{
	return L->data[i-1];
}

// version 2
// 引用传递
int GetItem(SqList &L,int i)
{
	return L.data[i-1]
}

动态分配

#define MaxSize 10
typedef struct
{
	int *data;
}SqList;

// 指针传递
int GetItem(SqList *L,int i)
{
	return L->data[i-1];
}

void InitList(SeqList *L)
{
    L->data=(int*)malloc(InitSize*sizeof(int));
}
  • 按值查找
// 利用for 循环判定

链表

单链表

模板

struct Node
{
    dataType data;
    struct Node *next; // 用于指向下一个节点
};

struct Node *p=(struct Node *)malloc(sizeof(struct Node));

free(p)

编码思想

typedef struct Node
{
    dataType data;
    struct Node *next; // 用于指向下一个节点
}NODE,*LinkList;
// typedef struct Node NODE;
// typedef struct Node *LinkList; 

// 下面其实是一样的,不过看起来更优雅
NODE * 表示一个节点,一个指向一个节点的指针
LinkList 表示一个链表


// 一个模板
NODE * GetNode(LinkList L,int i)
{
	int j=1; // 从1开始 不是从0开始
	NODE *p=L->next;

	if (i==0) 
		return L;
	
	if (i<1)
		return NULL;
	
	while (p!=NULL && j<i)
	{
		p=p->next;
		j++;
	}
	return p;
}

例子 - 不带头结点

typedef struct LNode
{
    int data;
    struct LNode *next; // 用于指向下一个节点
}LNode,*LinkList; 
// typedef struct LNode NODE;
// typedef struct LNode *LinkList; 

// 下面其实是一样的,不过看起来更优雅
// LNODE * 表示一个节点,一个指向一个节点的指针
// LinkList 表示一个链表

bool InitList(LinkList &L) // 引用传递
{
    L=NULL; //struct LNode* ,这个必须是指针引用,否则,就不对
    return true;
}

bool Empty(LinkList L) // 此时因为不涉及修改,则可以不使用指针引用
{
    if (L==NULL) 
        return true;
    else 
        return false;
}

int main()
{

    LinkList L; // 相当于指针引用
    InitList(L);

    return 0;
}

例子 - 带头结点推荐使用带头结点的

typedef struct LNode
{
    int data;
    struct LNode *next; // 用于指向下一个节点
}LNode,*LinkList; 
// typedef struct LNode NODE;
// typedef struct LNode *LinkList ; 
 
// 下面其实是一样的,不过看起来更优雅
// LNODE * 表示一个节点,一个指向一个节点的指针
// LinkList 表示一个链表

bool InitList(LinkList &L) // 引用传递
{
    // 分配一个头节点
    L=(LNode *)malloc(sizeof(LNode));
    if (L==NULL)
        return false;
    
    L->next=NULL; // 头结点在初始化是,next指向null

    return true;
}

bool Empty(LinkList L) // 此时因为不涉及修改,则可以不使用指针引用
{
    if (L->next==NULL)  // 注意与不带头结点的区别
        return true;
    else 
        return false;
}

int main()
{
    LinkList L; // 相当于指针引用
    InitList(L);

    return 0;
}
插入删除
  • 带头结点

bool ListInsert(LinkList &L,int idx,int value); 注意j和越界插入

#include <iostream>
#include <cstdlib>

using namespace std;

typedef struct LNode
{
    int data;
    struct LNode *next;
}LNode,*LinkList;

bool InitList(LinkList &L)
{
    L=(LNode *)malloc(sizeof(LNode));

    if (L==NULL)
    {
        return false;
    }
    L->next=NULL;
    return true;
}

bool Empty(LinkList L)
{
    if (L->next==NULL)
    {
        return true;
    }
    else
    {
        return false;
    }
}


// 按位序插入节点
bool ListInsert(LinkList &L,int idx,int value)
{
    if (idx<1) // idx表示位序,从1开始
        return false;

    LNode *p; // 创建一个节点指针
    int j=0; // 当前p指向的是第j个节点
    p=L; // L是别名,p指向了L; 一开始L指向头节点,注意头节点是第0个节点

    // 遍历,找到第idx-1 也就是要插入的节点的前一个节点 idx是位序
    while (p!=NULL && j<idx-1)
    {
        p=p->next;
        j++;
    }

    /* version 1*/
    // if (p==NULL) // 如果找到最后一个节点
    // {
    //     return false;
    // }

    // // 分配空间
    // LNode *node=(LNode *)malloc(sizeof(LNode));

    // // 插入
    // node->data=value;
    // node->next=p->next;
    // p->next=node;

    // return true;

    /*version 2*/
    return InsertNextNode(p,value);

}

// 指定节点的插入 - 后插
bool InsertNextNode(LNode *pnode,int value)
{
    if (pnode==NULL)
    {
        return false;
    }
    
    LNode *node=(LNode *)malloc(sizeof(LNode));

    node->data=value;
    node->next=pnode->next;
    pnode->next=node;

    return true;

}


// 按位序删除节点
bool ListDelete(LinkList &L,int idx,int &value_return)
{
    if (idx<1)
    {
        return false;
    }

    LNode *pnode;
    int j=0;
    while (pnode!=NULL && j<idx-1)
    {
        pnode=pnode->next;
        j++;
    }

    if (pnode==NULL) // 如果找到最后一个节点
    {
        return false;
    }

    if (pnode->next==NULL) 
    {
        return false;
    }

    /*version 1*/
    // pnode->next=pnode->next->next;
    // value_return=pnode->next->data;
    // free(pnode->next);
    
    /*version 2*/
    LNode *pnext=pnode->next;
    value_return=pnext->data;
    pnode->next=pnext->next;
    free(pnext); // 注意,因为是malloc得来的要释放!!! 且free释放的是分配的内存

    return true;

}

// 删除指定节点
//采用后继赋值的操作(翻转覆盖) !!!
// 但是对于删除最后一个节点是存在问题的
bool DeleteNode(LNode *pnode)
{
    if (pnode==NULL)
    {
        return false;
    }

    LNode *pnext=pnode->next;
    pnode->data=pnode->next->data; // pnode->data=pnext->data
    pnode->next=pnext->next;
    free(pnext);
    return true;
}

int main()
{
    // struct LNode * L
    LinkList L;

    // struct LNode * &L=L; 形参L是实参L的别名
    InitList(L);

    ListInsert(L,1,1);

    return 0;
}
  • 不带头结点
#include <iostream>
#include <cstdlib>

using namespace std;

typedef struct LNode
{
    int data;
    struct LNode *next;
}LNode,*LinkList;

bool InitList(LinkList &L)
{
    L=NULL;
    return true;
}

bool Empty(LinkList L)
{
    if (L==NULL)
    {
        return true;
    }
    else
    {
        return false;
    }
}


bool ListInsert(LinkList &L,int idx,int value)
{
    if (idx<1) // idx表示位序,从1开始
        return false;

    // 初始节点
    if (idx==1)
    {
        LNode *firstNode=(LNode *)malloc(sizeof(LNode));
        firstNode->data=value;
        firstNode->next=L;
        L=firstNode;
        return true;
    }

    LNode *p; // 创建一个节点指针
    int j=1; // 当前p指向的是第j个节点
    p=L; // L是别名,p指向了L; 一开始L指向头节点,注意头节点是第0个节点

    // 遍历,找到第idx-1 也就是要插入的节点的前一个节点 idx是位序
    while (p!=NULL && j<idx-1)
    {
        p=p->next;
        j++;
    }

    if (p==NULL)
    {
        return false;
    }

    // 分配空间
    LNode *node=(LNode *)malloc(sizeof(LNode));

    // 插入
    node->data=value;
    node->next=p->next;
    p->next=node;

    return true;

}

int main()
{
    // struct LNode * L
    LinkList L;

    // struct LNode * &L=L; 形参L是实参L的别名
    InitList(L);

    ListInsert(L,1,1);

    return 0;
}
查找
  • 按位查找(带头结点)
LNode *GetItem(LinkList L,int idx)
{
    if (idx<0)
    {
        return NULL;
    }

    LNode *pnode;
    int j=0;
    pnode=L;
    
    while (pnode!=NULL && j<idx)
    {
        pnode=pnode->next;
        j++;
    }

    return pnode;
}
// 按位序插入节点
bool ListInsert(LinkList &L,int idx,int value)
{
    if (idx<1) // idx表示位序,从1开始
        return false;

	LNode *p=GetItem(L,idx-1);

    /* version 1*/
    // if (p==NULL) // 如果找到最后一个节点
    // {
    //     return false;
    // }

    // // 分配空间
    // LNode *node=(LNode *)malloc(sizeof(LNode));

    // // 插入
    // node->data=value;
    // node->next=p->next;
    // p->next=node;

    // return true;

    /*version 2*/
    return InsertNextNode(p,value);

}

// 指定节点的插入 - 后插
bool InsertNextNode(LNode *pnode,int value)
{
    if (pnode==NULL)
    {
        return false;
    }
    
    LNode *node=(LNode *)malloc(sizeof(LNode));

    node->data=value;
    node->next=pnode->next;
    pnode->next=node;

    return true;

}

LNode *GetItem(LinkList L,int idx)
{
    if (idx<0)
    {
        return NULL;
    }

    LNode *pnode;
    int j=0;
    pnode=L;
    
    while (pnode!=NULL && j<idx)
    {
        pnode=pnode->next;
        j++;
    }

    return pnode;
}
尾插法建立 – 很重要!!!
  • 普通方法

时间复杂度O(n)

#include <iostream>
using namespace std;

typedef struct LNode
{
    int data;
    struct LNode * next;
}LNode,*LinkList;

bool InitList(LinkList &L);
LNode * getNode(LinkList L,int idx);
bool ListInsert(LinkList &L,int idx,int value);
bool InsertNextNode(LNode *p,int value);

bool InitList(LinkList &L)
{
    L=(LNode *)malloc(sizeof(LNode));

    if (L==NULL)
    {
        return false;
    }

    L->next=NULL;
    return true;
}

bool ListInsert(LinkList &L,int idx,int value)
{
    if (L==NULL || idx<1)
    {
        return false;
    }

    // 按位查找找到前一个节点
    LNode *pre_node=getNode(L,idx-1);

    // 插入节点
    // if (!InsertNextNode(pre_node,value))
    // {
    //     return false;
    // }

    // return true;


    return InsertNextNode(pre_node,value);
}



LNode * getNode(LinkList L,int idx)
{
    if (idx<0)
    {
        return NULL;
    }

    LNode *p=L;
    int j=0;
    while (p!=NULL && j<idx)
    {
        p=p->next;
        j++;
    }

    return p;
}

bool InsertNextNode(LNode *p,int value)
{
    if (p==NULL)
    {
        return false;
    }

    // 分配一个新的节点
    LNode *new_node=(LNode *)malloc(sizeof(LNode));

    if (new_node==NULL)
    {
        return false;
    }

    new_node->data=value;
    if (p->next==NULL)
    {
        cout<<"NULL"<<endl;
    }
    else
    {
        cout<<"not NULL"<<endl;
    }
    
    new_node->next=p->next;
    p->next=new_node;

    return true;

}

int main()
{
    LinkList L;
    InitList(L); // 指针引用 ,头结点的值没有

    int insert_length=10;
    int j=0; // value
    int idx=1; // index
    while (j<insert_length)
    {
        ListInsert(L,idx,j);
        j++;
        idx++;
    }

    LNode *p=L->next; // 头结点的值没有
    while (p!=NULL)
    {
        cout<<p->data<<endl;
        p=p->next;
    }

    return 0;
}
  • 进阶方法
LinkList List_TailInsert(LinkList &L)
{
    int insert_length=10;
    int j=0; // value
    int idx=0; // index
    LNode *p=L;

    while (j<insert_length)
    {   
        LNode *new_node=(LNode *)malloc(sizeof(LNode));
        
        new_node->data=j;
        new_node->next=NULL;

        p->next=new_node; // 先对 L 添加一个节点
        p=new_node; // 再更新指针
        j++;
        idx++;
    }

    return L;
}
  • 进阶方法2
// 指定节点的插入 - 后插
bool InsertNextNode(LNode *pnode,int value)
{
    if (pnode==NULL)
    {
        return false;
    }
    
    LNode *node=(LNode *)malloc(sizeof(LNode));

    node->data=value;
    node->next=pnode->next;
    pnode->next=node;

    return true;

}

int main()
{
    // struct LNode * L
    LinkList L;

    // struct LNode * &L=L; 形参L是实参L的别名
    InitList(L);

    // ListInsert(L,1,1);
    
    /* == 插入 version 1 == */
    // int insert_length=10;
    // int j=0; // value
    // int idx=1; // index
    // while (j<insert_length)
    // {
    //     ListInsert(L,idx,j);
    //     j++;
    //     idx++;
    // }

    /* == 插入 version 2 == */
    // List_TailInsert(L); // 不返回也行

    /* == 插入 version 3 == */
    int insert_length=10;
    int value=0;
    int idx=1;
    LNode *p=L;
    while (idx<=insert_length)
    {
        if (InsertNextNode(p,value))
        {
            value++;
            idx++;
            p=p->next;
        }
        else
            break;
    }

    // LNode *p=L->next; // 头结点的值没有
    p=L->next; // 头结点的值没有
    while (p!=NULL)
    {
        cout<<p->data<<endl;
        p=p->next;
    }

    return 0;
}
头插法建立 – 很重要!!!

链表的逆序

双链表

模板

typedef struct DNode
{
    int data;
    struct DNode *prior; // 前驱结点
    struct DNode *next; // 后继节点
}DNode,*DLinkList;

带头结点

#include <iostream>
using namespace std;

typedef struct DNode
{
    int data;
    struct DNode *prior; // 前驱结点
    struct DNode *next; // 后继节点
}DNode,*DLinkList;

// 初始化
bool InitDLinkList(DLinkList &L)
{
    // 创建一个头结点
    L=(DNode*)malloc(sizeof(DNode));

    if (L==NULL)
    {
        return false;
    }

    L->prior=NULL;
    L->next=NULL;

    return true;
}


int main()
{
    DLinkList L;
    InitDLinkList(L);

    return 0;
}

遍历伪代码

    后序遍历
    DNode *p=L;
    while (p!=NULL)
    {
        cout<<p->data<<endl;
        p=p->next;
    }

    前向遍历 ??? 尾结点
    DNode *p=L;
    while (p->prior!=NULL) // 
    {
        cout<<p->data<<endl;
        p=p->prior;
    }
插入删除
#include <iostream>
using namespace std;

typedef struct DNode
{
    int data;
    struct DNode *prior; // 前驱结点
    struct DNode *next; // 后继节点
}DNode,*DLinkList;

bool InitDLinkList(DLinkList &L);
bool Empty(const DLinkList L);
bool DListInsert(DLinkList &L,int idx,int value);
bool InsertNextDNode_node(DNode *p,DNode *s);
bool InsertNextDNode(DNode *p,int value);
bool  DeleteNextDNode_node(DNode *p);
bool  DListDelete(DNode *p);

// 初始化
bool InitDLinkList(DLinkList &L)
{
    // 创建一个头结点
    L=(DNode*)malloc(sizeof(DNode));

    if (L==NULL)
    {
        return false;
    }

    L->prior=NULL;
    L->next=NULL;

    return true;
}

bool Empty(const DLinkList L)
{
    if (L->next==NULL)
    {
        return true;
    }
    else
    {
        return false;
    }
}

bool DListInsert(DLinkList &L,int idx,int value)
{
    if (idx<1)
    {
        return false;
    }

    DNode *p=L;
    int j=0;

    // 后序遍历
    while (p!=NULL && j<idx-1) // 找到前一个节点
    {
        p=p->next;
        j++;
    }
    
    if (p==NULL)
    {
        return false;
    }

    /* version 1*/
    // DNode *new_node=(DNode *)malloc(sizeof(DNode));
    // new_node->data=value;
    // new_node->next=p->next;
    // if (p->next != NULL)
    // {
    //     p->next->prior=new_node;
    // }

    // new_node->prior=p;
    // p->next=new_node;

    /* version 2 后序插入*/
    InsertNextDNode(p,value);

    return true;
}

// p节点之后插入s节点 -- 例子
bool InsertNextDNode_node(DNode *p,DNode *s)
{
    if (p==NULL || s==NULL) // 判断节点的合法性
    {
        return false;
    }
    // 断后
    s->next=p->next;
    if (p->next != NULL) // 判断p是否为最后一个节点,这个很重要
    {
        p->next->prior=s;
    }

    // 接前
    s->prior=p;
    p->next=s;
    
    return true;
}

bool InsertNextDNode(DNode *p,int value)
{
    if (p==NULL)
    {
        return false;
    }

    DNode *new_node=(DNode *)malloc(sizeof(DNode));
    new_node->data=value;
    new_node->next=p->next;
    if (p->next != NULL)
    {
        p->next->prior=new_node;
    }

    new_node->prior=p;
    p->next=new_node;

    return true;
}

// 删除p节点的后继节点
bool  DeleteNextDNode_node(DNode *p)
{
    if (p==NULL)
    {
        return false;
    }

    DNode *q=p->next;
    if (q==NULL) // 要么错误,要么p就是最后一个节点,没有后继节点
    {
        return false;
    }

    p->next=q->next;
    if (q->next!=NULL) // q是最后一个节点,没有后继节点
    {
        q->next->prior=p;
    }

    free(q); // 因为原始这个是通过malloc开辟的内存
    return true;
}

// bool  DListDelete(DLinkList &L,int idx,int &value_return)
// {
//     // 第一个节点和最后一个节点!!!
// }



int main()
{
    DLinkList L;
    InitDLinkList(L);

    /* == 插入 version 1 O(n^2) == */
    // int insert_length=11;
    // int value=0; // value
    // int idx=1; // index
    // while (idx<=insert_length)
    // {
    //     DListInsert(L,idx,value);
    //     value++;
    //     idx++;
    // }

    /* == 插入 version 3 O(n) == */
    int insert_length=11;
    int value=0; // value
    int idx=1; // index
    DNode *p=L;
    while (idx<=insert_length)
    {
        if (InsertNextDNode(p,value))
        {
            p=p->next;
            value++;
            idx++;
        }
        else
            break;
    }

    // DNode *p=L->next; // 插入 version 1
    p=L->next; // 插入 version 3
    while (p!=NULL)
    {
        cout<<p->data<<endl;
        p=p->next;
    }
    
    return 0;
}

循环链表

  • 循环单链表
  • 循环双链表
循环单链表

最后一个节点的next指向头结点

初始化时,头结点指向自己
链表为空:头结点是否指向自己

#include <iostream>
using namespace std;

typedef struct LNode
{
    int 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(const LinkList L)
{
    if (L->next==L) // 判断头结点的next是否指向自己
    {
        return true;
    }
    else
    {
        return false;
    }
    
}

// 判断节点p是否是循环单链表的表尾结点
// 某一结点的下一个节点是头结点
bool isTail(LinkList L,LNode *p)
{
    if (p->next==L)
    {
        return true;
    }
    else
    {
        return false;
    }
    
}


int main()
{
    return 0;
}

静态链表 – 没细看

模板

#define MAXSIZE 10

struct Node
{
    int data;
    int next; // 下一个元素的数组下表
};


int main()
{
    struct Node arr[MAXSIZE]; // 数组
    return 0;
}

编码思想

#define MAXSIZE 10

typedef struct
{
    int data;
    int next; // 下一个元素的数组下表
}SLinkList[MAXSIZE];


int main()
{
    // struct Node arr[MAXSIZE]; // 数组
    SLinkList arr;
    return 0;
}

模板

#define MaxSize 10
typedef struct stack
{
    int data[MaxSize]; // 静态分配
    int top; // 栈顶指针
}SqStack; // sq表示顺序

顺序栈

例子

静态存储

#include <iostream>
using namespace std;

#define MaxSize 10
typedef struct stack
{
    int data[MaxSize]; // 静态分配
    int top; // 栈顶指针
}SqStack; // sq表示顺序


void InitStack(SqStack &s)
{
    s.top=-1;
}

bool StackEmpty(const SqStack &s)
{
    if (s.top==-1)
    {
        return true;
    }
    else
    {
        return false;
    }
}

bool Push(SqStack &s,int val)
{
    if (s.top==MaxSize-1) // 栈满
    {
        return false;
    }

    s.top++; // 栈顶+1
    s.data[s.top]=val; // 赋值  s.datap[++s.top]=val;
    return true;

}

bool Pop(SqStack &s,int &return_val)
{
    if (s.top==-1)
    {
        return false;
    }

    return_val=s.data[s.top]; // s.data[s.top--]
    s.top--;
    return true;
}

bool getTop(const SqStack &s,int return_val)
{ 
    if (s.top==-1)
    {
        return false;
    }

    return_val=s.data[s.top];
    return true;
}

int main()
{

    SqStack s;
    InitStack(s); // 初始化 

    // 赋值
    for (int i=0;i<MaxSize;i++)
    {
        Push(s,i);
    }

    int val=0;
    for (int i=0;i<MaxSize;i++)
    {
        if (Pop(s,val))
        {
            cout<<val<<endl;
        }
    }

    return 0;
}


链式栈

#include <iostream>
using namespace std;

#define MaxSize 10

typedef struct LinkStackNode
{
    int data;
    struct LinkStackNode *next;
} LSNode, *LinkStack;

bool initStack(LinkStack &LS)
{
    LS = (LSNode *)malloc(sizeof(LSNode));

    if (LS == NULL)
    {
        return false;
    }

    LS->next = NULL;
    return true;
}

bool StackEmpty(const LinkStack LS)
{
    if (LS->next == NULL)
    {
        return true;
    }
    else
    {
        return false;
    }
}

bool Push(LinkStack &LS, int val)
{
    if (LS == NULL)
    {
        return false;
    }

    LSNode *lsNode = (LSNode *)malloc(sizeof(LSNode));

    if (lsNode == NULL)
    {
        return false;
    }

    // 利用头插法
    LSNode *head = LS;
    lsNode->data = val;
    lsNode->next = head->next;
    head->next = lsNode;
    
    return true;
}

bool Pop(LinkStack &LS, int &return_val)
{
    if (LS == NULL || StackEmpty(LS))
    {
        return false;
    }

    LSNode *head = LS;
    
    /* verison1 */
    // return_val=head->next->data;
    
    // if (head->next->next == NULL)
    // {
    //     head->next = NULL;
    // }
    // else
    // {
    //     head->next=head->next->next;
    // }

    /* version2 */ // -- 推荐这种写法
    LSNode *pnode=head->next;
    return_val=pnode->data;
    head->next=pnode->next;
    free(pnode);

    return true;
}

bool getTop(const LinkStack LS,int return_val)
{
    if (LS == NULL || StackEmpty(LS))
    {
        return false;
    }

    LSNode *head = LS;
    return_val=head->next->data;
    return true;
}


int main()
{

    LinkStack LS;
    initStack(LS);

    // 赋值
    for (int i=0;i<MaxSize;i++)
    {
        Push(LS,i);
    }

    int val=0;
    for (int i=0;i<MaxSize;i++)
    {
        if (Pop(LS,val))
        {
            cout<<val<<endl;
        }
    }

    return 0;
}

队列

顺序循环队列

利用数组实现

第一种实现方法

在某些情况下会浪费一个存储空间
在这里插入图片描述

#include <iostream>
using namespace std;

#define MaxSize 10
typedef struct queue
{
    int data[MaxSize];
    int front; // 队头,指向队头元素; 注意:出队后,队头指针向后移动
    int rear;  // 队尾,指向队尾元素的后一个元素(下一个待插入的元素)
} SqQueue;

void InitQueue(SqQueue &q)
{
    q.front = 0;
    q.rear = 0; // 队尾指向0
}

bool QueueEmpty(const SqQueue &q) // const SqQueue q 没有意义,因为本来就是深拷贝
{
    if (q.front == q.rear)
    {
        return true;
    }
    else
    {
        return false;
    }
}

bool EnQueue(SqQueue &q, int val)
{
    if ((q.rear + 1) % MaxSize == q.front) // 这句很重要!!!队列满的条件:队尾指针的再下一个位置是队头
    {
        return false;
    }
    q.data[q.rear] = val;
    q.rear = (q.rear + 1) % MaxSize; // 这句很重要!!!画图思考
    return true;
}

bool DeQueue(SqQueue &q, int &return_val)
{
    if (q.rear == q.front) // 判断是否为空
    {
        return false;
    }

    return_val = q.data[q.front];
    q.front = (q.front + 1) % MaxSize;

    return true;
}

bool getHead(const SqQueue &q, int &return_val)
{
    if (q.rear == q.front)
    {
        return false;
    }
    return_val = q.data[q.front];
    return true;
}

size_t getLength(const SqQueue &q)
{
    return (q.rear + MaxSize - q.front) % MaxSize; // 记住!!!
}

int main()
{
    SqQueue q;
    InitQueue(q);

    for (int i=0;i<MaxSize;i++)
    {
        EnQueue(q,i);
    }

    int val=0;
    for (int i=0;i<MaxSize;i++)
    {
        if (DeQueue(q,val))
        {
            cout<<val<<endl;
        }
    }

    return 0;
}

第二种实现方法

链表队列

利用链表实现

例子1

#include <iostream>
using namespace std;

#define MaxSize 10

// 定义节点
typedef struct linkQueueNode
{
    int data;
    struct linkQueueNode* next;
}LQNode;

// 队头、队尾指针
typedef struct 
{
    LQNode *front; // 头节点 不是实际上的第一个元素
    LQNode *rear; // 尾节点
}LinkQueue;


void InitQueue(LinkQueue &q)
{
    // 头尾指向相同 
    q.rear=(LQNode *)malloc(sizeof(LQNode));
    q.front=q.rear;

    q.front->next=NULL;
}

bool IsEmpty(const LinkQueue q)
{
    /* version1 */
    if (q.front==q.rear)
    {
        return true;
    }
    else
    {
        return false; 
    }

    /* version2 */
    // if (q.front->next==NULL)
    // {
    //     return true;
    // }
    // else
    // {
    //     return false;
    // }
}

void EnQueue(LinkQueue &q,int val)
{
    LQNode *node=(LQNode *)malloc(sizeof(LQNode));

    node->data=val;
    node->next=NULL;

    q.rear->next=node; // 入队
    q.rear=node; // 修改尾指针
    
}


bool DeQueue(LinkQueue &q,int &return_val)
{
    if (IsEmpty(q))
    {
        return false;
    }

    /* version1 */
    // return_val=q.front->data; 
    // q.front->next=q.front->next->next; // 最好不要使用next->next 会出现内存内存泄漏!!!

    /* version2 */ // -- 推荐写法
    LQNode *pnode=q.front->next;
    return_val=pnode->data;
    q.front->next=pnode->next; // 出队

    // 特殊处理
    if (q.rear==pnode) // 如说是最后一个节点,画图理解很重要!!!
    {
        q.rear=q.front;
    }
     
    free(pnode); // 这种方法好,最好不要使用next->next 会出现内存内存泄漏!!!

    return true;
}

int main()
{
    LinkQueue q;
    InitQueue(q);

    for (int i=0;i<MaxSize;i++)
    {
        EnQueue(q,i);
    }

    int val=0;
    for (int i=0;i<MaxSize;i++)
    {
        if (DeQueue(q,val))
        {
            cout<<val<<endl;
        }
    }

    return 0;
}

例子2 !!! 反复思考

#include <iostream>
using namespace std;

#define MaxSize 10

// 定义节点
typedef struct linkQueueNode
{
    int data;
    struct linkQueueNode* next;
}LQNode;

// 队头、队尾指针
typedef struct LQ
{
    LQNode *front; // 头节点 不是实际上的第一个元素
    LQNode *rear; // 尾节点
}LQ,* LinkQueue;


void InitQueue(LinkQueue &q)
{
    // 头尾指向相同 
    // q=(LQ *)malloc(sizeof(LQ)); // q=(LinkQueue)malloc(sizeof(LinkQueue)); // !!!
    
    q->rear=(LQNode *)malloc(sizeof(LQNode));
    q->front=q->rear;

    q->front->next=NULL;
}

bool IsEmpty(const LinkQueue q)
{
    /* version1 */
    if (q->front==q->rear)
    {
        return true;
    }
    else
    {
        return false; 
    }

    /* version2 */
    // if (q->front->next==NULL)
    // {
    //     return true;
    // }
    // else
    // {
    //     return false;
    // }
}

void EnQueue(LinkQueue &q,int val)
{
    LQNode *node=(LQNode *)malloc(sizeof(LQNode));

    node->data=val;
    node->next=NULL;

    q->rear->next=node; // 入队
    q->rear=node; // 修改尾指针
    
}


bool DeQueue(LinkQueue &q,int &return_val)
{
    if (q==NULL|| IsEmpty(q))
    {
        return false;
    }

    /* version1 */
    // return_val=q->front->data; 
    // q->front->next=q->front->next->next; // 最好不要使用next->next 会出现内存内存泄漏!!!

    /* version2 */ // -- 推荐写法
    LQNode *pnode=q->front->next;
    return_val=pnode->data;
    q->front->next=pnode->next; // 出队

    // 特殊处理
    if (q->rear==pnode) // 如说是最后一个节点,画图理解很重要!!!
    {
        q->rear=q->front;
    }
     
    free(pnode); // 这种方法好,最好不要使用next->next 会出现内存内存泄漏!!!

    return true;
}

int main()
{
    // LinkQueue q=NULL;
    LinkQueue q;//=NULL;
    InitQueue(q);

    for (int i=0;i<MaxSize;i++)
    {
        EnQueue(q,i);
    }

    int val=0;
    for (int i=0;i<MaxSize;i++)
    {
        if (DeQueue(q,val))
        {
            cout<<val<<endl;
        }
    }

    return 0;
}

2. 递归

例子 斐波那契数列

#include <iostream>
using namespace std;

int Fib(int n)
{
    if (n==0)
    {
        return 0;
    }
    else if (n==1)
    {
        return 1;
    }
    else 
    {
        return Fib(n-1)+Fib(n-2);
    }
}

int main()
{
    int x=Fib(4);
    cout<<x<<endl;

    return 0;
}

在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值