算法基础-线性结构

前往我的主页以获得更好的阅读体验算法基础-线性结构 - DearXuan的主页icon-default.png?t=M276https://blog.dearxuan.com/2022/02/15/%E7%AE%97%E6%B3%95%E5%9F%BA%E7%A1%80-%E7%BA%BF%E6%80%A7%E7%BB%93%E6%9E%84/

数组

内存结构

数组是一种顺序存储的结构,他所占用的空间是固定的,不能随意增加或减小,其中所有元素以特定的方式按顺序排列下来,各个元素的位置都是固定的。因此数组是一种有序的线性结构

数组的随机访问性能优秀,因为只需要对首地址进行加减运算就能得到任意位置处的值

int a[100];
for(int i=0;i<100;i++){
    a[i] = i + 1;
}
cout << a[50] << endl;

除此之外,我们也可以使用地址直接获取元素的值

int a[100];
for(int i=0;i<100;i++){
    a[i] = i;
}
cout << *(a + 50) << endl;

插入与删除

当从一个数组中删除第10个元素时,原本的第11个元素成了新的第10个元素,因此需要对10之后的元素进行移动操作

而在插入元素时,同样需要对数组里的元素进行移动操作

int a[100];
void remove(int p){
    for(int i=p+1;i<100;i++){
        a[i-1] = a[i];
    }
}
void add(int p, int num){
    for(int i=98;i>=p;i--){
        a[i+1] = a[i];
    }
    a[p] = num;
}

因此数组并不适合需要大量增删的场景,更适合于元素位置不会轻易改变的场景

堆栈

堆栈是一种先进后出的线性结构,他只能从数组的尾部进行增删。例如一个长度为100的数组,其中有10个元素,那么新的元素必须添加到11的位置上

堆栈类似于一个集装箱,每次都必须先把门口的货物搬走,才能搬里面的货物

在STL中已经有了堆栈容器,这里为了演示实现原理,采用结构体编写代码

#define Length 100
#define Error -1

struct Stack{
    int list[Length];//储存元素的数组
    int count;//当前堆栈的元素个数
};

//入栈
bool push(Stack * stack, int num){
    //判断堆栈是否未满
    if(stack->count < Length){
        //插入元素
        stack->list[stack->count] = num;
        //元素个数加一
        ++(stack->count);
        return true;
    }else{
        //堆栈已满,返回false
        return false;
    }
}

//出栈
int pop(Stack * stack){
    //判断堆栈是否不为空
    if(stack->count != 0){
        --(stack->count);
        return stack->list[stack->count];
    }else{
        return Error;
    }
}

int main() {
    Stack * stack = (Stack*) malloc(sizeof(Stack));
    stack->count = 0;
    push(stack,1);
    push(stack,3);
    push(stack,5);
    cout << pop(stack) << endl;
    cout << pop(stack) << endl;
    cout << pop(stack) << endl;
    //输出为:5 3 1
    return 0;
}

队列

队列与堆栈相似,是一种先进先出的线性结构,最先进入队列的元素也会最先输出,就像是在排队一样,因此称为队列

一般队列

普通的队列实际上就是一个数组,如果想要输出首位元素,则需要把整个数组整体往前移动,效率极低

循环队列

如果能够把队列围城一个圈,这样我们只需要知道首位地址和末位地址,就可以在不移动整个数组的情况下更新队列

构造出圈结构较难,我们可以使用数组来实现,因此当指针移动到数组的最后一项时,它的下一位应该设置为数组的首位。循环队列通过两个指针分别指向首元素和末元素,插入元素时,只需要把末元素指针后移一位,而输出元素时,只需要把首元素指针后移一位。当队列长度较大时,这种方法大大降低了执行所需要的时间

#define Length 5
#define Error -1

struct Queue{
    int list[Length];//储存队列的数组
    int front;//队首元素位置
    int rear;//队尾元素位置
    int count;//元素个数
};

//插入队列
bool push(Queue * queue, int num){
    if(queue->count == Length){
        //队列已满
        return false;
    }else{
        //队尾后移一位
        queue->rear = (queue->rear + 1) % Length;
        queue->list[queue->rear] = num;
        ++(queue->count);
        return true;
    }
}

//弹出队列
int pop(Queue * queue){
    if(queue->count == 0){
        //队列为空
        return Error;
    }else{
        int result = queue->list[queue->front];
        //队首后移一位
        queue->front = (queue->front + 1) % Length;
        --(queue->count);
        return result;
    }
}

int main() {
    Queue * queue = (Queue*) malloc(sizeof(Queue));
    //初始化
    queue->count = 0;//元素个数初始为0
    queue->front = 0;//首元素为数组的第0项
    queue->rear = Length - 1;//末元素为最后一项,而不是第0项,因为当前没有元素
    for(int i=0;i<10;i++){
        push(queue, i);
    }
    for(int i=0;i<10;i++){
        cout << pop(queue) << " ";
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Dear_Xuan

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值