数据结构篇:实现顺序表和单链表

本文分享了一次初创公司面试的经历,并根据反馈调整了学习方向,重点介绍了使用C++实现顺序表和链表的过程。

前言

许久没写博客了,7月初去广州一家公司面试了实习生的岗位,是一家小型的创业公司,目前主要做外包业务。作为人生中第一次面试,感觉还是挺宝贵的。刚到广州的时候下着雨,一个人为了一件事走在一个陌生的城市,是一种熟悉又陌生的感觉。广州这座城市给我的感觉:安静,一切都井然有序,繁华,但你关注的绝对不是他的繁华,然后就是四通八达的地铁,我几天的出行全都是地铁,深切的感受到广州交通的发达。
第二天上午到的公司面试,不知道为什么我没有太紧张,由于是初创公司,面试官就是ceo,直接三轮面完我,andorid和java准备了蛮多的不过他都没有问,而是针对一个问题深挖,叫我给出解决方案,我感觉目的是在考我思维的全面性和解决问题的能力,然后就是谈我做过的项目。后来聊了薪资,在聊了我平时的学习方式等等,最后让我等通知。因为在拉勾上投的,他们招的是正式工,我只能作为实习生的身份可能提的薪资比较高了,我觉得初创企业很少愿意花成本去培养一个学生吧,感觉那个薪资我要是老板也宁愿找一个有工作经验的。
回来以后我觉的,是应该改变一下了,我觉得自己数据结构算法等基础不太扎实,又觉得android那块想继续深入学,在掘金上问了大牛,大牛给我的建议,我觉得确实也是很中肯,android什么的可以以后在继续深入学习,但是数据结构算法等这种,是最基础最核心的东西,短时间可能感觉不到,但是对我们影响还是蛮深远的。
所以这几天在练车的间隙,就在抽时间学习数据结构和算法,实现了基本的顺序表和链表(c++)。我觉得写博客真的蛮好的,比起那些杂乱的代码,将来生疏了的内容在自己博客里查找一些就好了。

顺序表

其实数据结构这种东西,语言什么的影响不大,一通百通,之前有用java实现过,这次用c++自己先保证不参考书的情况下,也能实现,顺便回顾下c++。

顺序表在java和c++中有点不一样,其实也没有不一样吧,只是书上实现方式是直接一个固定大小数组,java源码中是初始一个固定大小数组,当增加到一定程度会换数组,比如每增加5个换一个新数组存储,这些都大同小异,主要是实现数据结构的构造,释放,曾删查改等基本操作。好了,话不多说,上代码

先是头文件:

//
// Created by panhao on 17-7-12.
//

#ifndef DATABASE_SEQLIST_H
#define DATABASE_SEQLIST_H


#include <iostream>

const int MaxSize = 100;

template<class Data>
class SeqList {
public:
    SeqList() {}

    SeqList(Data a[], int n);

    ~SeqList() {}

    int Length() { return this->length; }

    Data get(int index);//根据下标查找元素

    int Locate(Data data);//按照值来查找

    void add(Data data);

    void insert(int index, Data data);

    Data remove(int index);//根据下标删除元素

    void printList();


private:
    Data datas[MaxSize];

    int length;

};


#endif //DATABASE_SEQLIST_H

这边是声明数组最大为100,然后声明了一个模板类,我更喜欢称为泛型~,然后就是一系列曾删查改等方法。private域存储了作为全局变量的数组和数组的大小。
接下来看具体实现:

//
// Created by panhao on 17-7-12.
//

#include <iostream>
#include "SeqList.h"

using namespace std;


/**
 * 有参的构造函数
 * @tparam Data
 * @param a
 * @param n
 */
template<class Data>
SeqList<Data>::SeqList(Data a[], int n) {
    if (n > MaxSize)
        throw "参数非法";
    for (int i = 0; i < n; i++) {
        datas[i] = a[i];
    }
    length = n;
}

/**
 * 顺序表的按位查找
 * @tparam Data
 * @param index
 * @return
 */
template<class Data>
Data SeqList<Data>::get(int index) {
    if (index > length - 1) {
        throw "位置非法";
    }
    return datas[index];
}


template<class Data>
int SeqList<Data>::Locate(Data data) {
    for (int i = 0; i < length; i++) {
        if (datas[i] == data) {
            return i;
        }
    }
    return -1;
}

template<class Data>
void SeqList<Data>::add(Data data) {
    if (length > MaxSize) {
        throw "链表超长度";
    }
    datas[length] = data;
    length++;
}

template<class Data>
void SeqList<Data>::insert(int index, Data data) {
    if (index > MaxSize) {
        throw "溢出";
    }
    if (index > length - 1 || index < 0) {
        throw "位置非法";
    }
    for (int i = length; i > index; i--) {
        datas[i] = datas[i - 1];
    }
    datas[index] = data;
    length++;
}

template<class Data>
Data SeqList<Data>::remove(int index) {
    if (index > MaxSize) {
        throw "上溢";
    }
    if (index < 0 || index > length - 1) {
        throw "位置非法";
    }
    //先获得index位置上的值
    Data mData = datas[index];

    for (int i = index; i < length - 1; i++) {
        datas[i] = datas[i + 1];
    }
    length--;
    return mData;
}


