数据结构之间接寻址

本文探讨了数据结构中的一种方法——间接寻址,通过结合数组和指针,存储指向数据元素的指针而非元素本身。文章介绍了算法设计,提供了C++的详细实现,并进行了测试,展示运行结果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一.引入

        间接寻址是将数组和指针结合起来的一种方法,它将数组中存储数据元素的单元改为存储指向该元素的指针。


二.算法设计

IndirAddress.h

#ifndef SRC_INDIRADDRESS_H_
#define SRC_INDIRADDRESS_H_

template <class T>
class IndirAddress {
public:
	IndirAddress();//无参构造器
	IndirAddress(T array[],int length);//带参构造器
	virtual ~IndirAddress();//空的析构函数
	int getLength();//返回当前长度
	void getAll();//遍历当前数组
	T getByIndex(int index);//通过角标获得元素
	void getByValue(T value);//通过值获得该元素所在的位置
	void insert(int index,T value);//插入:可以实现在头部、元素间和尾部插入。
	void removeByIndex(int index);//通过角标移除元素
	void removeByValue(T value);//通过值移除元素:可以移除所有的
	void updateByIndex(int index,T value);//通过角标修改元素的值
	void updateByValue(T oldValue,T newValue);//通过值修改元素的值
private:
	static const int MAX_LENGTH = 30;//静态数组的最大长度
	T array[MAX_LENGTH];//静态数组,存储元素
	T *address[MAX_LENGTH];//存储数组中元素的地址,即 address[0] 存储的是数组第一个元素的地址,address[1] 存储的是数组第二个元素的地址。
	                      //注意:数组中第一个元素的地址不一定存储在 address[0] ,类似
	int length;//当前静态数组的长度
	bool checkIndex(int index);//检查角标是否合法
};

#endif

三.详细设计(C++)

IndirAddress.cpp

#include "IndirAddress.h"
#include <iostream>
using namespace std;

/*
 * 检查角标:
 * 角标小于0或大于等于最大长度和当前长度都视为非法,返回 false ,否则返回 true 。
 */
template <class T>
bool IndirAddress<T>::checkIndex(int index){
	if(index < 0){
		cout<<"角标不能小于0!"<<endl;
		return false;
	}
	if(index >= MAX_LENGTH){
		cout<<"角标越界,最大长度为:"<<MAX_LENGTH<<"!"<<endl;
		return false;
	}
	if(index >= length){
		cout<<"角标越界,当前长度为:"<<length<<"!"<<endl;
		return false;
	}
	return true;
}
/*
 * 无参构造器:
 * 初始化当前静态数组的长度为0
 */
template <class T>
IndirAddress<T>::IndirAddress(){
	length = 0;
}
/*
 * 带参构造器:
 * 1.判断传入的数组的长度,如果传入的数组的长度大于静态数组的最大长度,返回,否则
 * 2.循环,依次给静态数组赋值,并把每一个数组元素的地址存储起来
 * 3.记录当前长度
 */
template <class T>
IndirAddress<T>::IndirAddress(T array[],int length){
	if(length > MAX_LENGTH){
		cout<<"长度过大,最大长度为:"<<MAX_LENGTH<<"!"<<endl;
		return;
	}
	for(int i = 0;i < length;i++){
		this->array[i] = array[i];
		address[i] = &this->array[i];
	}
	this->length = length;
}
/*
 * 空的析构函数
 */
template <class T>
IndirAddress<T>::~IndirAddress(){
}
/*
 * 返回当前长度
 */
template <class T>
int IndirAddress<T>::getLength(){
	return length;
}
/*
 * 遍历当前数组:
 * 依次遍历 address 指针,输出其指向的地址的值
 */
template <class T>
void IndirAddress<T>::getAll(){
	if(length == 1){
		cout<<"["<<*address[0]<<"]"<<endl;
	}else{
		for(int i = 0;i < length;i++){
			if(i == 0){
				cout<<"["<<*address[i]<<",";
			}else if(i == length-1){
				cout<<*address[i]<<"]"<<endl;
			}else{
				cout<<*address[i]<<",";
			}
		}
	}
}
/*
 * 通过角标获得元素:
 * 1.判断角标是否合法,若不合法返回 -1 ,否则
 * 2.返回 address[index] 指向的地址的值
 */
template <class T>
T IndirAddress<T>::getByIndex(int index){
	if(!checkIndex(index)){
		return -1;
	}
	return *address[index];
}
/*
 * 通过值获得该元素所在的位置:
 * 1.定义一个标记 flag,初始化为 false ,用来记录是否找到该值
 * 2.遍历 address 指针,判断其指向的地址的值是否等于 value ,若是,输出该元素的位置,并把 flag 赋值为 true
 * 3.若找不到与 value 相等的,输出“没有此值!”
 */
template <class T>
void IndirAddress<T>::getByValue(T value){
	bool flag = false;
	for(int i = 0;i < length;i++){
		if(*address[i] == value){
			cout<<"arr["<<i<<"]="<<*address[i]<<" ";
			flag = true;
		}
	}
	if(!flag){
		cout<<"没有此值!"<<endl;
	}
}
/*
 * 插入:可以实现在头部、元素间和尾部插入。
 * 1.判断角标是否合法,若不合法返回(注意:此处的 index 可以等于 length ) ,否则
 * 2.在当前静态数组的尾部存储新插入的元素的值
 * 3.循环,把 address 指针从尾部依次后移一位,直到到达 index 处
 * 4.把新插入的数组元素的地址赋给 address[index]
 * 5.当前长度加一
 * >如:在数组[0,1,2,3]的0和1之间插入元素5,就
 *    ①.把5赋给 array[4]
 *    ②.把 address[3] 存储的地址赋给 address[4] ,
 *      把 address[2] 存储的地址赋给 address[3] ,
 *      把 address[1] 存储的地址赋给 address[2] ,
 *    ③.把 array[4] 的地址赋给 address[1]
 */
