C++基础——10-指针

指针

1 指针的基本概念

作用:可以通过指针间接访问内存

  1. 内存编号是从0开始记录的,一般用用16进制数字表示
  2. 可以利用指针变量保存地址
    在这里插入图片描述

2 指针的变量定义和使用

指针变量定义语法:数据类型 *变量名;
代码示例:
1、指针就是地址;
2、指针可以访问内存地址所对应的值,也可以修改该值

int main()
{
	//1、如何定义指针
	
	int a = 10;
	//指针定义的语法:数据类型 *指针变量名;
	int* p;
	//让指针记录变量a的地址
	p = &a;//取a的地址,指针p记录这个地址
	cout << "a的地址是:" << &a<<endl;
	cout << "指针p=" << p << endl;
	//2、使用指针
	//可以通过解引用的方式来找到指针指向的内存
	//指针前加"*"代表解引用,找到指针指向的内存中的数据
	cout<<"=======================" << endl;
	*p = 1000;//可以修改内存指向的值
	cout << "a=" << a << endl;
	cout << "*p=" << *p << endl;



	return 0;

}

结果:
在这里插入图片描述

3 指针所占内存空间

提问:指针也是一种数据类型,那么,它占了多少内存空间?

int main()
{
	//指针所占空间
	int a = 10;
	int* p = &a;
	//在32为操作系统下,指针都是占4个字节大小,不管是什么数据类型。在64位操作系统下,指针都是占8个字节大小,不管是什么数据类型。
	cout << "sizeof int * =" <<sizeof(p) <<endl;
	cout << "sizeof float * =" << sizeof(float*) << endl;
	cout << "sizeof double * =" << sizeof(double*) << endl;
	cout << "sizeof char * =" << sizeof(char*) << endl;


	return 0;

}

结果:
64为操作系统:
在这里插入图片描述
32位操作系统:
在这里插入图片描述
结论:不管是什么数据类型,在32为操作系统下,指针都是占4个字节大小,在64位操作系统下,指针都是占8个字节大小。

4 空指针和野指针

空指针:指针变量指向内存中编号为0的空间
用途:初始化指针变量
注意:空指针指向的内存是不可以访问的

代码示例:
空指针是不可以进行访问的

	//1、初始化指针变量
	 int* p = NULL;
	//2、空指针是不可以进行访问的
	 *p = 100;

假设定义了一个空指针,然后解引用,将空指针所在地址的值变成100,则会报警告:
在这里插入图片描述
运行时则会报错:
在这里插入图片描述

野指针:指针变量指向非法的内存空间
代码示例:

	//指针变量p指向内存地址编号为0x1100的地址
	//在程序中,尽量避免出现野指针
	int* p = (int *)0x1100;
	cout << *p << endl;

结果:
在这里插入图片描述
总结:空指针和野指针都不是我们申请的空间,因此不要访问

5 const修饰指针

const修饰有3种情况:

  1. const修饰指针 —常量指针
  2. const修饰常量 —指针常量
  3. const既修饰指针,又修饰常量

1、常量指针
常量指针的指向可以改,但指针指向的值不可以改。
在这里插入图片描述

代码示例:

	//1 、const修饰指针 常量指针
	int a = 10;
	int b = 10;
	//指针指向的值不可以改变,但指向可以改变
	const int* p = &a;
	//*p=20; //错误
	p = &b;

	//2、const修饰常量 指针常量
	//指针的指向不可以改,指针指向的值可以改
	int* const p2 = &a;
	*p2 = 100; //正确
	//p2 = &b;//错误,指针指向不可以改

	//3、const修饰指针和常量
	const int* const p3 = &a;
	//指针指向和常量都不可以改
	//*p3 = 100;//错误
	//p3 = &b;//错误

6 指针和数组

