{ E item; Node next; Node ( E x ) { item = x; }} Node 是 LinkedBlockingQueue 的基石。 它如第一張圖所示的一個(gè)單向鏈表形式的內(nèi)部類,item 是當(dāng)前節(jié)點(diǎn)的內(nèi)容,next 指向的是下一個(gè) Node 節(jié)點(diǎn)。 屬性 //容量 private final" />

99精品伊人亚洲|最近国产中文炮友|九草在线视频支援|AV网站大全最新|美女黄片免费观看|国产精品资源视频|精彩无码视频一区|91大神在线后入|伊人终合在线播放|久草综合久久中文

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

LinkedBlockingQueue基于單向鏈表的實(shí)現(xiàn)

科技綠洲 ? 來(lái)源:Java技術(shù)指北 ? 作者:Java技術(shù)指北 ? 2023-10-13 11:41 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

在前面的文章中,已經(jīng)對(duì) ArrayBlockingQueue 進(jìn)行了一次源碼分析,對(duì)它的核心源碼做了分析,今天來(lái)解析一波同為 BlockingQueue 家族中的一員的 LinkedBlockingQueue。它的底層基于單向鏈表實(shí)現(xiàn)。

圖片

先看一看它的 Node 內(nèi)部類和主要屬性、構(gòu)造函數(shù)。

Node

static class Node< E > {
    E item;
    Node< E > next;

    Node(E x) { item = x; }
}

Node 是 LinkedBlockingQueue 的基石。 它如第一張圖所示的一個(gè)單向鏈表形式的內(nèi)部類,item 是當(dāng)前節(jié)點(diǎn)的內(nèi)容,next 指向的是下一個(gè) Node 節(jié)點(diǎn)。

屬性

//容量
private final int capacity;

//隊(duì)列中元素的數(shù)量
private final AtomicInteger count = new AtomicInteger();

//鏈表的頭節(jié)點(diǎn)
transient Node< E > head;

//鏈表的尾節(jié)點(diǎn)
private transient Node< E > last;

//出隊(duì)鎖
private final ReentrantLock takeLock = new ReentrantLock();

//當(dāng)隊(duì)列沒(méi)有元素了,出隊(duì)鎖的線程會(huì)加入 notEmpty 條件隊(duì)列中被阻塞,等待其它線程喚醒
private final Condition notEmpty = takeLock.newCondition();

//入隊(duì)鎖
private final ReentrantLock putLock = new ReentrantLock();

//當(dāng)隊(duì)列滿了,入隊(duì)鎖的線程會(huì)加入 notFull 條件隊(duì)列中被阻塞,等待其它線程喚醒
private final Condition notFull = putLock.newCondition();
  1. 從屬性中就可以看出 LinkedBlockingQueue 和 ArrayBlockingQueue 的差異點(diǎn): ArrayBlockingQueue 只有一把 ReentrantLock 鎖,入隊(duì)和出隊(duì)相互互斥。 LinkedBlockingQueue 分了出隊(duì)鎖 takeLock 和入隊(duì)鎖 putLock,兩把鎖相互不阻塞。
  2. capacity 是 LinkedBlockingQueue 的容量,表示 LinkedBlockingQueue 是一個(gè)有界隊(duì)列。

構(gòu)造函數(shù)

LinkedBlockingQueue 提供了三個(gè)構(gòu)造函數(shù)。

圖片

LinkedBlockingQueue()

public LinkedBlockingQueue() {
    this(Integer.MAX_VALUE);
}

LinkedBlockingQueue() 構(gòu)造函數(shù)直接調(diào)用帶參數(shù)的構(gòu)造函數(shù),參數(shù)被設(shè)置為 2 的 31 次方 - 1

LinkedBlockingQueue(int capacity)

public LinkedBlockingQueue(int capacity) {
    //檢查容量大小
    if (capacity <= 0) throw new IllegalArgumentException();
    this.capacity = capacity;
    //構(gòu)造一個(gè) null 節(jié)點(diǎn)
    last = head = new Node< E >(null);
}

