一.引入
间接寻址是将数组和指针结合起来的一种方法,它将数组中存储数据元素的单元改为存储指向该元素的指针。
二.算法设计
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;
}
五.运行结果