作用:利用指针访问数字中的元素
代码示例:

	//利用指针访问数组中的元素
	int arr[] = {1,2,3,4,5,6,7,8,9,10};
	cout << "第一个元素为:"<<arr[0] << endl;
	int* p = arr;//利用指针指向数组名,arr就是数组首地址
	//利用指针来访问数组第一个元素
	cout << "指针访问的第一个元素为:" << *p << endl;
	p++;//指针会往后+4个字节,就会到第二个元素
	cout << "指针访问的第二个元素为:" << *p << endl;
	cout << "for循环指针遍历数组:" << endl;
	int* p2 = arr;
	for (int i = 0; i < 10; i++)
	{
		cout << *p2 << " ";
		p2++;
	}
	cout << endl;

结果:
在这里插入图片描述

7 指针和函数

作用:利用指针作函数参数,可以修改实参的值
        之前有一节我们说过,形参不会改变实参的值,但是,在指针中,形参可以改变实参的值。
代码示例:

//指针和函数
void swap001(int a,int b) //2个数字交换,值传递
{
	int temp = a;
	a = b;
	b = temp;
}
void swap002(int *p1, int *p2) //2个数字交换,地址传递
{
	int temp = *p1;
	*p1 = *p2;
	*p2 = temp;
}
void value_swap()
{
	//1、值传递
	int a = 10;
	int b = 20;
	swap001(a, b);
	cout << "a= " << a << endl;
	cout << "b= " << b << endl;//实参不会发生改变
	cout << "============="<<endl;
	//2、地址传递
	swap002(&a, &b);
	cout << "a= " << a << endl;
	cout << "b= " << b << endl;//实参a和b发生了改变

}

结果:
在这里插入图片描述

8 指针、数组和函数的小案例

描述:封装一个函数,利用冒泡排序,实现对整型数组的升序排序
例如数组 int arr[10]={4,3,6,9,1,2,10,8,7,5};
代码示例:

//指针、数组和函数的小案例
	//步骤:
	//1、创建数组
	//2、创建函数实现冒泡排序
	//3、打印排序后的数组

//2、冒泡排序函数创建
//参数1 数组首地址,参数2 数组长度
void bubblesort(int * arr,int len)
{
	for (int i = 0; i < len-1; i++)
	{
		for (int j = 0; j < len - i - 1; j++)
		{
			//如果j>j+1的值,交换数字
			if (arr[j] > arr[j + 1])
			{
				int temp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = temp;
			}
		}
	}

}
//3、打印数组
void print_arr(int* arr, int len)
{
	for (int i = 0; i < 10; i++)
	{
		cout << arr[i] << " ";
	}
	cout << endl;
}
void case_point_array_func() {
	//1、创建数组
	int arr[10] = { 4,3,6,9,1,2,10,8,7,5 };
	// 数组长度
	int len = sizeof(arr) / sizeof(arr[0]);
	//2、冒泡排序函数创建
	bubblesort(arr, len);
	//3、打印数组
	print_arr(arr, len);
	
}

结果:
在这里插入图片描述
本章所有代码:

#include<iostream>
#include<string>
using namespace std;