LinkedBlockingQueue(int capacity) 構(gòu)造函數(shù)做了三件事:

  1. 先檢查參數(shù)是否大于 0,不大于 0 就拋出異常。
  2. 設(shè)置 capacity 容量為參數(shù)大小。
  3. 構(gòu)造了一個(gè) null 節(jié)點(diǎn),賦值給 last 和 head。
  4. head 的 item 元素永遠(yuǎn)是一個(gè) null。

LinkedBlockingQueue(Collection c)

public LinkedBlockingQueue(Collection< ? extends E > c) {
    //容量是最大值
    this(Integer.MAX_VALUE);
    final ReentrantLock putLock = this.putLock;
    //加鎖
    putLock.lock();
    try {
        int n = 0;
        for (E e : c) {
            if (e == null)
                throw new NullPointerException();
            if (n == capacity)
                throw new IllegalStateException("Queue full");
            
            //真實(shí)的入隊(duì)操作
            enqueue(new Node< E >(e));
            ++n;
        }
        //設(shè)置元素的數(shù)量
        count.set(n);
    } finally {
        //解鎖
        putLock.unlock();
    }
}
  1. LinkedBlockingQueue(Collection c) 調(diào)用了 LinkedBlockingQueue(int capacity) 構(gòu)造函數(shù)并將參數(shù)設(shè)置成了最大值。
  2. putLock 加鎖后,將集合中的元素一個(gè)個(gè)遍歷并且入隊(duì)。
  3. 設(shè)置元素的數(shù)量就是集合中元素的數(shù)量。
  4. 在遍歷元素時(shí),會(huì)將 null 元素拋出異常并且檢查隊(duì)列是否滿了。

入隊(duì)

LinkedBlockingQueue 有多種入隊(duì)方法,當(dāng)隊(duì)列滿了之后它們的處理方法各不相同。在入隊(duì)之前和入隊(duì)之后的操作都是相同的。

offer

//LinkedBlockingQueue.offer()
public boolean offer(E e) {
    //檢查是否為 null
    if (e == null) throw new NullPointerException();
    //檢查隊(duì)列是否滿了,隊(duì)列滿了返回 fasle
    final AtomicInteger count = this.count;
    if (count.get() == capacity)
        return false;
    //初始化一個(gè) size
    int c = -1;
    //創(chuàng)建一個(gè) Node 節(jié)點(diǎn)
    Node< E > node = new Node< E >(e);
    //putLock 加鎖
    final ReentrantLock putLock = this.putLock;
    putLock.lock();
    try {
        //如果沒(méi)有滿隊(duì),則入隊(duì)
        if (count.get() < capacity) {
            //入隊(duì)
            enqueue(node);
            //返回元素的數(shù)量并且元素的數(shù)量 + 1
            c = count.getAndIncrement();
            //元素的數(shù)量 + 1 還沒(méi)有滿隊(duì),還有剩余的容量空間,喚醒 notFull 隊(duì)列中因?yàn)殛?duì)列滿了而等待入隊(duì)的線程。
            if (c + 1 < capacity)
                notFull.signal();
        }
    } finally {
        //解鎖
        putLock.unlock();
    }
    //當(dāng) c == 0 表示元素入隊(duì)之前是一個(gè)空的隊(duì)列
    //現(xiàn)在隊(duì)列不是空的了,喚醒阻塞在 notEmpty 條件隊(duì)列中因?yàn)榭贞?duì)列而等待元素出隊(duì)的線程
    if (c == 0)
        signalNotEmpty();
    return c >= 0;
}

//LinkedBlockingQueue.enqueue()
private void enqueue(Node< E > node) {
    //直接加到 last 的 next 屬性中,并替換 last 屬性
    last = last.next = node;
}

//LinkedBlockingQueue.signalNotEmpty()
private void signalNotEmpty() {
    final ReentrantLock takeLock = this.takeLock;
    takeLock.lock();
    try {
        notEmpty.signal();
    } finally {
        takeLock.unlock();
    }
}

