什么是数据结构?
接下来我们手写一个动态数组
首先动态数组的接口设计如下:
实现代码如下:
#import
//修饰属性的类型,如果一个类属性的类型并不确定,那么就可以通过创建对象的时候来控制类的类型
@interface ArrayList <__covariant objectType> : NSObject
//元素数量
@property (readonly) NSUInteger count;
@property (nullable, nonatomic, readonly) id firstObject;
@property (nullable, nonatomic, readonly) id lastObject;
/**
默认初始化
@return 实例对象
*/
+ (instancetype)arrary;
/**
类方法初始化
@param numItems 初始数量
@return 实例对象
*/
+ (instancetype)arrayWithCapacity:(NSUInteger)numItems;
/**
对象方法初始化
@param numItems 初始数量
@return 实例对象
*/
- (instancetype)initWithCapacity:(NSUInteger)numItems;
/**
取某个位置的元素
@param numItems 参数
*/
- (objectType)objectAtIndex:(NSUInteger)numItems;
/**
查看某个元素的下标
@param anObject 某个元素
@return index
*/
- (objectType)indexOfobject:(objectType)anObject;
/**
是否包含某个元素
@param anObject 某个元素
@return 是否包含
*/
- (BOOL)containsObject:(objectType)anObject;
/**
添加元素
@param anObject 要添加的元素
*/
- (void)addObject:(objectType)anObject;
/**
插入某个元素
@param anObject 某个元素
@param index 要插入的下标
*/
- (void)insertObject:(objectType)anObject atIndex:(NSUInteger)index;
/**
替换某个位置的元素
@param index 要替换的位置
@param anObject 要替换的参数元素
*/
- (void)replaceObjectAtIndex:(objectType)index withObject:(objectType)anObject;
/**
删除所有元素
*/
- (void)removeAllObjects;
/**
删除最后一个元素
*/
- (void)removeLastObjects;
/**
删除某个下标的元素
@param index index
*/
- (void)removeObjectAtIndex:(NSUInteger)index;
/**
删除某个元素
@param anObject 某个元素
*/
- (void)removeObject:(objectType)anObject;
@end
#import "ArrayList.h"
static const int DEFAULT_CAPACITY = 10;
static const int ELEMENT_NOT_FOUND = -1;
typedef void* AnyObject;
@interface ArrayList ()
{
AnyObject *_array; ///<本来是想用 objectType ,但是calloc的去接收的时候会出野指针错误,另外作用域只到interface>
NSInteger _size;
NSInteger _capacity;
}
@end
@implementation ArrayList
/**
默认初始化
@return 实例对象
*/
+ (instancetype)arrary{
return [[self alloc] initWithCapacity:DEFAULT_CAPACITY];
}
/**
类方法初始化
@param numItems 初始数量
@return 实例对象
*/
+ (instancetype)arrayWithCapacity:(NSUInteger)numItems{
return [[self alloc] initWithCapacity:numItems];
}
/**
对象方法初始化
@param numItems 初始数量
@return 实例对象
*/
- (instancetype)initWithCapacity:(NSUInteger)numItems{
_capacity = numItems < DEFAULT_CAPACITY ? DEFAULT_CAPACITY : numItems;
_array = (calloc(numItems, sizeof(AnyObject)));
_size = 0;
return self;
}
/**
取某个位置的元素
@param numItems 参数
*/
- (AnyObject)objectAtIndex:(NSUInteger )numItems{
if (numItems >= _size) {
@throw [NSException exceptionWithName:@"Array is out of bounds" reason:@"out of bounds" userInfo:nil];
return nil;
}
return _array[numItems];
}
/**
查看某个元素的下标
@param anObject 某个元素
@return index
*/
- (AnyObject)indexOfobject:(id)anObject{
for (int i = 0; i < _size; i ++) {
if ([anObject isEqual:anObject]){
return i;
}
}
return ELEMENT_NOT_FOUND;
}
/**
是否包含某个元素
@param anObject 某个元素
@return 是否包含
*/
- (BOOL)containsObject:(AnyObject)anObject{
return [self indexOfobject:(__bridge id)(anObject)] != ELEMENT_NOT_FOUND;
}
/**
添加元素
@param anObject 要添加的元素
*/
- (void)addObject:(id)anObject{
[self insertObject:(anObject) atIndex:_size];
}
- (NSUInteger)count{
return _size;
}
- (void)insertObject:(id)anObject atIndex:(NSUInteger)index{
[self ensureCapacity:_size + 1];
///交换索引位置
if (self.count > 0 ) {
for(NSInteger i = _size - 1 ; i >= index ; i--)
_array[i + 1] = _array[i];
}
self->_array[index] = (__bridge_retained AnyObject)(anObject);
_size++;
}
/**
替换某个位置的元素
@param index 要替换的位置
@param anObject 要替换的参数元素
*/
- (void)replaceObjectAtIndex:(NSInteger)index withObject:(AnyObject)anObject{
_array[index] = anObject;
}
/**
删除所有元素
*/
- (void)removeAllObjects{
for (int i = 0; i < _size - 1; i++) {
_array[i] = NULL;
}
[self resetArray];
}
/**
数组重置
*/
- (void) resetArray {
_size = 0;
// if (_array != NULL)
// _array[_size] = NULL;
// free(_array);
// _capacity = DEFAULT_CAPACITY;
// _array = calloc(_capacity, sizeof(AnyObject));
}
- (void)removeObjectAtIndex:(NSUInteger)index{
if (index >= _size) {
@throw [NSException exceptionWithName:@"Array is out of bounds" reason:@"out of bounds" userInfo:nil];
}
for (int i = index + 1; i < _size; i++) {
_array[i -1 ] = _array[i];
}
_size--;
_array[_size] = NULL;
if (_size == _capacity / 2) {
NSInteger newCapacity = _capacity / 2;
AnyObject *newArr = (calloc(newCapacity , sizeof(AnyObject)));
for (int i = 0; i < _size; i++) {
newArr[i] = _array[i];
}
_array = newArr;
_capacity = newCapacity;
NSLog(@"新容量 %zd",newCapacity);
}
}
/**
删除某个元素
@param anObject 某个元素
*/
- (void)removeObject:(id)anObject{
for (int i = 0; i < _size; i ++) {
if ([anObject isEqual:(__bridge id)(_array[i])]) {
[self removeObjectAtIndex:i];
}
}
}
/**
扩容
*/
- (void)ensureCapacity:(NSInteger)capacity{
if (capacity <= _capacity) {
return;
}
NSInteger newCapacity = _capacity + (_capacity >> 1);
AnyObject *newArr = (calloc(newCapacity , sizeof(AnyObject)));
for (int i = 0; i < _size; i++) {
newArr[i] = _array[i];
}
_array = newArr;
_capacity = newCapacity;
NSLog(@"新容量 %zd",newCapacity);
}
- (NSString *)description {
NSMutableString *string = [NSMutableString stringWithFormat:@"\nArrayList %p : [ \n" ,self];
for (int i = 0; i<_size; i++) {
AnyObject obj = _array[i];
[string appendFormat:@"%@",(__bridge id)obj];
if (i<_size-1) {
[string appendString:@" , \n"];
}
}
[string appendString:@"\n]\n"];
return string;
}
@end
在写动态数组的过程中发现几个问题。
1.范型作用域只有@interface
2.free()函数并没有将数组中的元素释放。。。
3.扩容realloc是一个提高性能的方向,malloc,calloc,realloc都能实现这个功能。。