//指针定义
void point_define()
{

	//1、如何定义指针

	int a = 10;
	//指针定义的语法:数据类型 *指针变量名;
	int* p;
	//让指针记录变量a的地址
	p = &a;//取a的地址,指针p记录这个地址
	cout << "a的地址是:" << &a << endl;
	cout << "指针p=" << p << endl;
	//2、使用指针
	//可以通过解引用的方式来找到指针指向的内存
	//指针前加"*"代表解引用,找到指针指向的内存中的数据
	cout << "=======================" << endl;
	*p = 1000;//可以修改内存指向的值
	cout << "a=" << a << endl;
	cout << "*p=" << *p << endl;


}
//指针所占内存空间
void point_space()
{
	//指针所占空间
	int a = 10;
	int* p = &a;
	//在32为操作系统下,指针都是占4个字节大小,不管是什么数据类型。在64位操作系统下,指针都是占8个字节大小,不管是什么数据类型。
	cout << "sizeof int * =" <<sizeof(p) <<endl;
	cout << "sizeof float * =" << sizeof(float*) << endl;
	cout << "sizeof double * =" << sizeof(double*) << endl;
	cout << "sizeof char * =" << sizeof(char*) << endl;
}
//空指针
void null_point()
{
	
	
	//1、初始化指针变量
	 int* p = NULL;
	//2、空指针是不可以进行访问的,因为0-255之间的内存编号是系统占用的,不可以访问
	 *p = 100;
	 //cout<<*p<<endl;


}
//野指针
void wild_point()
{
	//指针变量p指向内存地址编号为0x1100的地址
	//在程序中,尽量避免出现野指针
	int* p = (int *)0x1100;
	cout << *p << endl;

}
// const 指针常量、常量指针
void const_point()
{
	//1 、const修饰指针 常量指针
	int a = 10;
	int b = 10;
	//指针指向的值不可以改变,但指向可以改变
	const int* p = &a;
	//*p=20; //错误
	p = &b;

	//2、const修饰常量 指针常量
	//指针的指向不可以改,指针指向的值可以改
	int* const p2 = &a;
	*p2 = 100; //正确
	//p2 = &b;//错误,指针指向不可以改

	//3、const修饰指针和常量
	const int* const p3 = &a;
	//指针指向和常量都不可以改
	//*p3 = 100;//错误
	//p3 = &b;//错误



}
//利用指针访问数组中的元素
void point_array() {
	
	int arr[] = {1,2,3,4,5,6,7,8,9,10};
	cout << "第一个元素为:"<<arr[0] << endl;
	int* p = arr;//利用指针指向数组名,arr就是数组首地址
	//利用指针来访问数组第一个元素
	cout << "指针访问的第一个元素为:" << *p << endl;
	p++;//指针会往后+4个字节,就会到第二个元素
	cout << "指针访问的第二个元素为:" << *p << endl;
	cout << "for循环指针遍历数组:" << endl;
	int* p2 = arr;
	for (int i = 0; i < 10; i++)
	{
		cout << *p2 << " ";
		p2++;
	}
	cout << endl;
}
//指针和函数
void swap001(int a,int b) //2个数字交换,值传递
{
	int temp = a;
	a = b;
	b = temp;
}
void swap002(int *p1, int *p2) //2个数字交换,地址传递
{
	int temp = *p1;
	*p1 = *p2;
	*p2 = temp;
}
void value_swap()
{
	//1、值传递
	int a = 10;
	int b = 20;
	swap001(a, b);
	cout << "a= " << a << endl;
	cout << "b= " << b << endl;//实参不会发生改变
	cout << "============="<<endl;
	//2、地址传递
	swap002(&a, &b);
	cout << "a= " << a << endl;
	cout << "b= " << b << endl;//实参a和b发生了改变

}
//指针、数组和函数的小案例
	//步骤:
	//1、创建数组
	//2、创建函数实现冒泡排序
	//3、打印排序后的数组