offer() 方法做了以下幾件事情:

  1. 檢查需要入隊(duì)的元素是否為 null。
  2. 判斷隊(duì)列是否滿了,滿了就返回 false。
  3. 隊(duì)列沒(méi)有滿,創(chuàng)建一個(gè)新的 Node 節(jié)點(diǎn)。
  4. putLock 鎖加鎖,不讓其他線程操作隊(duì)列。
  5. 當(dāng)隊(duì)列沒(méi)有滿隊(duì)的時(shí)候,將元素入隊(duì)并且將局部變量 c 設(shè)置為入隊(duì)之前元素的數(shù)量,元素?cái)?shù)量 + 1。
  6. 再次判斷隊(duì)列是否滿了,如果隊(duì)列中還有空位,則喚醒正在阻塞的入隊(duì)線程。這些阻塞的線程來(lái)自 put()、offer(E e, long timeout, TimeUnit unit) 方法。
  7. 釋放 putLock 鎖
  8. 當(dāng)入隊(duì)之前是一個(gè)空隊(duì)列的時(shí)候,調(diào)用 signalNotEmpty() 方法開啟 takeLock 出隊(duì)鎖,將阻塞在 notEmpty 條件隊(duì)列中的線程喚醒。

enqueue() 方法的源碼比較簡(jiǎn)單,就是將 last 節(jié)點(diǎn)的 next 指向需要入隊(duì)的元素,如下圖所示。

圖片

add()

//LinkedBlockingQueue.add()
public boolean add(E e) {
    //調(diào)用 offer()
    if (offer(e))
        return true;
    else
        //隊(duì)列滿了,就拋出異常
        throw new IllegalStateException("Queue full");
}

add() 方法調(diào)用的是 offer() 方法,它在隊(duì)列滿了的時(shí)候不是返回 false 而是拋出一個(gè) Queue full 異常。

put()

//LinkedBlockingQueue.put()
public void put(E e) throws InterruptedException {
    //檢查是否為 null
    if (e == null) throw new NullPointerException();
    int c = -1;
    Node< E > node = new Node< E >(e);
    final ReentrantLock putLock = this.putLock;
    final AtomicInteger count = this.count;
    //putLock 加鎖
    putLock.lockInterruptibly();
    try {
        //如果隊(duì)列滿了,就把線程加入 notFull 隊(duì)列,阻塞線程
        while (count.get() == capacity) {
            notFull.await();
        }
        //入隊(duì)
        enqueue(node);
        //返回元素的數(shù)量并且元素的數(shù)量 + 1
        c = count.getAndIncrement();
        //元素的數(shù)量 + 1 還沒(méi)有滿隊(duì),還有剩余的容量空間,喚醒 notFull 隊(duì)列中因?yàn)殛?duì)列滿了而等待入隊(duì)的線程
        if (c + 1 < capacity)
            notFull.signal();
    } finally {
        //解鎖
        putLock.unlock();
    }
    if (c == 0)
        signalNotEmpty();
}

put() 方法和 offer()、and() 的方法大致相同,不同的是對(duì)隊(duì)列滿了之后的操作,offer() 是直接返回 false,and() 是拋出異常,put() 則是將線程加入到 notFull 條件隊(duì)列中阻塞入隊(duì)線程。

offer(E e, long timeout, TimeUnit unit)

這是一個(gè)帶超時(shí)時(shí)間的 offer() 方法。

