数据结构应用-栈/队列/链表 (+map)

1 C++标准库STL常用介绍

1.1 map

map可以将任何基本类型 (键key) 映射到任何基本类型 (值value)

1.1.1 准备工作

#include< map> ; using namespace std;

1.1.2 定义

map< string,int > mp; 字符串(键) 到 整型(值) 的映射,键是唯一的。

1.1.3 使用

(1) 基本访问
#include<stdio.h>
#include<map>
using namespace std;
int main(){
	map<char,int> mp;
	mp['c']=20;
	mp['c']=30;//20被覆盖
	printf("%d\n",mp['c']);//输出30
	return 0;
}
(2) 迭代器访问
#include<stdio.h>
#include<map>
using namespace std;
int main(){
	map<char,int> mp;
	mp['m']=20;
	mp['r']=30;
	mp['a']=40;
	for(map<char,int>::iterator it = map.begin(); it !=mp.end(); it++){
		printf("%c %d\n",it -> first,it -> second);
	}	
	return 0;
}

输出结果:(map会自动按照键的大小排序)
a 40
m 20
r 30

(3) find() /erase()

mp.find(key) 返回键为key的映射迭代器。
mp.erase(key) 删除键为key的映射,
mp.erase(first,last) 删除first-last区间内的映射。

#include<stdio.h>
#include<map>
using namespace std;
int main(){
	map<char,int> mp;
	mp['a']=1;
	mp['b']=2;
	mp['c']=3;
	map<char,int>::iterator it = map.find('b');
	//mp.erase(it);//删除it映射,即b 2
	//mp.erase(it,mp.end());//删除it 之后的所有映射
	printf("%c %d\n",it -> first,it -> second);
	
	return 0;
}

输出结果:
b 2

1.2 queue() 队列 先进先出

从队尾加入,队头移除。
简单图示:
在这里插入图片描述

1.2.1 准备工作

#include< queue> ; using namespace std;

1.2.2 定义

queue< int > vi;

1.2.3 直接使用

(1) 入队 push(x)
vi.push(x) 将x放入队列,先放为队首,后放为队尾

(2) 出队 pop()
vi.pop() 将元素出队,从队首开始出。

(3) 访问队首、队尾 front()、back()
vi.front():访问队首元素;
vi.back():访问队尾元素。

(4) 获取队列大小 size()
vi.size() 返回队列内元素个数。

(5) 判空 empty()
vi.empty() 返回bool类型值。

1.2.4 应用-非标准库

下面用数组q[ ]实现队列,int变量front存放队首元素的前一个元素的下标,rear存放队尾元素的下标,数组下标从0开始。

(1) 入队 push(x)
元素入队时,从队尾入队,需要先把rear+1,然后再把元素存放到rear指向的位置 (即+1后得新rear位置)

void push(int x){
	q[++rear] = x;
}

(2) 出队 pop()
从队首开始出。可以直接把队首指针+1实现出队。

void pop(){
	front++;
}

(3) 取队首元素(get_front)
front指向队首的前一个元素,所以,front+1指向队首。

int get_front(){
	return q[front+1];
}

(4) 取队尾元素(get_rear)
rear指向队尾元素,所以,直接访问rear即可。

int get_rear(){
	return q[rear];
}

(5) 清空 clear()
使用数组来实现队列时,初始状态为front=-1,rear=-1,用此状态表示空队列。

void clear(){
	front=rear=-1;
}
注意:真正的清空,是需要pop实现的,具体代码如下:
while(!q.empty()){
	q.pop();
}

(6) 获取队列大小 size()
rear-front为队列的元素个数。

int size(){
	return rear-front;
}

(7)判空 empty()
front==rear则为空,返回true;否则返回false。

bool empty(){
	if(front==rear) return true;
	else return false;
}

1.3 stack() 栈 后进先出

从栈顶加入,栈顶移除。
简单图示:
在这里插入图片描述

1.3.1 准备工作

#include< stack > ; using namespace std;

1.3.2 定义

stack< int > st;

1.3.3 直接使用

(1)进栈 push(x)
st.push(x) 将x压入栈,先放为栈底,后放为栈顶

(2)出栈 pop()
st.pop() 弹出栈顶元素。

(3)取栈顶元素 top()
st.top() 访问栈顶元素,不弹出。

(5)判空 empty()
st.empty();

(6)获取栈的大小 size()
st.size(); 返回值为int。

1.3.4 应用-非标准库

(1)进栈 push(x)
vi.push(x) 将x压入栈,先放为栈底,后放为栈顶

(2)出栈 pop()
vi.pop() 弹出栈顶元素