template<class Data>
void SeqList<Data>::printList() {
    for (int i = 0; i < length; i++) {
        cout << datas[i] << endl;
    }
}


int main() {
    int arr[] = {20, 19, 30, 3, 4, 6, 3, 68};

    SeqList<int> seqList = SeqList<int>(arr, 8);
    seqList.insert(2, 100);
    seqList.remove(2);
    int position = seqList.Locate(68);

    cout << "position==" << position << endl;

    seqList.printList();
    int len = seqList.Length();

    cout << "len==" << len << endl;
    return 0;
}

单独测试的方法我就不一一打印截图,这样太麻烦了,我都有测试过应该是没什么问题的。基本大家的数据结构课程也都会要求写这样的代码。

链表

链表在java和c++中最大的不同就是引用和指针的不同了,不过其实java内部的引用也是通过指针引用,只是被封装了而已。
头文件:

//
// Created by panhao on 17-7-13.
//

#ifndef DATABASE_LINKLIST_H
#define DATABASE_LINKLIST_H

#include <iostream>

using namespace std;
template<class Data>
struct Node {
    Data data;
    Node<Data> *next;
};

template<class Data>
class LinkList {
public:
    LinkList();

    LinkList(Data arr[], int n);

    LinkList(Node<Data> *first);

    ~LinkList();

    int length();

    Data get(int index);

    void insert(Data data, int index);

    Data remove(int index);

    void printList();

private:
    Node<Data> *first;//头指针
};


#endif //DATABASE_LINKLIST_H

头文件声明了一个Node的结构体,里面存储了对应的数据类型和下一个节点的指针,指向下一个节点的内存地址。
链表的存储了一个头指针,通过头指针来确认不同节点的位置从而作出不同的操作。

//
// Created by panhao on 17-7-13.
//

#include "LinkList.h"
#include <iostream>

using namespace std;


template<class Data>
LinkList<Data>::LinkList() {
    first = new Node<Data>;
    first->next = NULL;
}

template<class Data>
LinkList<Data>::LinkList(Data arr[], int n) {

    //尾插法,首先确保first是不可变的
    first = new Node<Data>;
    Node<Data> *tmp = first;//头指针引用

    for (int i = 0; i < n; i++) {
        //创建一个新的节点并分配内存
        Node<Data> *node = new Node<Data>();
        node->data = arr[i];
        tmp->next = node;
        tmp = node;

    }
    //单链表建立完毕
    tmp->next = NULL;
}

/**
 * 析构函数~
 * @tparam Data
 */
template<class Data>
LinkList<Data>::~LinkList() {
    while (first != NULL) {
        Node<Data> *q = first;
        first = first->next;//first指向被释放的下一个节点
        delete q;
    }
    cout << "链表被finish掉了" << endl;
}

template<class Data>
int LinkList<Data>::length() {
    int count = 0;
    Node<Data> *p = first;
    while (p->next != NULL) {
        count++;
        p = p->next;
    }
    return count;
}

template<class Data>
Data LinkList<Data>::get(int index) {
    //通过指定的下标获取数据。
    if (index > length() || index < 0) {
        throw '溢出';
    }
    Node<Data> *p = first;
    int count = 0;

    while (count <= index) {
        p = p->next;
        count++;
    }
    if (p == NULL) {
        throw '位置';
    }
    return p->data;
}

template<class Data>
void LinkList<Data>::insert(Data data, int index) {
    if (index < 0 || index > length()) {
        throw '溢出';
    }

    Node<Data> *p = first;
    int count = 0;
    while (p != NULL && count < index) {
        p = p->next;
        count++;
    }
    if (p == NULL) {
        throw '位置';
    }
    Node<Data> *node = new Node<Data>();
    node->data = data;
    node->next = p->next;
    p->next = node;
}

template<class Data>
Data LinkList<Data>::remove(int index) {
    if (index < 0 || index > length()) {
        throw '溢出';
    }
    Node<Data> *p = first;
    int count = 0;

    while (p != NULL && count < index) {
        p = p->next;
        count++;
    }
    if (p == NULL) {
        throw '位置';
    }
    Node<Data> *q = p->next;
    Data data = q->data;
    p->next = q->next;
    delete q;
    return data;
}

template<class Data>
void LinkList<Data>::printList() {
    Node<Data> *p = first->next;
    while (p != NULL) {
        cout << p->data << " ";
        p = p->next;
    }
}

int main() {
    int arr[] = {20, 19, 30, 3, 4, 6, 3, 68};
    LinkList<int> list(arr, 8);

    list.printList();
    list.insert(100, 3);

    cout << endl;
    list.printList();

    list.remove(8);
    cout << endl;
    list.printList();

    return 0;
}

这边给个截图吧,因为是新鲜的。
这里写图片描述

结语

时间有限,明早还要练车,今天就先到这里了,后续会继续学习数据结构算法这些内容,也会顺便学习android更新android的知识。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值