public boolean offer(E e, long timeout, TimeUnit unit)
    throws InterruptedException {
    //檢查是否為 null
    if (e == null) throw new NullPointerException();
    //將 timeout 超時(shí)轉(zhuǎn)換為毫秒數(shù)
    long nanos = unit.toNanos(timeout);
    int c = -1;
    final ReentrantLock putLock = this.putLock;
    final AtomicInteger count = this.count;
    //加鎖
    putLock.lockInterruptibly();
    try {
        //當(dāng)隊(duì)列滿了之后,等待超時(shí)時(shí)間,如果超時(shí)時(shí)間到了,還沒(méi)入隊(duì)則返回 false
        while (count.get() == capacity) {
            if (nanos <= 0)
                return false;
            nanos = notFull.awaitNanos(nanos);
        }
        //入隊(duì)
        enqueue(new Node< E >(e));
        //返回元素的數(shù)量并且元素的數(shù)量 + 1
        c = count.getAndIncrement();
        //元素的數(shù)量 + 1 還沒(méi)有滿隊(duì),還有剩余的容量空間,喚醒 notFull 隊(duì)列中因?yàn)殛?duì)列滿了而等待入隊(duì)的線程
        if (c + 1 < capacity)
            notFull.signal();
    } finally {
        //解鎖
        putLock.unlock();
    }
    if (c == 0)
        signalNotEmpty();
    return true;
}

這個(gè)方法是在一定時(shí)間內(nèi)元素等待入隊(duì),就是在 timeout 時(shí)間內(nèi)隊(duì)列中有空余位置就將元素加入單向鏈表的隊(duì)尾,如果在 timeout 時(shí)間內(nèi)元素還沒(méi)有入隊(duì),就返回 false。

入隊(duì)總結(jié)

LinkedBlockingQueue 的入隊(duì)一共有 offer()、add()、put()、offer(E e, long timeout, TimeUnit unit) 四種方法。這四種方法在隊(duì)列滿了之后的處理是不同的:

  1. offer() 方法在隊(duì)列滿了之后就返回 false。
  2. add() 方法在內(nèi)部調(diào)用的是 offer() 方法,當(dāng)隊(duì)列滿了就拋出 Queue full 異常。
  3. put() 方法在隊(duì)列滿了之后會(huì)將線程加入 notFull 中,等待被喚醒后加入隊(duì)列。
  4. offer(E e, long timeout, TimeUnit unit) 方法在隊(duì)列滿了之后會(huì)等待一段 timeout 的時(shí)間,在這時(shí)間內(nèi)入隊(duì)就返回 true,在這段時(shí)間內(nèi)未能入隊(duì)就返回 false。
  5. 每個(gè)方法在入隊(duì)完后都會(huì)喚醒在 notEmpty 隊(duì)列中等待出隊(duì)的線程。

出隊(duì)

LinkedBlockingQueue 的出隊(duì)也有幾種不同的方法,它們對(duì)于空隊(duì)列的處理方式各不相同。

poll()

//LinkedBlockingQueue.poll()
public E poll() {
    //元素的數(shù)量
    final AtomicInteger count = this.count;
    //隊(duì)列中的非空檢查
    if (count.get() == 0)
        return null;
    //初始化一個(gè) null 對(duì)象
    E x = null;
    //初始化元素的個(gè)數(shù)
    int c = -1;
    //takeLock 出隊(duì)加鎖
    final ReentrantLock takeLock = this.takeLock;
    takeLock.lock();
    try {
        //當(dāng)隊(duì)列中有元素
        if (count.get() > 0) {
            //出隊(duì)
            x = dequeue();
            //取出出隊(duì)之前的元素?cái)?shù)量并且元素的數(shù)量 - 1
            c = count.getAndDecrement();
            //當(dāng)隊(duì)列中還有元素,喚醒 notEmpty 條件隊(duì)列中的線程
            if (c > 1)
                notEmpty.signal();
        }
    } finally {
        //解鎖
        takeLock.unlock();
    }
    //如果出隊(duì)之前隊(duì)列是滿的,就喚醒 putLock 鎖中的 notFull 條件隊(duì)列中等待的線程
    if (c == capacity)
        signalNotFull();
    return x;
}

//LinkedBlockingQueue.dequeue()
private E dequeue() {
    //head 節(jié)點(diǎn)沒(méi)有存儲(chǔ)元素,head.next 是第一個(gè)元素
    Node< E > h = head;
    //取出第一個(gè)元素
    Node< E > first = h.next;
    //將 head 節(jié)點(diǎn)的 next 指向自己
    h.next = h;
    //將第一個(gè)元素變成新的 head
    head = first;
    //取出內(nèi)容
    E x = first.item;
    first.item = null;
    return x;
}

