线性结构-链表、栈、队列应用场景

一、单链表数据结构定义

  1. python版
class ListNode:
    def __init__(self, val, next_node = None):
        self.val = val
        self.next = next_node

  2.C++版

struct ListNode {
    int value;
    ListNode *next;
    ListNode(int item, next = nullptr) {
        value = item;
        next = next;
    }
};

  3.go版 

type ListNode struct {
	val  int
	next *ListNode
}

  4.js版

class ListNode{
    constructor(data) {
       this.value = data;
       this.next = null;
    }
}

 

二、链表的优缺点及应用场景事例

链表优点:适用于对节点的增删改操作,时间复杂度O(1);

链表缺点:相对于顺序表,除保存数据外,还额外增加存放下个节点地址的内存开销;

同时单链表相对于双链表,查询某个节点从头遍历,双链表双向查找可进可退,缺点是需增加节点的前驱地址的内存开销;

为提高查询效率,同时保留增删改的执行效率,因此,引入跳表数据结构

跳表数据结构定义:

// 跳跃表节点定义
struct skipListNode
{
    struct skipListLevel 
    {
        // 前进指针
        skipListNode *forward;
        // 跨度
        unsigned int span;
    } level[];
    // 后退指针
    struct skipListNode *backward
    // 分值
    double score;
    // 成员对象
    robj *obj;
} skipListNode;
// 跳跃表定义
struct skipList 
{
    // 表头节点和表尾节点
    struct skipListNode *header, *tail;
    // 表中节点数量
    unsigned long length;
    // 表中节点层数
    int level;
};

跳表是一种有序的数据结构,通过在每个节点中维护多个指向其他节点的指针,从而达到快速访问节点的目的,跳表平均复杂度O(logN),最坏复杂的度O(N),多数情况下跳表的效率可以与平衡树相媲美,并且跳表比平衡树结构更为简单,应用场景中redis的有序集合底层实现就使用跳表结构;

链表实现LRU缓存淘汰策略事例:

struct ListNode {
    int value;
    ListNode *next;
    ListNode(int item, next = nullptr) {
        value = item;
        next = next;
    }
};

ListNode* lruStrategy(ListNode* L, int val, int n) {
    ListNode* head = new ListNode(0, L);
    ListNode* p = head->next;
    int index = count = 0;
    bool isExist = false;
    while (p)
    {
        count++;
        if (p->value == val) {
            index = count;
            isExist = true;
        }
        p = p->next;
    }
    if (isExist) {
        delListNode(head, index);
        addListNode(head, val);
    }
    if (count == n) {
        delListNode(head, n);
    }
    addListNode(head, val);
}

ListNode* addListNode(ListNode* head, int val) {
    ListNode* p;
    p->value = val;
    p->next = head->next;
    head->next = p;
    return head->next;
}

ListNode* delListNode(ListNode* p, int index) {
    ListNode* p = head;
    for (int i = 0; i < index; i++) {
        p = p->next;
    }
    p->next = p->next->next;
    return head->next;
}

栈的特点是先进后出,常见应用场景有括号匹配,数制转换,函数调用,表达式求值,二叉树遍历等

栈的链式数据结构定义:

struct LinkStack
{
    int value;
    LinkStack* next;
} *stack;

以有效括号匹配为例:

#include <iostream>
#include <stack>

using namespace std;

class Solution {
    public:
    /**
     * 判定左右括号是否匹配
     * @param left
     * @param right
     * @return
     */
    bool check(char left , char right){
        if(left == '('){
            return right == ')' ? true : false;
        }

        if(left == '['){
            return right == ']' ? true : false;
        }

        if(left == '{'){
            return right == '}' ? true : false;
        }
        return false;
    }

    /**
     * 核心方法
     * @param s
     * @return
     */
    bool isValid(string s) {
        stack<char> stk;
        for (int i = 0 ; i < s.size() ; i++) {
            //左括号,入栈
            if (s[i] == '(' || s[i] == '{' || s[i] == '[') {
                stk.push(s[i]);
            } 
            if (s[i] != ')' && s[i] != ']' && s[i] != '}') {
                continue;
            } 
            if (!check(stk.top(), s[i])) {
                return false;
            }
            stk.pop();
        }
        //循环完毕后,若栈不空,说明左括号个数大于右括号,不匹配
        return stk.empty();
    }
};

int main() {
    string s = "{dadfsa[fjsfjks]s23u(4sjhd)fks}";
    Solution *p = new Solution();
    if (p->isValid(s)) {
        cout << "match success" << endl;
        return 0;
    } 
    cout << "match fail!!" << endl;
}

队列的特点先进先出,应用场景如排队买票,广度优先遍历等

队列数据结构的定义:

struct QNode
{
    int data;
    QNode* next;
};

struct LinkQueue
{
    QNode* front;   //队头指针
    QNode* rear;    //队尾指针
};

 

posted @ 2022-06-11 23:52  Rafa2008bj  阅读(535)  评论(0编辑  收藏  举报