栈与队列基本操作

目录

一.栈

1.顺序栈操作:

① 顺序栈的创建(初始化):

②判断栈是否满了/空:

③顺序栈入栈:

④得到栈顶元素(不弹出,仅获得):

⑤弹出栈顶元素: 

顺序栈 示例:

2.链栈

①链栈创建(初始化):

②判断栈是否为空:

 ③入栈:

④得到栈顶元素(不弹出) :

⑤弹出栈顶元素:

链栈示例:

二.队列

1.顺序队列操作:

①创建顺序队列

②得到队列长度

③判断队空/队满

④推入元素(队尾

⑤弹出队首元素

示例:

 2.链队列

①链队列创建

 ②链队列判空

③链队列推入元素

④得到队首元素(不弹出)

⑤得到队列长度(遍历)

⑥链队列弹出队首元素

示例:


一.栈

1.顺序栈操作:

注:

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.链栈

注:

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<

 栈与队列基本操作_第2张图片

二.队列

1.顺序队列操作:

注:

1.顺序表的一个很大的缺点就是空间是固定的,如果数据过大,则会非常麻烦。对此

我们可以稍微优化一下, 采用循环顺序队列。也就是尾指针到队尾后返回队首继续使用

之前剩下的空间,循环用取模%来实现。示意图:

栈与队列基本操作_第3张图片

 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为"<

栈与队列基本操作_第4张图片

 2.链队列

注:

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)<

栈与队列基本操作_第5张图片

 

你可能感兴趣的:(栈与队列,数据结构,链表,数据结构)