ArrayList(线性表)
定义:
线性表是 n(n>0) 个相同类型数据元素构成的有限序列,其中n为线性表的长度。
只讨论单位操作,因为范围操作不过是多次单位操作而已,对于数据结构而言知道最基本的操作即可实现稍复杂的操作
除此之外有些函数方法返回的可能是元素,也可能是bool值,而把所需值传给引用参数
线性表应有的基本操作:
Function | Describe | O |
---|---|---|
ArrayList() | 建立一个新的空表 | 1 |
ArrayList(Array) | 用数组元素依次建立线性表 | n |
getItem(idx) | 返回索引为idx的元素,idx为-1时返回最后一个 | 1 |
getIdx(item) | 返回遇到的第一个与item相同的元素索引,无返回-1 | n |
removeItem(idx) | 删除索引为idx的元素 | n |
size() | 返回线性表的元素数量 | 1 |
contains(item) | 判断元素item是否在线性表中 | n |
empty() | 判空 | 1 |
insert(idx, item) | 在索引idx处,插入新元素item | n |
push(item) | 尾插item元素 | 1 |
clear() | 清空线性表 | 1 |
set(idx, item) | 将索引idx处元素更改为item,并返回原元素 | 1 |
expand() | 扩容 | n |
/**
ArrayList(线性表的实现)
函数列表:
| ArrayList() | 建立一个新的空表 | 1 |
| ArrayList(Array) | 用数组元素依次建立线性表 | n |
| getItem(idx) | 返回索引为idx的元素,idx为-1时返回最后一个 | 1 |
| getIdx(item) | 返回遇到的第一个与item相同的元素索引,无返回-1 | n |
| removeItem(idx) | 删除索引为idx的元素 | n |
| size() | 返回线性表的元素数量 | 1 |
| contains(item) | 判断元素item是否在线性表中 | n |
| empty() | 判空 | 1 |
| insert(idx, item) | 在索引idx处,插入新元素item | n |
| push(item) | 尾插item元素 | 1 |
| clear() | 清空线性表 | 1 |
| set(idx, item) | 将索引idx处元素更改为item,并返回原元素 | 1 |
| expand() | 扩容 | n |
此处函数列表多针对于面向对象语言实现,C语言无法完全相似实现
固看到的方法实现可能有些不同,下面会详细解释
*/
#include <stdio.h>
// 声明ArrayList结构体(类) ,以及结构体指针 list
typedef struct {
int* Array;
int _size; // 元素数量
int _capacity; // 容量
} _list, *list;
// 函数声明处
list ArrayList();
list ArrayListByAr(int*, int);
void expand(list);
int size(list);
void push(list, int);
int getItem(list, int);
int getIdx(list, int);
void removeItem(list, int);
int removeIdx(list, int);
int contains(list, int);
int insert(list, int, int);
void clear(list);
int set(list , int , int );
// 函数实现处
list ArrayList() {
/**
通过malloc在堆区开辟一整块array数组,然后将地址返回
*/
list array_list = (list)malloc(sizeof(_list));
array_list->_capacity = 20; // 初始容量为20
array_list->Array = (int*)malloc(array_list->_capacity * sizeof(int)); //开辟空间
array_list->_size = 0; // 初始元素数量为0
return array_list;
}
void expand(list array_list){
/**
扩容函数的实现是重新开辟一段更大的数组空间,
随后将原数组元素重录到新数组中,然后释放原数组空间
最后将线性表的数组指针指向新数组
*/
array_list->_capacity *= 1.5; // 更新容量
int* Array = (int*)malloc(array_list->_capacity * sizeof(int) ); // 开辟更大的空间 ,容量为capacity
int i;
for(i = 0; i < array_list->_size; i++) {
Array[i] = array_list->Array[i];
} // 重录
free(array_list->Array); // 释放缓存
array_list->Array = Array; // 更换指针
}
list ArrayListByAr(int* arr, int size){
list array_list = (list)malloc(sizeof(_list)); // 建立线性表
if(size >= 20){
array_list->_capacity = size + 10; // 初始容量为size + 10
array_list->Array = (int*)malloc(array_list->_capacity * sizeof(int)); //开辟空间
array_list->_size = size; // 初始元素数量为0
}
else{
array_list = ArrayList();
array_list->_size = size;
}
int i = 0;
for(; i < size; i++) {
array_list->Array[i] = arr[i];
}
return array_list;
}
void show(list array_list){
printf("ArrayList = [");
int i;
for(i = 0; i < array_list->_size - 1; i++){
printf("%d, ", array_list->Array[i]);
}
if(array_list->_size) printf("%d", array_list->Array[array_list->_size - 1]);
printf("]\n");
}
int size(list array_list){
return array_list->_size;
}
void push(list array_list, int item){
// 检查是否空间足够, 不够则扩容
if(array_list->_capacity == array_list->_size) expand(array_list);
array_list->Array[(array_list->_size)++] = item;
}
int getItem(list array_list, int idx){
/**
可能会存在idx不合法的情况,但有异常处理手段
此处不做处理 ,c语言特性会返回一个物理存储上的随机数
*/
// if(idx < 0 || idx >= array_list->_size) 异常处理;
return array_list->Array[idx];
}
int getIdx(list array_list, int item){
/**
根据元素返回索引,可能会存在元素不存在情况,
我们返回非法索引-1
*/
int i = 0; for(;i < array_list->_size; i++){
if(array_list->Array[i] == item) return i;
}
return -1;
}
void removeItem(list array_list, int item){
/**
删除第一个遇到的item元素
*/
int i = 0; for(;i < array_list->_size; i++){
if(array_list->Array[i] == item){
int j = i + 1;for(;j < array_list->_size; j++){
array_list->Array[j - 1] = array_list->Array[j];
}
array_list->_size--;
return;
}
}
}
int removeIdx(list array_list, int idx){
/**
此处同样存在idx不合法情况,我们针对性的返回0表示错误
1表示删除成功, 同样的,idx = -1 时我们认为是末尾元素
*/
if(idx == -1) idx = array_list->_size - 1;
if(idx < 0 || idx >= array_list->_size) return 0;
int i = idx + 1; for(;i < array_list->_capacity; i++){
array_list->Array[i - 1] = array_list->Array[i];
}
array_list->_size --;
return 1;
}
int contains(list array_list, int item){
/**
判断item存不存在,存在返回1, 否则返回0
*/
int i = 0; for(;i < array_list->_size; i++){
if(array_list->Array[i] == item) return 1;
}
return 0;
}
int insert(list array_list, int idx, int item){
/**
将元素item插入索引item处,我们需要将idx之后的所有元素后移 ,
若idx为-1,表示在末尾之前插入 , 插入成功则返回1, 否则返回0
*/
if(idx < -1 || idx > array_list->_size) return 0;
if(idx == -1) {
idx = array_list->_size - 1;
}
int i = array_list->_size; for(;i > idx; i--){
array_list->Array[i] = array_list->Array[i - 1];
}
array_list->Array[idx] = item;
array_list->_size ++;
return 1;
}
void clear(list array_list){
/**
为了节省时间,我们可以直接将_size赋0
*/
array_list->_size = 0;
}
int set(list array_list, int idx, int item){
/**
将索引为idx处的元素替换为 item, 并返回原元素
同样存在索引越界问题,由于c语言的性质,此处仍不考虑
下标为-1时表示替换最后的元素
*/
if(idx == -1) idx = array_list->_size - 1;
int oldItem = array_list->Array[idx];
array_list->Array[idx] = item;
return oldItem;
}
int main(){
list array_list = ArrayList();
// int a[21] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21};
// list array_list = ArrayListByAr(a, 21);
int i = 21; for(;i <= 50; i++) push(array_list, i);
show(array_list);
// printf("获取值:%d", getItem(array_list, 3));
// printf("获取索引:%d", getIdx(array_list, 23));
// removeItem(array_list, 40);
// removeIdx(array_list, 1);
// int num = 51;
// if(contains(array_list, num)) printf("%d 存在\n", num);
// else printf("%d 不存在\n", num);
// int num = 99;
// if(insert(array_list, 0, num)) printf("%d 插入成功!\n", num);
// else printf("%d 插入失败!\n", num);
// if(insert(array_list, -1, num)) printf("%d 插入成功!\n", num);
// else printf("%d 插入失败!\n", num);
// if(insert(array_list, 99, num)) printf("%d 插入成功!\n", num);
// else printf("%d 插入失败!\n", num);
// clear(array_list);
// int oldItem = set(array_list, 0, 100);
// int oldItem = set(array_list, 1, 100);
// int oldItem = set(array_list, -1, 100);
// printf("%d 已被替换\n", oldItem);
show(array_list);
return 0;
}
// printf("passed!\n");