poll() 方法在出隊(duì)的時(shí)候做了以下幾件事情:

  1. 先取出隊(duì)列中元素的數(shù)量
  2. 隊(duì)列的非空檢查,當(dāng)隊(duì)列是空的,則返回 false。
  3. 初始化一個(gè)局部的元素變量。
  4. takeLock 出隊(duì)鎖加鎖,不讓其他線程操作隊(duì)列的出隊(duì)。
  5. 當(dāng)隊(duì)列中有元素的時(shí)候,將隊(duì)列中的第一個(gè)元素彈出。
  6. 判斷隊(duì)列中是否還有元素,喚醒阻塞在 notEmpty 條件隊(duì)列上的線程。
  7. takeLock 出隊(duì)鎖解鎖
  8. 在原隊(duì)列是滿隊(duì)的情況下,喚醒阻塞在 notFull 條件隊(duì)列上的線程。

dequeue() 方法會(huì)將 LinkedBlockingQueue 中第一個(gè)元素取出。取的并不是 head 中的item,而是 head.next 中的 item。

圖片

poll(long timeout, TimeUnit unit)

//LinkedBlockingQueue.poll(long timeout, TimeUnit unit)
public E poll(long timeout, TimeUnit unit) throws InterruptedException {
    E x = null;
    int c = -1;
    //將超時(shí)時(shí)間轉(zhuǎn)換為毫秒數(shù)
    long nanos = unit.toNanos(timeout);
    final AtomicInteger count = this.count;
    final ReentrantLock takeLock = this.takeLock;
    //takeLock 出隊(duì)加鎖
    takeLock.lockInterruptibly();
    try {
        //隊(duì)列中是空的,沒(méi)有元素
        while (count.get() == 0) {
            //等待超時(shí)時(shí)間, 超時(shí)后返回 null
            if (nanos <= 0)
                return null;
            nanos = notEmpty.awaitNanos(nanos);
        }
        //出隊(duì)
        x = dequeue();
        //取出出隊(duì)之前的元素?cái)?shù)量并且元素的數(shù)量 - 1
        c = count.getAndDecrement();
        //當(dāng)隊(duì)列中還有元素,喚醒 notEmpty 條件隊(duì)列中的線程
        if (c > 1)
            notEmpty.signal();
    } finally {
        //解鎖
        takeLock.unlock();
    }
    if (c == capacity)
        signalNotFull();
    return x;
}

poll(long timeout, TimeUnit unit) 方法是在一定時(shí)間內(nèi)出隊(duì)還未取到元素就阻塞線程,時(shí)間到了還沒(méi)取到元素就返回 null,并不會(huì)一直阻塞線程。

take()

//LinkedBlockingQueue.take()
public E take() throws InterruptedException {
    E x;
    int c = -1;
    final AtomicInteger count = this.count;
    final ReentrantLock takeLock = this.takeLock;
    //加鎖
    takeLock.lockInterruptibly();
    try {
        //隊(duì)列是空的,將線程加入到 notEmpty 隊(duì)列中等待并且阻塞線程
        while (count.get() == 0) {
            notEmpty.await();
        }
        //出隊(duì)
        x = dequeue();
        //取出出隊(duì)之前的元素?cái)?shù)量并且元素的數(shù)量 - 1
        c = count.getAndDecrement();
        //當(dāng)隊(duì)列中還有元素,喚醒 notEmpty 條件隊(duì)列中的線程
        if (c > 1)
            notEmpty.signal();
    } finally {
        //解鎖
        takeLock.unlock();
    }
    //如果出隊(duì)之前隊(duì)列是滿的,就喚醒 putLock 鎖中的 notFull 條件隊(duì)列中等待的線程
    if (c == capacity)
        signalNotFull();
    return x;
}

take() 方法和 poll() 最大的不同就是在空隊(duì)列的時(shí)候會(huì)一直阻塞線程,poll() 則返回 null,poll(long timeout, TimeUnit unit) 則在一定時(shí)間內(nèi)阻塞線程,超時(shí)后返回的 null。

