基本概念
数据:描述客观事物的符号(名字,年龄大小,人物关系,都用符号来表示)
数据对象:具有相同数据特征的数据的集合(Excel里的人员表)
数据元素:数据的基本单位(Excel表里的一行,某个人)
数据项:构成数据元素的最小单位(每一行的一个表格,某个人的学号)
绪论
空间复杂度
O(1):不需要辅助空间
递归函数的空间复杂度
递归函数的参数和局部变量占用的内存空间 随着递去增长,随着归来减小,若递到一定深度时,可能会造成内存空间不足。
算法的原地工作:需要的辅助空间为O(1)(例如:总是只需要100个int的辅助变量就能执行这个程序,强调空间不是时间)
O(n)是数组总量,O(n/2)是递归的平均量 O(n)是最后一个数组总量,O(n/2)是递归的平均量
线性表
顺序表:(静态)数组和动态数组
优点:随机存储快O(1);存储密度大 缺点:插入删除要移动大量元素;要预先分配空间;容量难以扩充。
C++顺序表的实现
动态数组:指针 数组大小
arr size
定义 *arr int size
初始化 arr= new [] size=0
#include<iostream>
using namespace std;
#define MAXSIZE 10
#define ERROR -1
typedef int INT;
//顺序表的定义
struct Sqlist
{
INT* arr;//动态数组 INT arr[MAXSIZE];//静态数组
int size;
Sqlist();//构造函数
~Sqlist();//析构函数
void InsertElem(int i, INT e);//增
void DeleteElem(int i);//删
INT GetElem(int i);//查
void AlterElem(int i, INT e);//改
};
//顺序表的初始化
Sqlist::Sqlist()
{
arr = new INT[MAXSIZE];//分配动态数组的内存空间; 静态数组不用
if (!arr)exit(0);
size = 0;
}
//顺序表的删除
Sqlist:: ~Sqlist()
{
if (arr)
{
delete[] arr;
arr = nullptr;
}
size = 0;
}
//任意位置插入
void Sqlist::InsertElem(int i, INT e)
{
if (i<0 || i>size)return;//检查插入序号是否超过数组,数组值=m最后一位+1
if (size == MAXSIZE)return;//检查数组大小是否超过开辟的最大长度
for (int j = size - 1; j >= i; j--)//j从最后一位开始,到第i位完成为止
{
arr[j + 1] = arr[j];//把前一位赋给后一位
}
arr[i] = e;//把新元素插入第i号位
size++;//数组加一
}
//任意位置删除
void Sqlist::DeleteElem(int i)
{
if (i<0 || i>size - 1)return;
for (; i < size - 1; i++)//i从第i位,到倒数第二位
{
arr[i] = arr[i + 1];//把后一位赋给前一位
}
size--;//数组减一
}
//按序号返回元素
INT Sqlist::GetElem(int i)
{
if (i<0 || i>size - 1)return ERROR;
return arr[i];
}
//改
void Sqlist::AlterElem(int i, INT e)
{
if (i<0 || i>size - 1)return;
arr[i] = e;
}
//打印
void Print(Sqlist& L);
void main()
{
Sqlist L;//声明
cout << L.GetElem(0); //查
L.InsertElem(0, 1); //增
L.AlterElem(0, 2); //改
L.DeleteElem(0); //删
L.~Sqlist();//析构
}
void Print(Sqlist& L)
{
for (int i = 0; i < L.size; i++)
{
cout << L.arr[i] << " ";
}cout << endl;
}
//来点C语言风格的
#include<iostream>
using namespace std;
#define MAXSIZE 10
#define ERROR -1
typedef int INT;
//顺序表的定义
typedef struct
{
INT* arr;//动态数组 INT arr[MAXSIZE];//静态数组
int size;
}Sqlist;
//顺序表的初始化
bool InitList(Sqlist& L)
{
L.arr = new INT[MAXSIZE];//分配动态数组的内存空间; 静态数组不用
if (!L.arr)exit(0);
L.size = 0;
return 1;
}
//顺序表的删除
void DestList(Sqlist &L)
{
if (L.arr)delete[] L.arr;
L.arr = nullptr;
L.size = 0;
}
//增
void InsertElem(Sqlist &L,int i,INT e)
{
if (i<0 || i>L.size)return;//检查插入序号是否超过数组,数组值=m最后一位+1
if (L.size == MAXSIZE)return;//检查数组大小是否超过开辟的最大长度
for (int j = L.size - 1; j >= i; j--)//j从最后一位开始,到第i位完成为止
{
L.arr[j+1] = L.arr[j];//把前一位赋给后一位
}
L.arr[i] = e;//把新元素插入第i号位
L.size++;//数组加一
}
//删
void DeleteElem(Sqlist& L, int i)
{
if (i<0 || i>L.size - 1)return;
for (; i < L.size-1; i++)//i从第i位,到最后一位
{
L.arr[i] = L.arr[i+1];//把后一位赋给前一位
}
L.size--;//数组减一
}
//查
INT GetElem(Sqlist &L, int i)
{
if (i<0 || i>L.size-1)return ERROR;
return L.arr[i];
}
//改
void AlterElem(Sqlist& L, int i ,INT e)
{
if (i<0 || i>L.size - 1)return;
L.arr[i] = e;
}
//打印
void Print(Sqlist& L);
void main()
{
Sqlist L;//声明
InitList(L);//初始化
InsertElem(L, 0, 1); //增
cout << GetElem(L, 0);//查
AlterElem(L, 0, 2); //改
DeleteElem(L, 0); //删
DestList(L);//析构
}
void Print(Sqlist& L)
{
for (int i = 0; i < L.size; i++)
{
cout << L.arr[i] << " ";
}cout << endl;
}
链表
#include<iostream>
using namespace std;
#define ERROR -1
typedef int INT;
//结点的定义
typedef struct Node
{
INT data = 0;//数据域
Node* next;//指针域
Node() :next(nullptr) {};//构造函数
Node(INT v) :data(v), next(nullptr) {};//有参构造
}Lnode, *LinkList;
/*对象别名 指针别名 用法Lnode L通常指向结点, LinkList L通常指向链表*/
//链表的定义
typedef struct List
{
List();
~List();
//增
void addAtHead(INT data);//头插
void addAtTail(INT data);//尾插
void addAtIndex(int index, INT data);//任意插
//删
void deleteAtIndex(int index);
//查
INT get(int index);
private:
Node* head;//头结点
int size;
};
//链表的初始化
List::List()
{
head = new Node;
size = 0;
}
//链表的销毁
List::~List()
{
Node* cur;
while(head)
{
cur = head;
head = head->next;
delete cur;
}
}
//头插
void List::addAtHead(INT data) {
Node* newNode = new Node(data);
{
newNode->next = head->next;
head->next = newNode; }
size++;
}
//尾插
void List::addAtTail(INT data) {
Node* cur = head;
while (cur->next)//while(size--)
{
cur = cur->next;
}
Node* newNode = new Node(data);
cur->next = newNode;
newNode->next = nullptr;
size++;
}
//任意位置插
void List::addAtIndex(int index, INT data) {
if (index<0 || index>size)return;
else if (index == 0)addAtHead(data);
else if (index == size)addAtTail(data);
else
{
Node* cur = head;
while (index--)//如果你要指到第0号元素,你就不需要移动,index=0
{
cur = cur->next;
}
Node* newNode = new Node(data);
newNode->next = cur->next;
cur->next = newNode;
size++;
}
}
//任意位置删除
void List::deleteAtIndex(int index) {
if (index < 0 || index >= size) return;
Node* cur = head;//从头指针开始
while (index--) {//遍历到index-1的位置,循环次数是index次
cur = cur->next;
}
cur->next = cur->next->next;//相当于直接跨过了index节点
size--;
}
//查找
INT List::get(int index) {
if (index < 0 || index >= size)
{
return ERROR;
}
Node* cur = head;
while (index--)
{
cur = cur->next;
}
return cur->next->data;//改的话,就把这里换成cur->next->data = 传入的元素;
}
int main()
{
return 0;
}
顺序栈
索引值:(第一个元素索引值为0)
栈空:top== - 1
栈满:top==Maxsize-1指针:有top、base指针(为了方便通常top指向栈顶元素的上方,base指向栈底元素)
栈空:top==base
栈满:top-base=Maxsize(top会指针栈外面)
(指针是可以±的)
如果两个指针向同一个数组,它们就可以相减,其为结果为两个指针之间的元素数目上溢(overflow):满栈还push
下溢(underflow):空栈还pop
顺序栈代码
top指向栈顶元素
#include<iostream>
using namespace std;
#define MAXSIZE 10
#define ERROR -1
typedef int INT;
struct SqStack
{
INT* arr;//栈顶指针
int top;//栈顶指针
int size;
SqStack();
~SqStack();
void Push(INT e);
INT Pop();
INT GetTop();
void ClearStack();
bool IsStackEmpty();
};
SqStack::SqStack()
{
arr= new INT[MAXSIZE];//开辟一个数组
if (arr)
{
top = -1;//栈空
size = 0;
}
}
SqStack::~SqStack()
{
if (arr)
{
delete[] arr;
arr = nullptr;
top = -1;
size = 0;
}
}
void SqStack::Push(INT e)
{
if (top == MAXSIZE - 1)return;
arr[++top] = e;
size++;
}
INT SqStack::Pop()
{
if (top == -1)return INT_MIN;
size--;
return arr[top--];
}
INT SqStack::GetTop()
{
if(IsStackEmpty()) return ERROR;
else return arr[top];
}
void SqStack::ClearStack()
{
if (arr)
{
top = -1;
size = 0;
}
}
bool SqStack::IsStackEmpty()
{
if (top == -1)return true;
else return false;
}
top指向栈顶元素的上方
#include<iostream>
using namespace std;
#define MAXSIZE 10
#define ERROR -1
typedef int INT;
struct SqStack
{
INT* base;//栈顶指针
INT* top;//栈顶指针
int size;
SqStack();
~SqStack();
void Push(INT e);
INT Pop();
INT GetTop();
void ClearStack();
bool IsStackEmpty();
};
SqStack::SqStack()
{
base = new INT[MAXSIZE];//开辟一个数组
if (base)
{
top = base;//栈空
size = 0;
}
}
SqStack::~SqStack()
{
if (base)
{
delete[] base;
top = base = null