//2、冒泡排序函数创建
//参数1 数组首地址,参数2 数组长度
void bubblesort(int * arr,int len)
{
	for (int i = 0; i < len-1; i++)
	{
		for (int j = 0; j < len - i - 1; j++)
		{
			//如果j>j+1的值,交换数字
			if (arr[j] > arr[j + 1])
			{
				int temp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = temp;
			}
		}
	}

}
//3、打印数组
void print_arr(int* arr, int len)
{
	for (int i = 0; i < 10; i++)
	{
		cout << arr[i] << " ";
	}
	cout << endl;
}
void case_point_array_func() {
	//1、创建数组
	int arr[10] = { 4,3,6,9,1,2,10,8,7,5 };
	// 数组长度
	int len = sizeof(arr) / sizeof(arr[0]);
	//2、冒泡排序函数创建
	bubblesort(arr, len);
	//3、打印数组
	print_arr(arr, len);
	
}
int main()
{
	//point_define();
	//point_space();
	//null_point();
	//wild_point();
	//const_point();
	//point_array();
	//value_swap();
	case_point_array_func();
	return 0;

}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
FP-growth算法是一种用于频繁项集挖掘的算法,它可以高效地挖掘大规模数据集中的频繁项集。在FP-growth算法中,首先构建一个称为FP树的数据结构,然后通过对FP树的遍历来挖掘频繁项集。本文将介绍如何使用C++实现FP-growth算法,并通过一个具体的案例来说明算法的应用。 一、FP-growth算法原理 FP-growth算法的主要思想是基于频繁项集的增长,通过构建FP树来高效地挖掘频繁项集。其基本流程如下: 1.扫描数据集,统计每个项的支持度,将支持度不低于阈值的项作为频繁项集; 2.按支持度从高到低排序频繁项集,构建FP树; 3.从FP树的根节点开始,对每个频繁项集进行遍历,找到包含该项集的所有路径,即条件模式基; 4.对每个条件模式基,递归地构建条件FP树,并以此挖掘频繁项集。 二、FP-growth算法C++实现 下面是FP-growth算法的C++实现代码,其中使用了类的封装来优化代码结构: ```cpp #include<iostream> #include<fstream> #include<cstring> #include<vector> #include<algorithm> #include<map> using namespace std; //定义FP树节点类 class TreeNode{ public: string name; //节点名称 int count; //节点计数 TreeNode* parent; //节点父亲 vector<TreeNode*> children; //节点孩子 TreeNode(string n, int c, TreeNode* p){ name = n; count = c; parent = p; } }; //定义FP树类 class FPTree{ public: TreeNode* root; //根节点 map<string, int> headerTable; //头指针表 FPTree(){ root = new TreeNode("", 0, NULL); } //插入一条事务 void insert(vector<string> trans, int count){ TreeNode* cur = root; for(int i=0; i<trans.size(); i++){ bool flag = false; for(int j=0; j<cur->children.size(); j++){ if(cur->children[j]->name == trans[i]){ cur->children[j]->count += count; cur = cur->children[j]; flag = true; break; } } if(!flag){ TreeNode* node = new TreeNode(trans[i], count, cur); cur->children.push_back(node); cur = node; if(headerTable.find(trans[i]) == headerTable.end()){ headerTable[trans[i]] = node->count; }else{ headerTable[trans[i]] += node->count; } } } } //获取指定项的条件模式基 vector<pair<vector<string>, int> > getCondPatternBase(string item){ vector<pair<vector<string>, int> > condPatternBase; if(headerTable.find(item) != headerTable.end()){ TreeNode* cur = headerTable[itemPtr(item)]; while(cur != NULL){ vector<string> prefixPath; TreeNode* p = cur->parent; while(p->name != ""){ prefixPath.push_back(p->name); p = p->parent; } if(prefixPath.size() > 0){ reverse(prefixPath.begin(), prefixPath.end()); condPatternBase.push_back(make_pair(prefixPath, cur->count)); } cur = cur->children.size() > 0 ? cur->children[0] : NULL; } } return condPatternBase; } //获取指定项的指针 TreeNode* itemPtr(string item){ if(headerTable.find(item) != headerTable.end()){ return headerTable[item]; }else{ return NULL; } } }; //定义项集类 class Itemset{ public: vector<string> items; //项集中的项 int count; //项集出现次数 Itemset(vector<string> i, int c){ items = i; count = c; } }; //比较器,用于将项按支持度从高到低排序 bool cmp(const Itemset& a, const Itemset& b){ return a.count > b.count; } //FP-growth算法 vector<Itemset> FPgrowth(vector<vector<string> > trans, double minsup){ map<string, int> freqItems; //频繁项集及其支持度 for(int i=0; i<trans.size(); i++){ for(int j=0; j<trans[i].size(); j++){ if(freqItems.find(trans[i][j]) == freqItems.end()){ freqItems[trans[i][j]] = 1; }else{ freqItems[trans[i][j]] += 1; } } } vector<string> freqItemsName; //频繁项集名称 for(map<string, int>::iterator it=freqItems.begin(); it!=freqItems.end(); it++){ if(double(it->second)/double(trans.size()) >= minsup){ freqItemsName.push_back(it->first); } } sort(freqItemsName.begin(), freqItemsName.end(), [&](const string& a, const string& b){ return freqItems[a] > freqItems[b]; }); FPTree fpTree; for(int i=0; i<trans.size(); i++){ vector<string> transSorted; for(int j=0; j<freqItemsName.size(); j++){ if(find(trans[i].begin(), trans[i].end(), freqItemsName[j]) != trans[i].end()){ transSorted.push_back(freqItemsName[j]); } } fpTree.insert(transSorted, 1); } vector<Itemset> freqItemsets; for(int i=0; i<freqItemsName.size(); i++){ vector<pair<vector<string>, int> > condPatternBase = fpTree.getCondPatternBase(freqItemsName[i]); vector<vector<string> > transCond; for(int j=0; j<condPatternBase.size(); j++){ vector<string> transCondJ; for(int k=0; k<condPatternBase[j].second; k++){ transCondJ.insert(transCondJ.end(), condPatternBase[j].first.begin(), condPatternBase[j].first.end()); } transCond.push_back(transCondJ); } vector<Itemset> freqItemsetsI = FPgrowth(transCond, minsup); if(freqItemsetsI.size() > 0){ for(int j=0; j<freqItemsetsI.size(); j++){ freqItemsetsI[j].items.insert(freqItemsetsI[j].items.begin(), freqItemsName[i]); } freqItemsets.insert(freqItemsets.end(), freqItemsetsI.begin(), freqItemsetsI.end()); } if(double(freqItems[freqItemsName[i]])/double(trans.size()) >= minsup){ freqItemsets.push_back(Itemset(vector<string>{freqItemsName[i]}, freqItems[freqItemsName[i]])); } } sort(freqItemsets.begin(), freqItemsets.end(), cmp); return freqItemsets; } //读取数据集 vector<vector<string> > readData(string filename){ vector<vector<string> > trans; ifstream fin(filename); string line; while(getline(fin, line)){ vector<string> transI; char* str = strtok(const_cast<char*>(line.c_str()), " "); while(str != NULL){ transI.push_back(str); str = strtok(NULL, " "); } trans.push_back(transI); } return trans; } //输出频繁项集 void printFreqItemsets(vector<Itemset> freqItemsets){ for(int i=0; i<freqItemsets.size(); i++){ cout << "频繁项集: {"; for(int j=0; j<freqItemsets[i].items.size(); j++){ cout << freqItemsets[i].items[j] << " "; } cout << "},支持度: " << freqItemsets[i].count << endl; } } int main(){ vector<vector<string> > trans = readData("data.txt"); double minsup = 0.4; vector<Itemset> freqItemsets = FPgrowth(trans, minsup); printFreqItemsets(freqItemsets); return 0; } ``` 三、FP-growth算法案例 假设有一个数据集如下: ``` A B C D A B C E A B D E A C D E B C D E ``` 使用上述C++代码对该数据集进行频繁项集挖掘,设置最小支持度为0.4。运行结果如下: ``` 频繁项集: {A B},支持度: 4 频繁项集: {C D},支持度: 4 频繁项集: {B C},支持度: 3 频繁项集: {B D},支持度: 3 频繁项集: {B E},支持度: 3 频繁项集: {C E},支持度: 3 频繁项集: {D E},支持度: 3 频繁项集: {A C},支持度: 2 频繁项集: {A D},支持度: 2 ``` 从结果可以看出,在最小支持度为0.4的情况下,频繁项集包括{A B}、{C D}、{B C}、{B D}、{B E}、{C E}、{D E}、{A C}和{A D}。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值