remove()

//LinkedBlockingQueue.remove()
public boolean remove(Object o) {
    //非空檢查
    if (o == null) return false;
    //將入隊(duì)鎖和出隊(duì)鎖都加鎖
    fullyLock();
    try {
        //遍歷所有元素
        for (Node< E > trail = head, p = trail.next;
                p != null;
                trail = p, p = p.next) {
            if (o.equals(p.item)) {
                //刪除節(jié)點(diǎn)
                unlink(p, trail);
                return true;
            }
        }
        return false;
    } finally {
        //將入隊(duì)鎖和出隊(duì)鎖都解鎖
        fullyUnlock();
    }
}

//LinkedBlockingQueue.unlink()
void unlink(Node< E > p, Node< E > trail) {
    //p 是需要?jiǎng)h除的節(jié)點(diǎn),trail 是 p 的上一個(gè)節(jié)點(diǎn)
    p.item = null;
    //將 trail.next 指向 p 的下一個(gè)節(jié)點(diǎn)
    trail.next = p.next;
    //要?jiǎng)h除的就是最后一個(gè)節(jié)點(diǎn)
    if (last == p)
        //將 trail 設(shè)置為最后一個(gè)節(jié)點(diǎn)
        last = trail;
    //原隊(duì)列是滿的隊(duì)列,喚醒 notFull 條件隊(duì)列中的線程
    if (count.getAndDecrement() == capacity)
        notFull.signal();
}

remove() 并不會(huì)彈出元素,它是刪除一個(gè)元素。遍歷整個(gè)單向鏈表,找到需要?jiǎng)h除的元素后,將元素前一個(gè)節(jié)點(diǎn)的next 指向刪除元素的 next。將需要?jiǎng)h除的元素設(shè)置為 null。

peek()

//LinkedBlockingQueue.peek()
public E peek() {
    //非空檢查
    if (count.get() == 0)
        return null;
    final ReentrantLock takeLock = this.takeLock;
    //加鎖
    takeLock.lock();
    try {
        //取出第一個(gè)元素,為 null 則返回 null
        Node< E > first = head.next;
        if (first == null)
            return null;
        else
            return first.item;
    } finally {
        //解鎖
        takeLock.unlock();
    }
}

peek() 方法僅僅是取出第一個(gè)元素,沒(méi)有修改節(jié)點(diǎn)的任何一個(gè) next 屬性,所以并不會(huì)將元素從隊(duì)列中移除。

出隊(duì)總結(jié)

LinkedBlockingQueue 的出隊(duì)一共有 poll()、take()、poll(long timeout, TimeUnit unit) 三種方法,移除元素用 remove() 方法,取出第一個(gè)元素用 peek() 方法。

出隊(duì)方法在遇到空隊(duì)列的時(shí)候操作不同:

  1. poll() 方法遇到空隊(duì)列就返回 null。
  2. take() 方法遇到空隊(duì)列就將線程加入到 notEmpty 條件隊(duì)列中并且阻塞線程。
  3. poll(long timeout, TimeUnit unit) 方法在遇到空隊(duì)列就阻塞一段時(shí)間,這期間沒(méi)獲取到元素就返回 null。

總結(jié)

  1. LinkedBlockingQueue 是基于單向鏈表的,線程安全的。
  2. 是一個(gè)有界的隊(duì)列,最大的容量是最大的 int 值。
  3. 出隊(duì)入隊(duì)基于兩把鎖。互不阻塞。

LinkedBlockingQueue 被用在線程池中,也可以用在生產(chǎn)者-消費(fèi)者模式中。

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 源碼
    +關(guān)注

    關(guān)注

    8

    文章

    671

    瀏覽量

    30321
  • 函數(shù)
    +關(guān)注

    關(guān)注

    3

    文章

    4380

    瀏覽量

    64843
  • 線程
    +關(guān)注

    關(guān)注

    0

    文章

    508

    瀏覽量

    20206
  • node
    +關(guān)注

    關(guān)注

    0

    文章

    24

    瀏覽量

    6137
