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;
}