数组
1.数组的初始化
// 存储在栈上
int arr[5];
int nums[5] = { 1, 2, 3, 4, 5 };
//存储在堆上
int* agg = new int[5];
int* ngg = new int[5] {1, 2, 3, 4, 5};
2.数组的检索
int access(int* ngg, int i)
{
return *(ngg + i);
}
3.数组的数据插入
void insert(int* ngg, int size, int num, int index)
{
for (int i = size - 1; i > index; i--)
{
ngg[i] = ngg[i - 1];
}
ngg[index] = num;
}
4.遍历数组
for (int j = 0; j < 5; j++)
{
std::cout <<*(ngg+j)<<std::endl;
}
5.在数组中查找指定元素
int find(int* ngg, int size, int target)
{
for (int i = 0; i < size; i++)
{
if (ngg[i] == target)
return i;
}
return -1;
}
6.扩展数组长度
int* extend(int* nums, int size, int enlarge)
{
int* res = new int[size + enlarge];
for (int i = 0; i < size; i++)
{
*(res + i) = *(nums + i);
}
delete[] nums;
return res;
}
7.集合
#include <iostream>
int access(int* ngg, int i);
void insert(int* ngg, int size, int num, int index);
int find(int* ngg, int size, int target);
int* extend(int* nums, int size, int enlarge);
int main()
{
// 存储在栈上
int arr[5];
int nums[5] = { 1, 2, 3, 4, 5 };
//存储在堆上
int* agg = new int[5];
int* ngg = new int[5] {1, 2, 3, 4, 5};
int* res = extend(ngg, 5, 3);
for (int i = 0; i < sizeof(res); i++)
{
std::cout<<*(res+i)<<std::endl;
}
}
int access(int* ngg, int i)
{
return *(ngg + i);
}
// 需要传入数组,大小,索引,数据
void insert(int* ngg, int size, int num, int index)
{
for (int i = size - 1; i > index; i--)
{
ngg[i] = ngg[i - 1];
}
ngg[index] = num;
}
int find(int* ngg, int size, int target)
{
for (int i = 0; i < size; i++)
{
if (ngg[i] == target)
return i;
}
return -1;
}
int* extend(int* nums, int size, int enlarge)
{
int* res = new int[size + enlarge];
for (int i = 0; i < size; i++)
{
*(res + i) = *(nums + i);
}
delete[] nums;
return res;
}
8.总结
1)数组的插入和删除空间复杂度为O(n),但 随机访问只需要O(1);
2) 空间效率高,缓存局部性:当访问数组元素时,计算机不仅会加载它,还会缓存其周围的其它数据,从而借助高速缓存来提升后续操作的执行速度;
3)长度不可变以及空间浪费
链表
1.链表的初始化
struct ListNode {
int val;
ListNode* next;
ListNode(int x):val(x),next(nullptr){}
};
int main()
{
ListNode* n0 = new ListNode(1);
ListNode* n1 = new ListNode(3);
ListNode* n2 = new ListNode(2);
ListNode* n3 = new ListNode(5);
ListNode* n4 = new ListNode(4);
n0->next = n1;
n1->next = n2;
n2->next = n3;
n3->next = n4;
}
2.链表插入:时间复杂度只有O(1)。
void insert(ListNode* n0, ListNode* P)
{
ListNode* n1 = n0->next;
P->next = n1;
n0->next = P;
}
一开始看的时候有一个误区,因为我代码是写在一块的,以为第一句是可省的,实际上是不可以的,该句保存了原始节点的next指针。
3.删除链表节点
void remove(ListNode* n0)
{
ListNode* P = n0->next;
ListNode* n1 = P->next;
n0->next = n1;
delete P;
}
4.访问链表元素
访问链表元素必须遍历该索引之前的链表,因此比较麻烦。
ListNode* access(ListNode* head, int index)
{
for (int i = 0; i < index; i++)
{
if (head == nullptr)
return nullptr;
head = head->next;
}
return head;
}
5.查找索引
int find(ListNode* head, int target)
{
int index = 0;
while (head!= nullptr)
{
if (head->val == target)
return index;
head = head->next;
index++;
}
return -1;
}
6.双向链表
常用于浏览器索引
struct ListNode {
int val;
ListNode* next;
ListNode* pre;
ListNode(int x) :val(x), next(nullptr), pre(nullptr) {}
};