收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    C語(yǔ)言-鏈表(單向鏈表、雙向鏈表)

    在前面章節(jié)已經(jīng)學(xué)習(xí)了數(shù)組的使用,數(shù)組的空間是連續(xù)空間,數(shù)組的大小恒定的,在很多動(dòng)態(tài)數(shù)據(jù)存儲(chǔ)的應(yīng)用場(chǎng)景下,使用不方便;而這篇文章介紹的鏈表結(jié)構(gòu),支持動(dòng)態(tài)增加節(jié)點(diǎn),釋放節(jié)點(diǎn),比較適合存儲(chǔ)動(dòng)態(tài)數(shù)據(jù)的應(yīng)用場(chǎng)景,而且鏈表的空間是存儲(chǔ)在堆上面的,可以動(dòng)態(tài)分配,釋放
    的頭像 發(fā)表于 09-09 11:30 ?1996次閱讀

    【Linux高級(jí)編譯】list.h的高效應(yīng)用—單向鏈表實(shí)現(xiàn)

    【Linux高級(jí)編譯】Linux內(nèi)核的list.h的高效應(yīng)用——單向鏈表實(shí)現(xiàn)
    的頭像 發(fā)表于 09-12 09:33 ?2539次閱讀
    【Linux高級(jí)編譯】list.h的高效應(yīng)用—<b class='flag-5'>單向</b><b class='flag-5'>鏈表</b>的<b class='flag-5'>實(shí)現(xiàn)</b>

    C語(yǔ)言實(shí)現(xiàn)動(dòng)態(tài)鏈表的建立

    上期講解了靜態(tài)鏈表的實(shí)例,但是靜態(tài)鏈表建立的節(jié)點(diǎn)數(shù)量有限,畢竟是手工建立,難免也會(huì)出問(wèn)題, 所以這期講講怎么使用動(dòng)態(tài)的方式建立鏈表,也就是 動(dòng)態(tài)鏈表 !
    發(fā)表于 01-13 15:16 ?1740次閱讀
    C語(yǔ)言<b class='flag-5'>實(shí)現(xiàn)</b>動(dòng)態(tài)<b class='flag-5'>鏈表</b>的建立

    C語(yǔ)言算法題:反轉(zhuǎn)一個(gè)單向鏈表

    鏈表是編程學(xué)習(xí)的一個(gè)難點(diǎn)。其實(shí),在C語(yǔ)言編程以及單片機(jī)裸機(jī)開發(fā)中,鏈表運(yùn)用并不多。但是如果想提升嵌入式技能水平或收入水平,可以考慮深入嵌入式系統(tǒng)層面(如參與操作系統(tǒng)設(shè)計(jì)、深入學(xué)習(xí)新的操作系統(tǒng)等),此時(shí),鏈表技術(shù)至關(guān)重要。
    發(fā)表于 06-21 11:07 ?1376次閱讀
    C語(yǔ)言算法題:反轉(zhuǎn)一個(gè)<b class='flag-5'>單向</b><b class='flag-5'>鏈表</b>

    C語(yǔ)言單向鏈表

    本帖最后由 snowmay001 于 2016-5-22 15:57 編輯 lianbiao.cpp/* 練習(xí)使用鏈表:創(chuàng)建鏈表、遍歷鏈表、查找節(jié)點(diǎn)、添加節(jié)點(diǎn)、刪除節(jié)點(diǎn)*/#include
    發(fā)表于 05-22 15:53

    玩轉(zhuǎn)C語(yǔ)言鏈表-鏈表各類操作詳解

    ,它稱為“表尾”,它的地址部分放一個(gè)“NULL”(表示“空地址”),鏈表到此結(jié)束?! ?b class='flag-5'>鏈表的各類操作包括:學(xué)習(xí)單向鏈表的創(chuàng)建、刪除、 插入(無(wú)序、有序)、輸出、 排序(選擇、插入、冒泡
    發(fā)表于 09-18 13:30

    鏈表的缺陷是什么

    鏈表有一定的缺陷,就是單向性,只能從一個(gè)結(jié)點(diǎn)到下一個(gè)節(jié)點(diǎn),而不能訪問(wèn)到上一個(gè)結(jié)點(diǎn),而循環(huán)鏈表就可以解決這一問(wèn)題,當(dāng)然,用雙向鏈表更加方便#include #include typed
    發(fā)表于 07-14 08:09

    怎么實(shí)現(xiàn)c語(yǔ)言循環(huán)鏈表?

    怎么實(shí)現(xiàn)c語(yǔ)言循環(huán)鏈表?
    發(fā)表于 10-19 06:07

    RT-Thread內(nèi)核中雙鏈表的使用與實(shí)現(xiàn)

    1. 單鏈表與雙鏈表鏈表: 由一個(gè)個(gè)節(jié)點(diǎn)(node)組成,每個(gè)節(jié)點(diǎn)都有指向下一個(gè)節(jié)點(diǎn)的指針。節(jié)點(diǎn)的連接方向是單向的,節(jié)點(diǎn)之間用指針連起來(lái),所有結(jié)構(gòu)體類型可以不一樣,
    發(fā)表于 04-01 12:05

    如何去實(shí)現(xiàn)一種基于Rust的單向鏈表設(shè)計(jì)呢

    , pub next: Option,}利用 impl 關(guān)鍵字來(lái)定義結(jié)構(gòu)體成員方法impl List {}創(chuàng)建鏈表pub fn new(value: i32) -> List { List {next
    發(fā)表于 04-27 15:11

    C語(yǔ)言實(shí)現(xiàn)鏈表舉例

    所謂鏈表,就是用一組任意的存儲(chǔ)單元存儲(chǔ)線性表元素的一種數(shù)據(jù)結(jié)構(gòu)。鏈表又分為單鏈表、雙向鏈表和循環(huán)鏈表等。我們先講講單
    發(fā)表于 07-11 16:40 ?87次下載
    C語(yǔ)言<b class='flag-5'>實(shí)現(xiàn)</b>單<b class='flag-5'>鏈表</b>舉例

    單向鏈表中的存值與存址、數(shù)據(jù)與p_next分離問(wèn)題

    第三章為算法與數(shù)據(jù)結(jié)構(gòu),本文為3.2 單向鏈表中的3.2.1 存值與存址和3.2.2 數(shù)據(jù)與p_next分離。
    的頭像 發(fā)表于 09-19 17:32 ?7458次閱讀
    <b class='flag-5'>單向</b><b class='flag-5'>鏈表</b>中的存值與存址、數(shù)據(jù)與p_next分離問(wèn)題

    周立功新著內(nèi)容分享:雙向鏈表是什么?

    單向鏈表的添加、刪除操作,都必須找到當(dāng)前結(jié)點(diǎn)的上一個(gè)結(jié)點(diǎn),以便修改上一個(gè)結(jié)點(diǎn)的p_next指針完成相應(yīng)的操作。
    的頭像 發(fā)表于 09-22 18:24 ?6189次閱讀

    C語(yǔ)言_鏈表總結(jié)

    本篇文章介紹C語(yǔ)言鏈表相關(guān)知識(shí)點(diǎn),涉及鏈表的創(chuàng)建、單向鏈表、循環(huán)鏈表、雙向鏈表、
    的頭像 發(fā)表于 08-14 09:53 ?2105次閱讀

    OpenHarmony中軟件模塊的單鏈表實(shí)現(xiàn)

    為了性能考慮,嵌入式系統(tǒng)一般使用C語(yǔ)言進(jìn)行開發(fā),由于C語(yǔ)言標(biāo)準(zhǔn)庫(kù)沒(méi)有封裝鏈表,所以嵌入式系統(tǒng)一般自己設(shè)計(jì)和實(shí)現(xiàn)鏈表這種數(shù)據(jù)結(jié)構(gòu)。
    發(fā)表于 08-30 09:25 ?470次閱讀