目录
一.栈
1.顺序栈操作:
① 顺序栈的创建(初始化):
②判断栈是否满了/空:
③顺序栈入栈:
④得到栈顶元素(不弹出,仅获得):
⑤弹出栈顶元素:
顺序栈 示例:
2.链栈
①链栈创建(初始化):
②判断栈是否为空:
③入栈:
④得到栈顶元素(不弹出) :
⑤弹出栈顶元素:
链栈示例:
二.队列
1.顺序队列操作:
①创建顺序队列
②得到队列长度
③判断队空/队满
④推入元素(队尾
⑤弹出队首元素
示例:
2.链队列
①链队列创建
②链队列判空
③链队列推入元素
④得到队首元素(不弹出)
⑤得到队列长度(遍历)
⑥链队列弹出队首元素
示例:
注:
1.顺序栈的栈顶top始终为最后一给入栈元素的后一位置
2.所以当top==base时栈空
3.同类型连续地址可以直接相减,结果自动转换为元素个数,所以可知一个栈的大小为top-base
4.该栈相关:
struct ele {
int data;
};
struct Sqstack {
ele* base = 0;
ele* top = 0;
int maxsize = MAX;
int nowsize = top - base;
};
Sqstack& sqstack_creat() {//返回一个顺序栈结构体
Sqstack s;
s.base = new ele [MAX];//new返回首地址
s.top = s.base;
return s;
}
满:
bool sqstack_f(Sqstack& s) {//判断栈是否满了
if (s.top - s.base == s.maxsize) return 1;
return 0;
}
空:
bool sqstack_emp(Sqstack& s) {//判断栈是否满了
if (s.top - s.base == 0) return 1;
return 0;
}
bool sqstack_push(Sqstack& s,ele e) {//向s顺序栈推入e元素
//因为top指向尾元素的下一位置,所以这里先给top位置赋值,在自加
if (s.top - s.base == s.maxsize) return 0;//栈满返回0
*s.top = e;
s.top++;
return 1;//添加成功返回1
}
ele sqstack_get(Sqstack s) {//得到栈顶元素(不弹出)
if (s.top - s.base != 0)
return *(s.top - 1);
}
ele sqstack_pop(Sqstack& s) {//弹出栈顶元素(显示并删除)
if (s.top - s.base != 0)
return *(--s.top);
}
int main()
{
int n;
Sqstack s = sqstack_creat();//创建顺序栈
ele e;
cin >> n;
e.data = n;
cout << "此时判断栈空的返回值为" << " " << sqstack_emp(s) << endl;
sqstack_push(s, e);//推入e元素
cout << "推入元素 e.data = " << n<
注:
1.链栈即为用链表表示的栈,此时定义头节点为栈顶(元素的地址)——即最后入栈的元素
2.因为头节点为栈顶,所以空栈时头节点为空指针,创建的时候初始化即可
3.头节点(栈顶)为空的时候空栈
***4.一个重要的操作:接下来的函数内部可能需要独立改变头节点(栈顶的地址),但是如果只用传进的参数来修改无法真正的对地址进行修改。所以采用引用地址的操作。
例把在函数里使head地址变为为head->next:
void test(Linkstack*& head) {//对地址head引用
head = head->next;
}
该栈相关:
struct ele {
int num;
};
struct Linkstack {
ele data ;
Linkstack* next=0 ;
};
Linkstack* linkstack_creat() {//创建一个空栈,返回头节点(栈顶)
Linkstack* q = 0;
return q;
}
bool linkstack_emp(Linkstack* head) {
if (head == 0)
return 1;
return 0;
}
Linkstack* linkstack_push(Linkstack*& head, ele e) {//推入e元素(注意引用
Linkstack* temp = new Linkstack;
temp->data = e;
temp->next = head;
head = temp;//****注意引用,不然操作无效
return head;
}
ele linkstack_get(Linkstack* head) {//获得栈顶元素(不弹出)
if(head!=0)
return head->data;
}
ele linkstack_pop(Linkstack*& head) {
Linkstack* temp1 = head;//保留原地址,操作完释放
ele temp2 = head->data;
head = head->next;
delete temp1;
return temp2;
}
#include
using namespace std;
struct ele {
int num;
};
struct Linkstack {
ele data ;
Linkstack* next=0 ;
};
Linkstack* linkstack_creat() {//创建一个空栈,返回头节点(栈顶)
Linkstack* q = 0;
return q;
}
bool linkstack_emp(Linkstack* head) {
if (head == 0)
return 1;
return 0;
}
Linkstack* linkstack_push(Linkstack*& head, ele e) {//推入e元素(注意引用
Linkstack* temp = new Linkstack;
temp->data = e;
temp->next = head;
head = temp;//****注意引用,不然操作无效
return head;
}
ele linkstack_get(Linkstack* head) {//获得栈顶元素(不弹出)
if(head!=0)
return head->data;
}
ele linkstack_pop(Linkstack*& head) {
Linkstack* temp1 = head;
ele temp2 = head->data;
head = head->next;
delete temp1;
return temp2;
}
int main()
{
int n;
Linkstack* s = linkstack_creat();//创栈
ele e;
cin >> n;
e.num = n;
cout << "此时判断栈空的返回值为" << " " << linkstack_emp(s) << endl;
linkstack_push(s, e);//推入e元素
cout << "推入元素 e,e.num = " << n<
注:
1.顺序表的一个很大的缺点就是空间是固定的,如果数据过大,则会非常麻烦。对此
我们可以稍微优化一下, 采用循环顺序队列。也就是尾指针到队尾后返回队首继续使用
之前剩下的空间,循环用取模%来实现。示意图:
2.所以队空时:rear==front
队满时:(rear+1)%max==front;
3.队列的长度为
(q.rear - q.front + maxsize) % maxsize
顺序队列相关:
struct ele {
int data;
};
struct sqQueue {
ele* base;//存储数据
int front = 0;
int rear = 0;
};
sqQueue& initqueue() {//返回一个结构体,表示顺序队列
sqQueue q;
q.base = new ele[maxsize];
q.front = q.rear = 0;
return q;
}
int sqQueue_len(sqQueue q) {
int len = (q.rear - q.front + maxsize) % maxsize;
return len;
}
队空:
bool sqQueue_emp(sqQueue q) {
if (q.front == q.rear)
return 1;
return 0;
}
队满:
bool sqQueue_f(sqQueue q) {//舍弃一个元素位置,以至于判断队满队空
if ((q.rear + 1) % maxsize == q.front)//真溢出
return 1;
return 0;
}
bool sqQueue_push(sqQueue& q, ele e) {//向q队列中推入e元素
if (!sqQueue_f(q)) {
q.base[q.rear] = e;
q.rear = (q.rear + 1) % maxsize;
return 1;
}
return 0;
}
ele sqQueue_pop(sqQueue& q) {//弹出队首元素
if (!sqQueue_emp(q)) {//非空
ele temp = q.base[q.front];
q.front = (q.front + 1) % maxsize;//循环队列
return temp;
}
}
int main()
{
sqQueue q;
q = initqueue();
ele e;
int n;
cin >> n;
e.data = n;
cout << "是否队空 " << sqQueue_emp(q) << endl;
cout << "向队列 q 推入e,e的data为"<
注:
1.像单链表以表头指针head表示这个链表,此处以包含队列的头尾指针的结构体linkqueue来表示队列。
2.队首指针的front的下一节点front->next表示队首
3.由于2,所以当队首指针等于队尾指针即front==rear时队列为空
队列相关
struct ele {
int data;
};
struct linkQnode {//链队的节点
ele num;//队列的内容
linkQnode* next = 0;
};
struct linkqueue {//存放队首指针和队尾指针,代表一个队列
linkQnode* front = 0;//队列的内容,注此处front->next才表示队首元素
linkQnode* rear = 0;
};
linkqueue linkqueue_creat() {//返回一个含头尾指针的结构体表示队列
linkqueue q;
q.front = new linkQnode;//队首开辟一个空间
q.rear = q.front;
return q;
}
bool linkqueue_emp(linkqueue q) {
if (q.front == q.rear)//头尾相同,队空
return 1;
return 0;
}
int linkqueue_push(linkqueue& q,ele e) {
linkQnode* temp = new linkQnode;//创建一个临时结构体,存放数据
temp->num = e;
q.rear->next = temp;//队尾的下一个元素指向它
q.rear = q.rear->next;//队尾成为这个新元素
return 1;
}
ele linkqueue_get(linkqueue q) {//得到队首元素不弹出
//队首元素为front->next;
return q.front->next->num;
}
//注意边界问题和指针初始化问题
int linkqueue_len(linkqueue q) {//得到队列当前长度
linkQnode* temp = q.front->next;//得到队首
int len = 0;
while (temp) {
len++;
temp = temp->next;
}
return len;
}
/*注意操作逻辑*/
ele linkqueue_pop(linkqueue& q) {//弹出队首元素
if (!linkqueue_emp(q)) {
linkQnode* temp1 = q.front->next;
ele temp2 = temp1->num;
q.front->next =temp1->next;//跳过队首节点
if (temp1 == q.rear) q.rear = q.front;//特判
delete temp1;
return temp2;
}
}
int main()
{
linkqueue q;
q = linkqueue_creat();
ele e[100];
int n;
cin >> n;
for (int j = 0; j < n; j++) {
e[j].data = j+1;
}
cout << "是否队空 " << linkqueue_emp(q) << endl;
for (int j = 0; j < n; j++) {
linkqueue_push(q, e[j]);
}
cout << "推入1-" << n << "的元素后";
cout << "是否队空 " << linkqueue_emp(q)<