template <class T>
void IndirAddress<T>::insert(int index,T value){
	if(index == length){
		goto A;
	}else if(!checkIndex(index)){
		return;
	}
	A:array[length] = value;
	for(int i = length;i > index;i--){
		address[i] = address[i-1];
	}
	address[index] = &array[length];
	length++;
}
/*
 * 通过角标移除元素:
 * 1.判断角标是否合法,若不合法返回,否则
 * 2.循环,把 address[index+1] 存储的地址依次向前赋值
 * 3.当前长度减一
 * >如:在数组[0,1,2,3]中移除1,就
 *     把 address[2] 存储的地址赋给 address[1] ,
 *     把 address[3] 存储的地址赋给 address[2]
 */
template <class T>
void IndirAddress<T>::removeByIndex(int index){
	if(!checkIndex(index)){
		return;
	}
	for(int i = index;i < length-1;i++){
		address[i] = address[i+1];
	}
	length--;
}
/*
 * 通过值移除元素:可以移除所有的
 * 1.定义一个标记 flag,初始化为 false ,用来记录是否找到该值
 * 2.定义一个角标 index ,初始化为 0 ,用来记录遍历到第几个元素
 * 3.定义一个长度 length ,初始化为当前长度,用来确保遍历到当前数组的所有元素
 * 4.遍历 address ,通过 address 指向的地址找到元素的值,判断此值是否与 value 相等
 *   若相等,调用 removeByIndex(int index) 方法,传入 index ,把  flag 赋值为 true
 *   否则,index++,
 * 5.若找不到与 value 相等的元素,输出“没有此值!”
 */
template <class T>
void IndirAddress<T>::removeByValue(T value){
	bool flag = false;
	int index = 0;
	int length = this->length;
	for(int i = 0;i < length;i++){
		if(*address[index] == value){
			removeByIndex(index);
			flag = true;
		}else{
			index++;
		}
	}
	if(!flag){
		cout<<"没有此值!"<<endl;
	}
}
/*
 * 通过角标修改元素的值:
 * 1.判断角标是否合法,若不合法返回 ,否则
 * 2.把 address[index] 指向的元素的值修改为 value
 */
template <class T>
void IndirAddress<T>::updateByIndex(int index,T value){
	if(!checkIndex(index)){
		return;
	}
	*address[index] = value;
}
/*
 * 通过值修改元素的值:
 * 1.定义一个标记 flag,初始化为 false ,用来记录是否找到该值
 * 2.遍历 address ,若当前 address 指向的元素的值等于 oldValue ,则把该元素的值修改为 newValue ,并把 flag 赋值为 true
 * 3.若找不到与 value 相等的,输出“没有此值!”
 */
template <class T>
void IndirAddress<T>::updateByValue(T oldValue,T newValue){
	bool flag = false;
	for(int i = 0;i < length;i++){
		if(*address[i] == oldValue){
			*address[i] = newValue;
			flag = true;
		}
	}
	if(!flag){
		cout<<"没有此值!"<<endl;
	}
}

四.测试

TestIndirAddress.cpp

#include "IndirAddress.h"
#include "IndirAddress.cpp"
#include <iostream>
using namespace std;
int main(int argc, char **argv) {
	int arr[] = {0,1,2,3,4,5,4,3,2,1,0};
	cout<<"创建对象:"<<endl;
	IndirAddress<int> indirAddress(arr,11);
	cout<<"当前长度:"<<indirAddress.getLength()<<endl;
	cout<<"遍历对象:";
	indirAddress.getAll();
	cout<<endl;

	cout<<"获得角标为6的值:"<<indirAddress.getByIndex(6)<<endl;
	cout<<endl;

	cout<<"获得值为0的元素的位置:"<<endl;
	indirAddress.getByValue(0);
	cout<<endl<<endl;

	cout<<"在角标为6处插入6:"<<endl;
	indirAddress.insert(6,6);
	cout<<"当前长度:"<<indirAddress.getLength()<<endl;
	cout<<"遍历对象:";
	indirAddress.getAll();
	cout<<endl;

	cout<<"移除角标为6的元素:"<<endl;
	indirAddress.removeByIndex(6);
	cout<<"当前长度:"<<indirAddress.getLength()<<endl;
	cout<<"遍历对象:";
	indirAddress.getAll();
	cout<<endl;

	cout<<"移除值为0的元素:"<<endl;
	indirAddress.removeByValue(0);
	cout<<"当前长度:"<<indirAddress.getLength()<<endl;
	cout<<"遍历对象:";
	indirAddress.getAll();
	cout<<endl;

	cout<<"把角标为4的元素的值修改为4:"<<endl;
	indirAddress.updateByIndex(4,4);
	cout<<"遍历对象:";
	indirAddress.getAll();
	cout<<endl;

	cout<<"把值为4的元素的值修改为0:"<<endl;
	indirAddress.updateByValue(4,0);
	cout<<"遍历对象:";
	indirAddress.getAll();
	cout<<endl;

	return 0;
}

五.运行结果



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值