(3)取栈顶元素 top()
vi.top() 访问栈顶元素,不弹出

(5)判空 empty()
vi.empty(); bool类型的返回值,仅当TOP=-1时返回true,否则返回false。

(6)获取栈的大小 size()
栈内元素个数为TOP+1。
vi.size(); 返回值为int。
(4)清空 clear()
vi.clear() 栈的清空,实际是将栈顶指针置为-1,表示栈中没有元素。

TOP=-1;
注意:真正的清空,是需要pop实现的,具体代码如下:
while(!st.empty()){
	st.pop();
}

1.4 链表处理

概念梳理:
在这里插入图片描述

链表和数组存储结构示意图:
在这里插入图片描述

1.4.1 为链表结点分配临时空间的两种方法

(1)C语言-malloc函数
头文件:#include<stdlib.h>
返回:申请的同变量类型的指针
用法

//typename* p = (typename*)malloc(sizeof(typename));
int* p = (int*)malloc(sizeof(int));
node* p = (node*)malloc(sizeof(node));

(2)C++ new运算符
返回:申请的同变量类型的指针
用法:

//typename* p = new typename;
int* p = new int;
node* p = new node;

(3) 空间开辟后的释放-防止内存泄漏

① free函数-对应malloc函数
头文件:#include<stdlib.h>
用法:

free(p);//p为需要释放的内存空间的指针变量

实现效果:释放P指向的内存空间;将P指向空地址NULL。

② delete运算符-对应new运算符
用法:

delete(p);

1.4.2 链表的基本操作

map< string,int > mp; 字符串(键) 到 整型(值) 的映射,键是唯一的。

(1) 基本操作

创建链表: malloc或new创建结点后,只要把零散的结点连起来就形成链表了。方法是把每个结点的next指针指向下一个结点的地址即可。

在这里插入图片描述

建立链表代码:

#include<iostream>
#include <stdlib.h> 
using namespace std;

//链表结点
struct node
{
	int data;
	node* next;
};
//创建链表
node* create(int Array[]) {
	node *p, *pre, *head;//pre保存当前结点的前驱结点,head为头结点
	head = new node;//创建头节点
	head->next = NULL;//头节点不需要数据域,指针域为null
	pre = head;//记录pre为head
	for (int i = 0; i < 10; i++)//新建10个结点
	{
		p = new node;//新建节点
		//将Array[i]赋值给新建的结点作为数据域,也可以cin输入
		p->data = Array[i];
		p->next = NULL;//新结点的指针域为NULL

		pre->next = p;//前驱节点的指针域为当前新建节点的地址
		pre = p;//把pre设为p,作为下个节点的前驱结点
	}
	return head;//返回头结点指针
}


int main()
{

	int Array[10] = { 9,8,7,5,6,4,2,10,60,21 };
	node* L = create(Array);//新建链表,返回头指针head赋值给L
	L = L->next;//从第一个结点开始有数据域
	while (L!=NULL)
	{
		cout << L->data << endl;
		L = L->next;
	}
	
	system("pause");
	return 0;
}

运行结果:
在这里插入图片描述
查询元素:

查询某个给定元素x,需要从第一个结点开始,不断地判断当前结点地数值域是否=x,若等于,给计数器count+1。这样到达结尾时,count=链表中元素x的个数。

查询代码:

//在以head为头结点的链表上计数x元素的个数
int search(node* head,int x){
	int count = 0;
	node* p=head->next;//从第一个节点开始
	while(p!=NULL){//未到链表结尾
		if(p->data == x) count++;
		p=p->next;
	}
	return count;
}

插入元素:
在给定位置增加节点。
在这里插入图片描述
插入代码:

//将x插入以head为头结点的链表上的第pos位置
void insert(node* head,int pos,int x){
	node* p=head;
	for(int i=0;i<pos-1;i++){
		p=p->next;//pos-1是为了到插入位置的前一个结点
	}
	node* q=new node;//新建结点
	q->data=x;//新结点数据域x
	q->next=p->next;//新结点的下一个结点指向原先位置的结点
	p->next=q;//前一个位置的结点指向新结点
}

删除元素:

删除代码:

//市删除以head为头结点的链表上的所有以x为数据域的结点
void delete(node* head,int x){
	node* p=head->next;//从第一个结点开始枚举
	node* pre =head;//pre保存p的前驱结点的指针
	while(p!=NULL){//未到链表结尾
		if(p->data == x) {//需要删除的结点
			pre->next=p->next;
			delete(p);
			p=pre->next;
		}else{//不是要删除的结点,则把pre和p都后移一位
		pre=p;
		p->p->next;
		}
		
	}
	
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值