WordPress 無敵架站手冊:架站新手都想擁有,參加活動免費帶回家

免費資源網路社群跟著 WordPress 一起長大,可以這麼說,我在 2006 年接觸 WordPress 後隨即就架設了第一個部落格,迄今十年,也就是大家正在瀏覽的網站。這些年持續不斷在 WordPress Taiwan 正體中文社群盡自己最大努力,除了程式中文語系維護,我也嘗試翻譯、撰寫部分教學文件以及在外掛功能上推動中文化工作,本著自己也有在使用就順手做一下,讓後來加入的人可以少碰一些問題的想法,我做得很開心。

這幾年台灣使用 WordPress 架站的朋友越來越多,全世界市佔率超越 25%(數據來自 W3Tech),到處都能看到 WordPress 蹤跡,想架設網站幾乎沒有第二個選項。但回到台灣書店一望,WordPress 書籍仍舊寥寥可數(當然相較於幾年前來說已經算活躍許多),即使網路上已有豐富的教學文件,卻沒有一本非常完整的中文手冊。

對於學習 WordPress 架站的人來說,想從頭到尾、穩紮穩打很難找到學習路徑,於是我這幾年就興起想要寫一本由淺入深、全面的 WordPress 工具書,恰巧得知英國出版商 Packt Publishing 的《WordPress 4.x Complete》一書,二話不說就決定將它翻譯成中文書,讓想學 WordPress 架站的朋友有個更完整的參考資料。

《WordPress 無敵架站手冊》是一本從 WordPress 介紹、入門、安裝操作,到進階開發外掛、佈景主題及小工具等主題皆有涵蓋的完整手冊!後半章節還會教你如何利用 WordPress 建立非網誌型態網站。

雖然無法在有限篇幅內詳細說明所有範圍,但讀者可將本書做為學習的起點,從基礎延伸出去,繼續學習。對於有心想要了解 WordPress 架站的朋友來說,這是一本易於閱讀及上手的工具書,也希望透過這本書讓你認識更方便、安全可靠的免費開放原始碼架站程式 WordPress。

如何購買這本書,網上購書更優惠

如果你對架站有興趣,或者對於 WordPress 好奇、有興趣、想學習甚至是希望搭建一個自己的個人網站或部落格,你可以在實體店面或從網路通路買到這本書,我僅在文章內提供幾個購書鏈結,透過 Google 搜尋可以找到更多管道。

購書鏈結:http://www.books.com.tw/products/0010730008 (博客來)

久違的抽獎活動,還是要免費送書

若你一路以來都有在關注或追蹤免費資源網路社群的文章,依照慣例我都會提供一些贈品來送讀者,感謝博碩文化贊助本次贈書。

活動方式一如往昔,只要到免費資源網路社群 Facebook 粉絲專頁按個讚、在本文下方留言,就有機會在免費得到《WordPress 無敵架站手冊》!我們會在活動結束後抽出幸運讀者,在最短時間內將新書寄到您手上。

STEP 1

前往免費資源網路社群 Facebook 按個讚,相信大家都已經按過(也請多多幫我們宣傳分享,謝謝);如果你有使用其他社群網站,例如 Twitter、Google+,也一併將免費資源網路社群加入追蹤。網站右側還有一些免費資源網路社群使用的社群服務。

STEP 2

在本文下方留言(或直接在粉絲頁面同一則貼文留言)回覆以下文字:

WordPress 無敵架站手冊:架站新手都想擁有,參加活動免費帶回家

這樣就可以參加抽獎活動,是不是非常簡單呢?

活動時間五天,請多多分享轉貼

如果方便的話,也歡迎將本文鏈結分享、轉貼到你的 Facebook 或其他網站。若活動夠踴躍,我們也會視情況增加更多贈書名額喔!我會在下週三(9/28)抽出幸運的朋友,屆時在本文更新及 Facebook 等社群網站公告得獎情形,請大家把握這次難得機會多多支持!

得獎名單(9/28 晚間 22:00 更新)

本次活動一共有 816 位讀者參加,扣掉重複留言,以「粉絲團留言抽籤小助手」小工具隨機抽取 10 位留言者贈送新書《WordPress 無敵架站手冊》一本,幸運得獎的朋友名單如下(依照抽獎結果順序排列):

黃楚翔、王凱蓓、Yu-Wei Chen、Stella Lin、Cheng Lin、尹翠軒、盧嘉皓、黃豊益、胡倫、黃謙。

請幸運中獎的讀者儘速與 Pseric 聯繫,我也會到留言下方 tag 通知你,直接私訊告知我收件人資料即可。確認完畢就會陸續將熱騰騰的新書寄到你們手上囉!本書已在各大書局、網路書店上架,有興趣的朋友也能直接從網上購得,謝謝大家熱烈參與支持本次活動!

為了公平起見,下方是本次抽獎影片紀錄:

  • 按一下以分享至 Facebook(在新視窗中開啟)
  • 分享到 Twitter(在新視窗中開啟)
  • 分享到 LinkedIn(在新視窗中開啟)
  • 分享到 Pinterest(在新視窗中開啟)
  • 分享到 Pocket(在新視窗中開啟)

相關文章

本站聲明:網站內容來源免費資源網路社群https://free.com.tw,如有侵權,請聯繫我們,我們將及時處理

【精選推薦文章】

智慧手機時代的來臨,RWD網頁設計已成為網頁設計推薦首選

想知道網站建置、網站改版該如何進行嗎?將由專業工程師為您規劃客製化網頁設計及後台網頁設計

帶您來看台北網站建置台北網頁設計,各種案例分享

廣告預算用在刀口上,網站設計公司幫您達到更多曝光效益

Java集合 ArrayList原理及使用

ArrayList是集合的一種實現,實現了接口List,List接口繼承了Collection接口。Collection是所有集合類的父類。ArrayList使用非常廣泛,不論是數據庫表查詢,excel導入解析,還是網站數據爬取都需要使用到,了解ArrayList原理及使用方法顯得非常重要。

一. 定義一個ArrayList

//默認創建一個ArrayList集合
List<String> list = new ArrayList<>();
//創建一個初始化長度為100的ArrayList集合
List<String> initlist = new ArrayList<>(100);
//將其他類型的集合轉為ArrayList
List<String> setList = new ArrayList<>(new HashSet());

我們讀一下源碼,看看定義ArrayList的過程到底做了什麼?

public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable {
    /**
     * Default initial capacity.
     */
    private static final int DEFAULT_CAPACITY = 10;

    /**
     * Shared empty array instance used for empty instances.
     */
    private static final Object[] EMPTY_ELEMENTDATA = {};

    /**
     * Shared empty array instance used for default sized empty instances. We
     * distinguish this from EMPTY_ELEMENTDATA to know how much to inflate when
     * first element is added.
     */
    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

    /**
     * The array buffer into which the elements of the ArrayList are stored.
     * The capacity of the ArrayList is the length of this array buffer. Any
     * empty ArrayList with elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA
     * will be expanded to DEFAULT_CAPACITY when the first element is added.
     */
    transient Object[] elementData; // non-private to simplify nested class access

    /**
     * The size of the ArrayList (the number of elements it contains).
     *
     * @serial
     */
    private int size;

    /**
     * Constructs an empty list with the specified initial capacity.
     *
     * @param  initialCapacity  the initial capacity of the list
     * @throws IllegalArgumentException if the specified initial capacity
     *         is negative
     */
    public ArrayList(int initialCapacity) {
        if (initialCapacity > 0) {
            this.elementData = new Object[initialCapacity];
        } else if (initialCapacity == 0) {
            this.elementData = EMPTY_ELEMENTDATA;
        } else {
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        }
    }

    /**
     * Constructs an empty list with an initial capacity of ten.
     */
    public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }

    /**
     * Constructs a list containing the elements of the specified
     * collection, in the order they are returned by the collection's
     * iterator.
     *
     * @param c the collection whose elements are to be placed into this list
     * @throws NullPointerException if the specified collection is null
     */
    public ArrayList(Collection<? extends E> c) {
        elementData = c.toArray();
        if ((size = elementData.length) != 0) {
            // c.toArray might (incorrectly) not return Object[] (see 6260652)
            if (elementData.getClass() != Object[].class)
                elementData = Arrays.copyOf(elementData, size, Object[].class);
        } else {
            // replace with empty array.
            this.elementData = EMPTY_ELEMENTDATA;
        }
    }
}

其實源碼裏面已經很清晰了,ArrayList非線程安全,底層是一個Object[],添加到ArrayList中的數據保存在了elementData屬性中。

  • 當調用new ArrayList<>()時,將一個空數組{}賦值給了elementData,這個時候集合的長度size為默認長度0;

  • 當調用new ArrayList<>(100)時,根據傳入的長度,new一個Object[100]賦值給elementData,當然如果玩兒的話,傳了一個0,那麼將一個空數組{}賦值給了elementData;

  • 當調用new ArrayList<>(new HashSet())時,根據源碼,我們可知,可以傳遞任何實現了Collection接口的類,將傳遞的集合調用toArray()方法轉為數組內賦值給elementData;

注意:在傳入集合的ArrayList的構造方法中,有這樣一個判斷

if (elementData.getClass() != Object[].class),

給出的註釋是:c.toArray might (incorrectly) not return Object[] (see 6260652),即調用toArray方法返回的不一定是Object[]類型,查看ArrayList源碼

public Object[] toArray() {    return Arrays.copyOf(elementData, size);}

我們發現返回的確實是Object[],那麼為什麼還會有這樣的判斷呢?

如果有一個類CustomList繼承了ArrayList,然後重寫了toArray()方法呢。。

public class CustomList<E> extends ArrayList {
    @Override
    public Integer [] toArray() {
        return new Integer[]{1,2};
    };
    
    public static void main(String[] args) {
        Object[] elementData = new CustomList<Integer>().toArray();
        System.out.println(elementData.getClass());
        System.out.println(Object[].class);
        System.out.println(elementData.getClass() == Object[].class);
    }
}

執行結果:

class [Ljava.lang.Integer;
class [Ljava.lang.Object;
false

接着說,如果傳入的集合類型和我們定義用來保存添加到集合中值的Object[]類型不一致時,ArrayList做了什麼處理?讀源碼看到,調用了Arrays.copyOf(elementData, size, Object[].class);,繼續往下走

public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {    
    T[] copy = ((Object)newType == (Object)Object[].class)
        ? (T[]) new Object[newLength]
        : (T[]) Array.newInstance(newType.getComponentType(), newLength); 
    System.arraycopy(original, 0, copy, 0, Math.min(original.length, newLength));
    return copy;
}

我們發現定義了一個新的數組,將原數組的數據拷貝到了新的數組中去。

二. ArrayList常用方法

ArrayList有很多常用方法,add,addAll,set,get,remove,size,isEmpty等

首先定義了一個ArrayList,

List<String> list = new ArrayList<>(10);
list.add('牛魔王');
list.add('蛟魔王');
...
list.add('美猴王');

Object[] elementData中數據如下:

1. add(E element)

我們通過源碼來看一下add(“白骨精”)到底發生了什麼

public boolean add(E e) {
    ensureCapacityInternal(size + 1);
    // Increments modCount!!
    elementData[size++] = e;
    return true;
}

首先通過 ensureCapacityInternal(size + 1) 來保證底層Object[]數組有足夠的空間存放添加的數據,然後將添加的數據存放到數組對應的位置上,我們看一下是怎麼保證數組有足夠的空間?

private void ensureCapacityInternal(int minCapacity) {
    if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
        minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
    }
    ensureExplicitCapacity(minCapacity);
}
private void ensureExplicitCapacity(int minCapacity) {
    modCount++;
    // overflow-conscious code
    if (minCapacity - elementData.length > 0)
        grow(minCapacity);
}

這裏首先確定了Object[]足夠存放添加數據的最小容量,然後通過 grow(int minCapacity) 來進行數組擴容

private void grow(int minCapacity) {
    // overflow-conscious code
    int oldCapacity = elementData.length;
    int newCapacity = oldCapacity + (oldCapacity >> 1);
    if (newCapacity - minCapacity < 0)
        newCapacity = minCapacity;
    if (newCapacity - MAX_ARRAY_SIZE > 0)
        newCapacity = hugeCapacity(minCapacity);
    // minCapacity is usually close to size, so this is a win:
    elementData = Arrays.copyOf(elementData, newCapacity);
}

擴容規則為“數組當前足夠的最小容量 + (數組當前足夠的最小容量 / 2)”,即數組當前足夠的最小容量 * 1.5,當然有最大值的限制。

因為最開始定義了集合容量為10,故而本次不會進行擴容,直接將第8個位置(從0開始,下標為7)設置為“白骨精”,這時Object[] elementData中數據如下:

還有和add()類似的方法。空間擴容原理都是一樣,如:

add("鐵扇", 0); //將數組中的元素各自往後移動一位,再將“鐵扇”放到第一個位置上;

addAll(list..七個葫蘆娃); //將集合{七個葫蘆娃}放到”白骨精”后,很明顯當前數組的容量已經不夠,需要擴容了,不執行該句代碼了;

addAll(list..哪吒三兄弟, 4);//從第五個位置將“哪吒三兄弟”插進去,那麼數組第五個位置后的元素都需往後移動三位,數組按規則擴容為18。

指定了插入位置的,會通過rangeCheckForAdd(int index)方法判斷是否數組越界

2. set(int index, E element)

因為ArrayList底層是由數組實現的,set實現非常簡單,調用 set(8, "豬八戒") 通過傳入的数字下標找到對應的位置,替換其中的元素,前提也需要首先判斷傳入的數組下標是否越界。將“獼猴王”替換為“豬八戒”

public E set(int index, E element) {
    rangeCheck(index);
    E oldValue = elementData(index);
    elementData[index] = element;
    return oldValue;
}

//返回值“獼猴王”,當前數組中數據:

3. get(int index)

ArrayList中get方法也非常簡單,通過下標查找即可,同時需要進行了類型轉換,因為數組為Object[],前提是需要判斷傳入的數組下標是否越界。

public E get(int index) {
    rangeCheck(index);
    return elementData(index);
}
E elementData(int index) {
    return (E) elementData[index];
}

調用get(6)返回”哪吒“。

4. remove(int index)

首先說一下ArrayList通過下標刪除的方法,我們看一下源碼

public E remove(int index) {
    rangeCheck(index);
    modCount++;
    E oldValue = elementData(index);
    int numMoved = size - index - 1;
    if (numMoved > 0)
        System.arraycopy(elementData, index+1, elementData, index, numMoved);
    elementData[--size] = null; // clear to let GC do its work
    return oldValue;
}

通過源碼我們可以看到首先獲取了待刪除的元素,並最終返回了。其次計算了數組中需要移動的位數 size – index – 1,那麼很明顯我們可以得出待刪除的是最後一個元素的話,移到位數為0,否則移動位數大於0,那麼通過數組元素的拷貝來實現往前移動相應位數。

如remove(10),找到的元素為“美猴王”,那麼移動位數 = 12-10-1 = 1;此時將原本在第12個位置上(數組下標為11)的“白骨精”往前移動一位,同時設置elementData[11] = null;這裏通過設置null值讓GC起作用。

5. remove(Object o)

刪除ArrayList中的值對象,其實和通過下標刪除很相似,只是多了一個步驟,遍歷底層數組elementData,通過equals()方法或 == (特殊情況下)來找到要刪除的元素,獲取其下標,調用remove(int index)一樣的代碼即可。

public boolean remove(Object o) {
    if (o == null) {
        for (int index = 0; index < size; index++)
            if (elementData[index] == null) {
                fastRemove(index);
                return true;
            }
    } else {
        for (int index = 0; index < size; index++)
            if (o.equals(elementData[index])) {
                fastRemove(index);
                return true;
            }
    }
    return false;
}

6. 其他方法

size() : 獲取集合長度,通過定義在ArrayList中的私有變量size得到

isEmpty():是否為空,通過定義在ArrayList中的私有變量size得到

contains(Object o):是否包含某個元素,通過遍歷底層數組elementData,通過equals或==進行判斷

clear():集合清空,通過遍歷底層數組elementData,設置為null

三. 總結

本文主要講解了ArrayList原理,從底層數組着手,講解了ArrayList定義時到底發生了什麼,再添加元素時,擴容規則如何,刪除元素時,數組的元素的移動方式以及一些常用方法的用途,若有不對之處,請批評指正,望共同進步,謝謝!

【精選推薦文章】

自行創業 缺乏曝光? 下一步"網站設計"幫您第一時間規劃公司的門面形象

網頁設計一頭霧水??該從何著手呢? 找到專業技術的網頁設計公司,幫您輕鬆架站!

評比前十大台北網頁設計台北網站設計公司知名案例作品心得分享

台北網頁設計公司這麼多,該如何挑選?? 網頁設計報價省錢懶人包"嚨底家"

JS數據結構第三篇—雙向鏈表和循環鏈表之約瑟夫問題

一、雙向鏈表

在上文《JS數據結構第二篇—鏈表》中描述的是單向鏈表。單向鏈表是指每個節點都存有指向下一個節點的地址,雙向鏈表則是在單向鏈表的基礎上,給每個節點增加一個指向上一個節點的地址。然後頭結點的上一個節點,和尾結點的下一個節點都指向null。同時LinkedList類中再增加一個last內部屬性,一直指向鏈表中最後一個節點。結構模擬如圖:

同樣對外暴露的方法和單向鏈表一樣,只是內部實現稍有變化

雙向鏈表完整設計代碼:

/**
 * 自定義雙向鏈表:對外公開的方法有
 * append(element) 在鏈表最後追加節點
 * insert(index, element) 根據索引index, 在索引位置插入節點
 * remove(element)  刪除節點
 * removeAt(index)  刪除指定索引節點
 * removeAll(element) 刪除所有匹配的節點
 * set(index, element) 根據索引,修改對應索引的節點值
 * get(index)  根據索引獲取節點信息
 * indexOf(element) 獲取某個節點的索引位置
 * clear()  清空所有節點
 * length()   返回節點長度
 * print() 打印所有節點信息
 * toString() 打印所有節點信息,同print
 * */
const LinkedListDouble = function(){
    let head = null; //鏈表中第一個LinkNode
    let last = null;  //鏈表中最後一個LinkNode
    let size = 0;   //記錄鏈表元素個數

    //Node模型
    function LinkNode(prev, element, next){
        this.prev = prev; //當前節點的上一個node
        this.element = element;  //當前節點的元素
        this.next = next; //當前節點的下一個node
    }

    //元素越界檢查, 越界拋出異常
    function outOfBounds(index){
        if (index < 0 || index >= size){
            throw("抱歉,目標位置不存在!");
        }
    }

    //根據索引,獲取目標對象
    function node(index){
        outOfBounds(index);

        //判斷index是靠近前半部分,還是後半部分,以求最少次數找到目標節點
        if (index <= size>>1){
            //說明從頭往後找,次數少一點
            let obj = head;
            for (let i = 0;i < index; i++){
                obj = obj.next;
            }
            return obj;
        }
        else{
            //說明從后往前找,次數少一點
            let obj = last;
            for (let i = size-1; i > index; i--){
                obj = obj.prev;
            }
            return obj;
        }
    }

    //新增一個元素
    function append(element){
        if (size == 0){
            head = new LinkNode(null, element, null);
            last = head;
        }
        else{
            let obj = node(size-1);
            obj.next = new LinkNode(obj, element, null);
            last = obj.next;
        }
        size++;
    }

    //插入一個元素
    function insert(index, element){
        if (index == 0){
            head = new LinkNode(null, element, head);

            if (size == 0){
                last = head;
            }
        }
        else{
            let obj = node(index-1);
            obj.next = new LinkNode(obj, element, obj.next);

            if (index == size){
                last = obj.next;
            }
        }
        size++;
    }

    //修改元素
    function set(index, element){
        let obj = node(index);
        obj.element = element;
    }

    //移除節點(內部使用,不對外暴露)
    function removeNode(node){
        let prev = node.prev, next = node.next; //當前節點的前一個,和后一個

        //判斷head臨界點
        if (prev == head){
            head = next;
        }
        else{
            prev.next = next;
        }

        //判斷last臨界點
        if (next == last){
            last = prev;
        }
        else{
            next.prev = prev;
        }
        size--;
        return node.element;
    }

    //根據值移除節點元素
    function remove(element){
        let temp = head;
        while(temp){
            if (temp.element == element){
                return removeNode(temp);
            }
            else{
                temp = temp.next;
            }
        }
        return null;
    }

    //根據索引移除節點
    function removeAt(index){
        return removeNode(node(index));
    }

    //移除鏈表裡面的所有匹配值element的元素
    function removeAll(element){
        let newFirst = new LinkNode(null, 0, head), ele = null;
        let virHead = newFirst;

        while(virHead.next){
            if (virHead.next.element == element){

                ele = element;

                if (virHead.next.next){
                    virHead.next.next.prev = virHead.next.prev;
                }
                else{ //刪除了最後一個節點
                    last = virHead.next.prev;
                }
                virHead.next = virHead.next.next;
                size--;
            }
            else{
                virHead = virHead.next;
            }
        }

        //重新賦值
        head = newFirst.next;

        return ele;
    }

    //獲取某個元素
    function get(index){
        return node(index).element;
    }

    //獲取元素索引
    function indexOf(element){
        let obj = head, index = -1;

        for (let i = 0; i < size; i++){
            if (obj.element == element){
                index = i;
                break;
            }
            obj = obj.next;
        }
        return index;
    }

    //清除所有元素
    function clear(){
        head = null;
        last = null;
        size = 0;
    }

    //屬性轉字符串
    function getObjString(obj){

        let str = "";

        if (obj instanceof Array){
            str += "[";
            for (let i = 0; i < obj.length; i++){
                str += getObjString(obj[i]);
            }
            str = str.substring(0, str.length - 2);
            str += "], "
        }
        else if (obj instanceof Object){
            str += "{";
            for (var key in obj){
                let item = obj[key];
                str += "\"" + key + "\": " + getObjString(item);
            }
            str = str.substring(0, str.length-2);
            str += "}, "
        }
        else if (typeof obj == "string"){
            str += "\"" + obj + "\"" + ", ";
        }
        else{
            str += obj + ", ";
        }

        return str;
    }
    function toString(){
        let str = "", obj = head;
        for (let i = 0; i < size; i++){
            str += getObjString(obj.element);
            obj = obj.next;
        }
        if (str.length > 0) str = str.substring(0, str.length -2);
        return str;
    }
    //打印所有元素
    function print(){
        console.log(this.toString())
    }

    //對外公開方法
    this.append = append;
    this.insert = insert;
    this.remove = remove;
    this.removeAt = removeAt;
    this.removeAll = removeAll;
    this.set = set;
    this.get = get;
    this.indexOf = indexOf;
    this.length = function(){
        return size;
    }
    this.clear = clear;
    this.print = print;
    this.toString = toString;
}


////測試
// let obj = new LinkedListDouble();
// let obj1 = { title: "全明星比賽", stores: [{name: "張飛vs岳飛", store: "2:3"}, { name: "關羽vs秦瓊", store: "5:5"}]};
// obj.append(99);
// obj.append("hello")
// obj.append(true)
// obj.insert(3, obj1);
// obj.insert(0, [12, false, "Good", 81]);
// obj.print();
// console.log("obj1.index: ", obj.indexOf(obj1));
// obj.remove(0);
// obj.removeAll(obj1);
// obj.print();

////測試2
console.log("\n\n......test2.....")
var obj2 = new LinkedListDouble();
obj2.append(8); obj2.insert(1, 99); obj2.append('abc'); obj2.append(8); obj2.append(false);
obj2.append(12); obj2.append(8); obj2.append('123'); obj2.append(8);
obj2.print();
obj2.removeAll(8); //刪除所有8
obj2.print();

View Code

 

二、循環鏈表

在鏈表的基礎上,再稍稍修改一下,讓鏈表中的尾結點和頭節點鏈接起來,形成一個循環生生不息。單向循環鏈表是尾結點的下一個地址指向頭結點,而不是null;雙向循環鏈表則是last節點的next指向head節點,head節點的prev指向last節點。結構模擬如下兩個圖:

 

 對於單個節點的循環鏈表,頭結點和尾節點為同一個節點,則自己指向自己。結構模擬如圖:

 循環鏈表的代碼這裏就不貼出來了,代碼放在Github那裡,有興趣可以點進去看看。

 

三、循環鏈表的應用—約瑟夫問題模擬

據說著名猶太歷史學家 Josephus有過以下的故事:在羅馬人佔領喬塔帕特后,39 個猶太人與Josephus及他的朋友躲到一個洞中,39個猶太人決定寧願死也不要被敵人抓到,於是決定了一個自殺方式,41個人排成一個圓圈,由第1個人開始報數,每報數到第3人該人就必須自殺,然後再由下一個重新報數,直到所有人都自殺身亡為止。然而Josephus 和他的朋友並不想遵從。首先從一個人開始,越過k-2個人(因為第一個人已經被越過),並殺掉第k個人。接着,再越過k-1個人,並殺掉第k個人。這個過程沿着圓圈一直進行,直到最終只剩下一個人留下,這個人就可以繼續活着。問題是,給定了和,一開始要站在什麼地方才能避免被處決?Josephus要他的朋友先假裝遵從,他將朋友與自己安排在第16個與第31個位置,於是逃過了這場死亡遊戲。

這裏我做了一個效果圖,模擬下約瑟夫問題:

接下來我們如何用鏈表來模擬約瑟夫問題。

在上面循環鏈表的基礎上,我們給LinkedList再添加一個內部屬性current,指向當前節點,默認指向頭結點;再增加三個對外方法next()、removeCurrent()、reset(),分別表示當前節點指向下一個節點,移除當前節點,重置當前節點為頭結點。修改后,新的LinkedList對外方法有:

 新的循環雙向鏈表完整設計代碼:

/**
 * 在循環雙向鏈表的基礎上,增加1個屬性,3個方法(屬性內部使用,方法對外開放),讓循環鏈表發揮更大的效果:
 * current: 指向當前節點,默認指向首節點head
 * next():讓current每次移動一次,移上下一個節點, 返回元素
 * removeCurrent(): 每次刪除當前current指向的節點,刪除后,current指向下一個節點
 * reset(): 重置current指向首節點head
 *
 * 自定義雙向循環鏈表:對外公開的方法有
 * append(element) 在鏈表最後追加節點
 * insert(index, element) 根據索引index, 在索引位置插入節點
 * remove(element)  刪除節點
 * removeAt(index)  刪除指定索引節點
 * removeAll(element) 刪除所有匹配的節點
 * set(index, element) 根據索引,修改對應索引的節點值
 * get(index)  根據索引獲取節點信息
 * indexOf(element) 獲取某個節點的索引位置
 * clear()  清空所有節點
 * length()   返回節點長度
 * print() 打印所有節點信息
 * toString() 打印所有節點信息,同print
 * */
const CircleLinkedListDouble = function(){
    let head = null; //鏈表中第一個LinkNode
    let last = null;  //鏈表中最後一個LinkNode
    let size = 0;   //記錄鏈表元素個數
    let current = null; //當前指向的節點

    //Node模型
    function LinkNode(prev, element, next){
        this.prev = prev; //當前節點的上一個node
        this.element = element;  //當前節點的元素
        this.next = next; //當前節點的下一個node
    }

    //元素越界檢查, 越界拋出異常
    function outOfBounds(index){
        if (index < 0 || index >= size){
            throw("抱歉,目標位置不存在!");
        }
    }

    //根據索引,獲取目標對象
    function node(index){
        outOfBounds(index);

        //判斷index是靠近前半部分,還是後半部分,以求最少次數找到目標節點
        if (index <= size>>1){
            //說明從頭往後找,次數少一點
            let obj = head;
            for (let i = 0;i < index; i++){
                obj = obj.next;
            }
            return obj;
        }
        else{
            //說明從后往前找,次數少一點
            let obj = last;
            for (let i = size-1; i > index; i--){
                obj = obj.prev;
            }
            return obj;
        }
    }

    //新增一個元素
    function append(element){
        if (size == 0){
            head = new LinkNode(null, element, null);
            head.next = head;
            head.prev = head;
            last = head;
            current = head;
        }
        else{
            let obj = node(size-1);
            obj.next = new LinkNode(obj, element, head);
            last = obj.next;
            head.prev = last;
        }
        size++;
    }

    //插入一個元素
    function insert(index, element){
        //表示插入到第一個
        if (index == 0){

            let last = null;
            if (size > 0) last = node(size-1);

            head = new LinkNode(last, element, head);

            if (size < 1){
                head.next = head;
                head.prev = head;
                last = head;
                current = head;
            }
            else{
                last.prev = head;
            }
        }
        else{
            let prev = node(index-1);
            prev.next = new LinkNode(prev, element, prev.next);

            //表示插入到最後一個
            if (index == size){
                last = prev.next;
                head.prev = last;
            }
        }
        size++;
    }

    //修改元素
    function set(index, element){
        let obj = node(index);
        obj.element = element;
    }

    //移除節點(內部使用,不對外暴露)
    function removeNode(node){

        if (size == 1){
            current = head = last = null;
        }
        else{
            let prev = node.prev, next = node.next; //當前節點的前一個,和后一個

            //判斷head臨界點
            if (prev == last){
                head = next;
                head.prev = last;
                last.next = head;
            }
            else{
                prev.next = next;
            }

            //判斷last臨界點
            if (next == head){
                last = prev;
                last.next = head;
                head.prev = last;
            }
            else{
                next.prev = prev;
            }

            if (current == node){
                current = next;
            }
        }

        size--;
        return node.element;
    }

    //根據值移除節點元素
    function remove(element){
        let temp = head;
        while(temp){
            if (temp.element == element){
                return removeNode(temp);
            }
            else{
                temp = temp.next;
            }
        }
        return null;
    }

    //根據索引移除節點
    function removeAt(index){
        return removeNode(node(index));
    }

    //移除鏈表裡面的所有匹配值element的元素
    function removeAll(element){
        let newFirst = new LinkNode(null, 0, head), delNode = null;
        let virHead = newFirst;

        //為了避免無限循環,先把循環鏈表斷開
        head.prev = null, last.next = null;

        while(virHead.next){
            if (virHead.next.element == element){

                delNode = virHead.next;

                if (virHead.next.next){
                    virHead.next.next.prev = virHead.next.prev;
                }
                else{
                    last = virHead.next.prev;
                }

                if (virHead.next == current){
                    current = current.next;
                    virHead.next = current;
                }
                else{
                    virHead.next = virHead.next.next;
                }

                size--;
            }
            else{
                virHead = virHead.next;
            }
        }

        //重新賦值
        head = newFirst.next;
        last = size > 0 ? node(size-1) : null;
        if (size > 0){
            last.next = head;
            head.prev = last;
        }
        else{
            current = head = last = null;
        }

        return delNode.element;
    }

    //獲取某個元素
    function get(index){
        return node(index).element;
    }

    //獲取元素索引
    function indexOf(element){
        let obj = head, index = -1;

        for (let i = 0; i < size; i++){
            if (obj.element == element){
                index = i;
                break;
            }
            obj = obj.next;
        }
        return index;
    }

    //清除所有元素
    function clear(){
        current = head = last = null;
        size = 0;
    }

    //這次新增加的三個方法next, removeCurrent, reset
    //調用重置current指向head節點
    function reset(){
        current = head;
    }
    function next(){
        if (!current) return null;

        current = current.next;
        return current.element;
    }

    //每調用一次,刪除current指向的節點
    function removeCurrent(){
        if (size < 1) return null;
        return removeNode(current);
    }

    //屬性轉字符串
    function getObjString(obj){

        let str = "";

        if (obj instanceof Array){
            str += "[";
            for (let i = 0; i < obj.length; i++){
                str += getObjString(obj[i]);
            }
            str = str.substring(0, str.length - 2);
            str += "], "
        }
        else if (obj instanceof Object){
            str += "{";
            for (var key in obj){
                let item = obj[key];
                str += "\"" + key + "\": " + getObjString(item);
            }
            str = str.substring(0, str.length-2);
            str += "}, "
        }
        else if (typeof obj == "string"){
            str += "\"" + obj + "\"" + ", ";
        }
        else{
            str += obj + ", ";
        }

        return str;
    }
    function toString(){
        let str = "", obj = head;
        for (let i = 0; i < size; i++){
            str += getObjString(obj.element);
            obj = obj.next;
        }
        if (str.length > 0) str = str.substring(0, str.length -2);
        return str;
    }
    //打印所有元素
    function print(){
        console.log(this.toString())
    }

    //對外公開方法
    this.append = append;
    this.insert = insert;
    this.remove = remove;
    this.removeAt = removeAt;
    this.removeAll = removeAll;
    this.set = set;
    this.get = get;
    this.indexOf = indexOf;
    this.length = function(){
        return size;
    }
    this.clear = clear;
    this.print = print;
    this.toString = toString;

    //新增加的方法
    this.next = next;
    this.removeCurrent = removeCurrent;
    this.reset = reset;
}


////測試
// let obj = new CircleLinkedListDouble();
// let obj1 = { title: "全明星比賽", stores: [{name: "張飛vs岳飛", store: "2:3"}, { name: "關羽vs秦瓊", store: "5:5"}]};
//
// obj.append(99);
// obj.append("hello")
// obj.append(true)
// obj.insert(3, obj1);
// obj.insert(0, [12, false, "Good", 81]);
// obj.print();
// console.log("obj1.index: ", obj.indexOf(obj1));
// obj.remove(0);
// obj.removeAll(obj1);
// obj.print();

////測試2
// console.log("\n\n......test2.....")
// var obj2 = new CircleLinkedListDouble();
// obj2.append(8); obj2.append(99); obj2.append('abc'); obj2.append(8); obj2.append(false);
// obj2.append(12); obj2.append(8); obj2.append('123'); obj2.append(8);
// obj2.print();
// obj2.removeAll(8); //刪除所有8
// obj2.print();


/**
 * 測試3,來做一個有意思的題目:約瑟夫題目
 據說著名猶太歷史學家 Josephus有過以下的故事:在羅馬人佔領喬塔帕特后,39 個猶太人與Josephus及他的朋友躲到一個洞中,
 39個猶太人決定寧願死也不要被敵人抓到,於是決定了一個自殺方式,41個人排成一個圓圈,
 由第1個人開始報數,每報數到第3人該人就必須自殺,然後再由下一個重新報數,直到所有人都自殺身亡為止。
 然而Josephus 和他的朋友並不想遵從。
 首先從一個人開始,越過k-2個人(因為第一個人已經被越過),並殺掉第k個人。
 接着,再越過k-1個人,並殺掉第k個人。這個過程沿着圓圈一直進行,直到最終只剩下一個人留下,這個人就可以繼續活着。
 問題是,給定了和,一開始要站在什麼地方才能避免被處決?
 Josephus要他的朋友先假裝遵從,他將朋友與自己安排在第16個與第31個位置,於是逃過了這場死亡遊戲。

 用循環鏈表來模擬這個遊戲
 */
console.log("\n\n........test3約瑟夫題目。。。....");
var obj3 = new CircleLinkedListDouble();
for (let i = 0; i < 41; i++){
    obj3.append(i+1);
}
obj3.print();
console.log("*************約瑟夫遊戲開始**********")
for (let i = 0; i < 39; i++){
    obj3.next(); obj3.next(); //移動兩次
    obj3.removeCurrent(); //刪除當前節點
    console.log("第", (i+1), "次,剩餘的為:", obj3.toString())
}
console.log("***************game over***************")
console.log("最後生存下來的是:", obj3.toString());

View Code

看下用鏈表模擬約瑟夫問題過程的效果:

 

其餘單向循環鏈表、單向循環鏈表增強、雙向循環鏈表等代碼Demo見github地址:https://github.com/xiaotanit/Tan_DataStruct

【精選推薦文章】

智慧手機時代的來臨,RWD網頁設計已成為網頁設計推薦首選

想知道網站建置、網站改版該如何進行嗎?將由專業工程師為您規劃客製化網頁設計及後台網頁設計

帶您來看台北網站建置台北網頁設計,各種案例分享

廣告預算用在刀口上,網站設計公司幫您達到更多曝光效益

專業SEO網站“排名第一”上線

 

SEO自上線以來,就收到國內站長的廣泛熱愛,人數持續增加,截止到19年六月,SEO收錄用戶數量超過百萬,月均活躍用戶超過千萬,成為名副其實的站長最受歡迎網站話題。在人數火爆的背後。為了能夠快速擁有一個權重較高的網站,能夠有一套全面的優化,可以有更多的能夠自由選擇關鍵詞,從而在網站排名中獲勝,成為很多新站長迫切的需求,很多本身沒有時間SEO優化的站長來說,選擇SEO服務也就成了一種效率的選擇。

然而,當前的SEO優化市場十分的混亂,隨便登入一個論壇都能搜到一大片,也出現了很多交了錢不見人,給想要尋找SEO的網站站長帶來了很多困惑。

日前了解到,一個專業從事SEO的網站“排名第一 www.paimingdiyi.com”已經上線運作了,網站以統一平台、公平價格的模式,為需要SEO的站長提供可靠、合理的服務,並同時提供快速排名、SEO教程等SEO服務。在交易方式上,同時支持淘寶、支付寶、等多種支付方式,並有專一客服進行定點服務,能夠有效的避免SEO優化詐騙和服務不到位的現象,實實在在解決了網站站長在選擇SEO顧問時的各種擔心。

掌握最新排名算法,有想要通過SEO排名獲得網站流量的朋友,要抓緊時間了。如果本身又沒有太多時間的話,那就不妨到“SEO排名第一”來尋找SEO顧問吧,不必再為詐騙擔心,也不用害怕服務不到位,有了可靠的平台,自己網站排名快速提升,獲得網站流量的願望也就不再遙不可及了。

但話說回來,一個網站排名還不好,最重要的還是在持續的SEO優化中積累的排名經驗。單純依靠SEO顧問或者是買別人的服務,雖然能夠僥倖獲得排名提升,但卻不能夠真實的體現自己的SEO水平。對於想要通過自己練習來提高真實SEO技術的站長,還是更多的花點時間,多來學習SEO,當然如果你更多的是希望感受巔峰對決,和第一比拼,那排名第一的SEO顧問,可能就是你最合適的選擇。

本站聲明:網站內容來源搜狐https://www.admin5.com/,如有侵權,請聯繫我們,我們將及時處理

【精選推薦文章】

自行創業 缺乏曝光? 下一步"網站設計"幫您第一時間規劃公司的門面形象

網頁設計一頭霧水??該從何著手呢? 找到專業技術的網頁設計公司,幫您輕鬆架站!

評比前十大台北網頁設計台北網站設計公司知名案例作品心得分享

台北網頁設計公司這麼多,該如何挑選?? 網頁設計報價省錢懶人包"嚨底家"

網絡營銷同行勸守護袁昆別天天聊SEO優化,原因何在?

 

(文/守護袁昆)最近一段時間守護袁昆聊網站SEO優化比較多,總有些朋友說現在還能做SEO優化嗎?SEO優化早就過時了,現在是移動互聯網時代,就應該做短視頻。

現在還能不能做網站SEO優化呢?

其實任何一個平台信息過量,那麼就會有搜索存在,守護袁昆認為有搜索就離不開SEO優化。大多數朋友認為SEO優化做不了,主要還是網站SEO優化,甚至百度SEO優化泛濫成災。

百度SEO優化、淘寶SEO優化、微博SEO優化、微信SEO優化、頭條SEO優化……哪一個平台不是用戶量大、信息量大?系統推薦的可能並不是你喜歡的,那麼搜索就是一種必然。

哪些人在說SEO優化做不了?

沒有玩好SEO優化的一群人,他們也許是真的做SEO優化沒什麼效果,最後不得不忍痛離開,還不忘抱怨一句:SEO優化不是人乾的事,SEO優化已經過時了。

沒有做過SEO優化的一群人,人云亦云的事太多了。很多朋友根本就沒做過SEO優化,聽到別人說SEO優化做不了,所以SEO優化不能做。

網絡營銷同行為什麼勸守護袁昆別談SEO優化?

SEO優化是網絡營銷的基礎,為什麼同行讓守護袁昆別談呢?因為大家都不做,才有更多的機會。其實完全沒這個必要,為什麼這麼說?

大多數SEO優化人員能力不足,所以完全不會對我們造成競爭,或者說競爭極小,沒必要擔心SEO優化市場。

SEO優化資深玩家更多的是資源,甚至做付費方面的營銷推廣,也看不起這低成本耗費時間的玩法。

守護袁昆認為不僅僅要談SEO優化,還要讓沒有多大營銷預算的中小企業看到SEO優化的效果,讓大家認可SEO優化在網絡營銷推廣中的地位,這樣才能更適合行業發展。

SEO優化過時了,應該做自媒體、做短視頻?

SEO優化並沒有過時,做自媒體也並沒有錯,自媒體寫好標題和描述不就是最基本的SEO優化技巧嗎?

中小企業是否要做短視頻?守護袁昆給大家分析過:做短視頻的投入成本應該是圖文的兩三倍。對於營銷預算嚴重不足的中小企業,能去玩短視頻嗎?

不管互聯網營銷怎麼變,只要涉及到信息過量就離不開搜索,那麼SEO優化還是基礎。不管互聯網營銷平台怎麼變,優質的原創內容已經越來越重要。

守護袁昆別天天聊SEO優化了,作為想玩好互聯網營銷推廣的中小企業主,大家認為是否應該繼續聊下去?

本站聲明:網站內容來源搜狐https://www.admin5.com/,如有侵權,請聯繫我們,我們將及時處理

【精選推薦文章】

智慧手機時代的來臨,RWD網頁設計已成為網頁設計推薦首選

想知道網站建置、網站改版該如何進行嗎?將由專業工程師為您規劃客製化網頁設計及後台網頁設計

帶您來看台北網站建置台北網頁設計,各種案例分享

廣告預算用在刀口上,網站設計公司幫您達到更多曝光效益

網站seo優化方案書 seo專員必寫方案 學到就是錢

 

公司成立后,都希望自己公司有一個公司官網,但有了公司網站后,並不是每個網站都做得很好,所以需要專業的seo優化人員進行站內和站外優化,針對公司網站寫seo優化方案時,有哪些要點呢?以下就是seo方案書的框架,僅供參考!

一、網站概述

1,網站介紹

1)網站名稱:

2)網站域名:

3)網站定位:

目標用戶:

2,網站數據分析

1)網站基本信息

2)網站收錄和反鏈

3)網站百度快照

4)網站的權重及外鏈

5)標題、關鍵詞及描述數據(TKD三大標籤)

6)關鍵詞指數和排名

3,網站優化目標

1)權重:將網站權重提升為3

2)關鍵詞排名:優化關鍵詞並把核心關鍵詞優化到百度前3頁

3)收錄數:後期達到每天2-3的收錄數

二、行業和競爭對手分析

1,分析競爭對手

1)競爭者

2)競爭策略

2,行業分析

三、網站優化方案

1,關鍵詞優化

2,標題優化

3,描述優化

4,代碼優化

5,網站結構和頁面優化

6,301和404頁面

7,內容優化

8,內鏈優化

1)文章正文錨文本設計四大原則:

a,軟性植入,符合文章的需要,不要生硬嵌套;

b,錨文本對文章有促進作用,二者可以做到相得益彰;

c,延展用戶需求,挖掘用戶額外需求並滿足;

d,錨文本數量不宜太多,否則會降低當前頁面的權重。

2)Tag標籤優化:起到引導作用,增加文章被訪問的機會,添加tag標籤要體現自己的特色;

3)定期檢查死鏈以及處理掉,可以使用站長工具查詢是否有死鏈,及時刪除或更改鏈接。

9,外鏈優化

1)軟文:新聞報道型、學員體驗型、故事講述型、利用網絡事件型、網絡熱帖型及總結歸納型等;

2)外鏈優化方法:原創或偽原創高質量的軟文,平衡持續增加文章數量,並且文章之間要有相關性,進行深度鏈接;

3)外鏈發布平台:微信平台、微博平台、問答平台、百科平台、直播平台、視頻平台、音頻平台、社區平台、論壇平台及自媒體平台等;

4)外鏈日常工作安排:每天堅持發布10篇關於網站的外鏈。

四、總結

這就是以上針對公司網站進行seo優化,寫方案書時的框架參考,通過站長之家查詢該公司網站的數據進行填寫,並且對該公司主營產品或服務進行詳細了解,針對性寫出優化方案即可。

不知道seo整體優化方案怎麼做?A5服務為企業提供SEO診斷方案,快速讓你了解問題所在。

本站聲明:網站內容來源搜狐https://www.admin5.com/,如有侵權,請聯繫我們,我們將及時處理

【精選推薦文章】

自行創業 缺乏曝光? 下一步"網站設計"幫您第一時間規劃公司的門面形象

網頁設計一頭霧水??該從何著手呢? 找到專業技術的網頁設計公司,幫您輕鬆架站!

評比前十大台北網頁設計台北網站設計公司知名案例作品心得分享

台北網頁設計公司這麼多,該如何挑選?? 網頁設計報價省錢懶人包"嚨底家"

一個優秀的SEO優化方案必須包含哪幾個方面

 

不管是我們為自己的網站做SEO優化,還是做公司網站的SEO優化,又或者是給客戶提供SEO服務,我都希望大家能在SEO工作開始之前做好一份詳細的SEO方案;我們首先確定一個整站seo優化方案,那麼SEO具體操作就不那麼困惑了。

下面我們來說說:個優秀的SEO優化方案必須包含哪幾個方面

1、 建站的基礎:域名和服務器的選擇。

眾所周知,一個權重高的域名在做網站優化的時候是非常有利的,這可以理解為一個十歲的孩子和一個八歲的孩子去摔跤,十歲的孩子更容易獲勝。服務器決定了搜索引擎的蜘蛛在查找你網站時候的友好度。你的服務器越穩定,速度越快,蜘蛛給你的評分越高。這對於一個搜索引擎蜘蛛對你網站權重的判斷也是有直接關係的。而且對用戶的體驗也是至關重要,所以域名和服務器就是我們網站的根基,要想做大做強根基一定要打撈,確保優化站點服務器或主機空間:安全、穩定、快速。

2、 競爭對手、行業特點、用戶群體的分析

孫子兵法有雲:“知己知彼,方能百戰不殆”。在着手優化之前,要先去了解客戶的產品和服務,以及研究競爭對手網站情況,關鍵詞的排名、網站權重、網站的基本數據;特別是在SEO現狀下,排名首頁的核心關鍵詞基本是被百度的產品和一些大型的門戶網站所佔,那麼這個時候我們應該如何區制定策略?

分析所在行業和了解用戶的群體,網站的目標用戶是屬於哪一類,不同的網站性質所需要的目標用戶是不同的,建議大家要做精準的用戶營銷,不為SEO而去SEO。

3、關鍵詞的確定

網站關鍵詞的選定必須根據產品的內容以及客戶的需求共同來確定這個網站需要做的詞,兩者缺一不可。

沒有產品內容則這個網站在相關性上的契合度不夠高,網站在搜索引擎的排名就比普通的網站更難。客戶的需求同樣決定了網站的轉化率問題。一個網站如果有產品內容了,但是關鍵詞確定的時候不能按照客戶的需求來確定就很難為客戶精準地找到目標群。對於分析關鍵詞的方法,建議大家可從以下幾點來入手:

1、研究競爭對手的網站關鍵詞

2、關鍵詞挖掘工具:這裏特別推薦百度後台關鍵詞查詢工具如:以及百度指數、百度推廣的關鍵詞規劃師和愛站網關鍵詞推薦挖掘工具。

3、搜索引擎下拉框和相關搜索。

4、問答平台長尾關鍵詞挖掘如:百度知道、360問答等(要自己起辨別真偽)

4、網站的欄目與結構優化

網站的欄目頻道應該清晰、直觀一,使用戶一目瞭然,充分根據用戶的需求用戶的特徵進行劃分,同時要保證欄目下內容的垂直度;

網站的結構優化,其中以扁平樹狀結構最為流行。扁平化結構就是:讓蜘蛛可以在盡量短的鏈接跳轉內達到你網站的每一個頁面。樹形機構的意思則是網站的二級目錄頁面要放在服務器的二級目錄,三級目錄要放在三級目錄。以保證網站的層次分明。從而使蜘蛛對於網站權重的分配達到理想的效果。

5、網站的內連和標籤的優化

好的網站內鏈方案,不僅可以提成用戶的體驗,增加用戶的訪問深度、訪問時間和減少用戶的跳出率還可以是網站更充分的收錄;

但要注意控制文章內部鏈接數量,文章之間鏈接對象的相關性要高,給重要的網頁相對多的鏈接。

網站的標籤:對於網站的文章或者產品給予標籤分類;從而形成聚合頁面,同樣網站的標籤和內連可以是網站形成網狀,網頁間的權重能得道更好的傳遞

6、網站的細節上的優化

網站細節上的優化,也是我們最容易忽視的一些地方如:標題的寫法,圖片是我ALT標籤;合理布局關鍵詞和關鍵詞密度(標題、標籤、描述文本中),描述設置;次導航,定向錨文本,內頁第一次出現的錨文本加黑;做好頁面內容的相關性,堅持原創文章內容更新;URL統一,使用絕對路徑,做好301重新定向等等

7、網站的引流與外鏈

網站的流量,它決定了這個網站能給企業帶來多少的效益。所以引流也是SEO方案需要考慮的問題。

如何引流有很多種方式,最為有效的方法主要包括:軟廣告以及事件營銷。軟文一般是指一些技術性比較高的文章在一些相關行業的平台或者一些自媒體平台發布,然後把客戶引到你的網站,來尋找另外一些知識。事件營銷主要是以利益為基點,通過一些活動優惠或者贈送等噱頭將客戶引入網站。

對於外鏈在前面(外鏈算法獨家見解)已有所介紹,這裏就不在重複,感興趣的朋友可以去前面看看;

8 除了這些者外別忘了對每個步驟所需的時間、人力、工具、費用以及每個階段可能達到目標效果的預測

 

不知道seo整體優化方案怎麼做?A5服務為企業提供SEO診斷方案,快速讓你了解問題所在。

本站聲明:網站內容來源搜狐https://www.admin5.com/,如有侵權,請聯繫我們,我們將及時處理

【精選推薦文章】

智慧手機時代的來臨,RWD網頁設計已成為網頁設計推薦首選

想知道網站建置、網站改版該如何進行嗎?將由專業工程師為您規劃客製化網頁設計及後台網頁設計

帶您來看台北網站建置台北網頁設計,各種案例分享

廣告預算用在刀口上,網站設計公司幫您達到更多曝光效益

Tables Generator 線上製作產生表格 HTML、LaTeX、Markdown 原始碼

如果有接觸過網頁設計或曾經嘗試在網站、部落格放入表格,應該會覺得表格(Tables)是一個非常難搞的東西,不但原始碼複雜,沒有所見即所得編輯器似乎也很難直接寫出來,而在瀏覽器上使用的網頁編輯器又很難修改表格內容,有時候從其他文書處理工具直接複製貼上就會自帶很多用不到的程式碼,程式碼看起來很髒又無法符合當前的頁面風格,總之表格一直是很多人的痛,我也很少在網頁中用到表格,不過表格還是呈現一些數據相當好的方式。

若你要在網頁上用到表格語法,本文要介紹的「Tables Generator」會對你有幫助,這是一款線上表格語法產生器,可產生 LaTeX、HTML、純文字、Markdown 和 MediaWiki 表格語法,是個非常方便好用的工具。

這個表格產生器內建所見即所得編輯器,使用者可匯入資料,或是直接從其他來源像是 Google Docs、LibreOffice、網頁複製貼上表格內容,也能在網站中編輯表格欄位,最終產生適合使用的程式碼。Tables Generator 適合不熟悉 HTML、CSS 的朋友使用,如果你想為網站或是部落格(WordPress、Drupal 或任何支援 HTML 程式碼的平台)加入表格,那麼可以透過這個工具產生程式碼。

網站名稱:Tables Generator
網站鏈結:http://www.tablesgenerator.com/

使用教學

STEP 1

開啟 Tables Generator 網站,從上方選單選擇要產生的原始碼類型,前面有提到網站支援的語法包括 LaTeX、HTML、純文字、Markdown 和 MediaWiki。

STEP 2

如果你的表格是 .csv 檔案,可點選上方的「Import CSV file…」快速匯入資料,或將表格資料貼上等等,依照使用者切換的語法類型不同,也會顯示不一樣的功能選單。

主要的表格功能也可以從上方選單選取,包括新增、插入欄位、刪除欄位,文字樣式相關設定也能從編輯器上方功能列找到。

STEP 3

Tables Generator 最大優勢是可直接在網頁中編輯表格內容,包括各個欄位的文字、數值等等,編輯完成後點選下方「Generate」就會產生對應程式碼,預設情況下會帶入 CSS 樣式表,如果不需要(或是網頁部落格本身就有相關樣式)勾選 Do not generate CSS 就不會產生樣式程式碼。

STEP 4

最後,複製 Tables Generator 產生的原始碼貼到網頁或部落格就能看到表格效果,下方還有一些功能像是讓表格支援自適應設計、表格水平置中、第一個欄位是表格表頭(Table header)、啟用表格排序,勾選會即時更新上方的原始碼。

值得一試的三個理由:

  1. 線上建立表格或從其他地方將表格資料貼上處理
  2. 產生 LaTeX、HTML、純文字、Markdown 等表格語法
  3. 可選擇是否帶入 CSS 樣式,針對細部選項進行調整
  • 按一下以分享至 Facebook(在新視窗中開啟)
  • 分享到 Twitter(在新視窗中開啟)
  • 分享到 LinkedIn(在新視窗中開啟)
  • 分享到 Pinterest(在新視窗中開啟)
  • 分享到 Pocket(在新視窗中開啟)

相關文章

本站聲明:網站內容來源免費資源網路社群https://free.com.tw,如有侵權,請聯繫我們,我們將及時處理

【精選推薦文章】

自行創業 缺乏曝光? 下一步”網站設計“幫您第一時間規劃公司的門面形象

網頁設計一頭霧水??該從何著手呢? 找到專業技術的網頁設計公司,幫您輕鬆架站!

評比前十大台北網頁設計台北網站設計公司知名案例作品心得分享

台北網頁設計公司這麼多,該如何挑選?? 網頁設計報價省錢懶人包”嚨底家”

DemosWP 免費 WordPress 開發測試網站,提供 MySQL、SFTP 和 SSL

根據 W3Techs 統計,全世界有 33.9% 網站使用 WordPress 架設,在內容管理系統中坐擁超過六成的市佔率,WordPress 無疑是當前最受歡迎的部落格軟體和網站平台,你目前正在閱讀的免費資源網路社群也是使用 WordPress 技術。對於一般使用者來說,WordPress 提供非常廣泛、全面的特性,包括更改佈景主題、安裝外掛以擴展網站功能,本身亦有很好的搜尋引擎最佳化(SEO)效果和內建編輯器 Gutenberg,當然 WordPress 還提供中文在內等多國語言,對於不同語言來說有著相當好的相容性。

WordPress 最廣為人知的特色是「五分鐘快速安裝」,也就是可以在支援的環境下快速將網站建構出來,如果是有經驗的開發者,從無到有讓 WordPress 上線並不會花太多時間,對於要進行測試來說,也能在一個乾淨的網站進行,避免影響到現有網站運作。

以前我介紹過 Poopy.life 是一個可以快速建立 WordPress 測試環境的免費服務,這個工具對開發者非常有用,快速產生 WordPress 網站,而且提供使用者最高管理員權限,讓我們可直接在網站中測試 WordPress 相關功能。

本文要推薦的「DemosWP」是一個免費 WordPress 開發測試網站服務,只要註冊就能在幾秒內快速建立一個全新 WordPress 網站,同時附上 MySQL、SFTP 帳號密碼和 SSL 功能,也能複製、備份網站,安裝佈景主題或外掛程式等等。DemosWP 建置於 SiteGround,如果有在研究虛擬主機的話應該對這空間不陌生(想自己架一個網站嗎?請參考使用 SiteGround 虛擬主機一鍵快速安裝 WordPress 教學)。

比較特別的是 DemosWP 提供 MySQL 資料庫(含 phpMyAdmin)和 SFTP 帳號密碼,可進行的測試更多,在建立網站時能夠預先匯入測試資料,幫使用者填充原本沒有的內容,以便更快使用。目前註冊後

網站名稱:DemosWP
網站鏈結:https://demoswp.com/

使用教學

STEP 1

開啟 DemosWP 網站點選「Register」免費註冊一個帳號,依序填入使用者名稱、Email 後設定密碼即可完成註冊,不用進行身分驗證會直接跳轉到控制台。

STEP 2

接著點選「Create my first site」建立第一個 WordPress 測試網站。

建立網站時要設定網站名稱(網址)、使用者名稱、密碼、Email、WordPress 版本,記得在最下方語言部分選擇「正體中文」才能預先設定為中文介面,這邊設定的資料都是使用於接下來要安裝的 WordPress 網站,和 DemosWP 帳號密碼是不一樣的。

要注意的是設定時盡量使用英文數字,避免使用中文,否則在建立時可能發生問題。

之後還可以重新設定 WordPress 使用者帳號密碼或刪除重新建立網站,若忘記密碼也可透過 WordPress 內建功能重設。

在建立網站前按下「顯示進階選項」功能,可預先安裝外掛或佈景主題,其中有個非常方便的功能「Demo Content」,可以在安裝時順便把選擇的測試用資料匯入 WordPress,這裡提供的測試資料包括 WordPress 官方提供的內容、WPTest.io、Genesis 和 WooCommerce。

這些測試資料我曾經介紹過,如果你想用在其他地方可參考這幾篇文章:

  • 如何下載、匯入 WordPress 佈景主題開發測試範例元件(Theme Unit Test)?
  • WP Test 測試 WordPress 最棒範例內容,填充各種內容協助開發佈景主題

STEP 3

設定完成按下「Create Site」就會開始建立網站,大約一兩分鐘左右即可完成,等待網站狀態顯示為 Ready 就能開始使用。右側有一整排的設定選項,包括:檢視資訊、開啟網站首頁、開啟 WordPress 控制台、修復檔案權限、複製網站、搜尋取代網址、建立和備份資料庫、暫停網站、變更 WordPress 使用者密碼,如果要刪除網站只要點選最後方的刪除按鈕即可。

當前 DemosWP 允許使用者一次建立最多五個 WordPress 測試網站。

點選後可以看到網站使用的容量、剩餘容量、MySQL 資料庫帳號密碼、SFTP 使用者帳號密碼等資訊,就跟一般虛擬主機提供的資訊大同小異,DemosWP 還預先提供資料庫管理工具 phpMyAdmin 可以協助使用者從網頁端進入資料庫進行相關操作。

如果測試用的環境全部設定就緒,可透過「Clone Site」功能複製一個一模一樣的網站,這個功能非常好用,在 WordPress 主機服務也經常能看到類似功能。

STEP 4

下面幾張圖就是透過 DemosWP 建置出來的 WordPress 測試網站,可以看到我選擇預先匯入的測試內容已經在網站內,包括各種類型的文章、圖片、格式等等能反映出佈景主題設計。

當然在 WordPress 控制台部分跟一般自己找主機架設出來的網站一樣。

前面有提到 DemosWP 內建 phpMyAdmin 功能,透過提供的網址、MySQL 帳號密碼就能登入資料庫存取相關資料表。

既然是一個測試用的網站服務,記得不要在 DemosWP 儲存重要資料,因為這些內容可能會被刪除或無法使用,當然做為測試服務來說確實很方便,使用者不用從頭到尾自己安裝、建置 WordPress,可以快速給出一些測試用的資訊,對於在開發或測試 WordPress 佈景主題和外掛來說非常有用。

值得一試的三個理由:

  1. 快速產生開發測試用途的 WordPress 網站
  2. 提供 SFTP、MySQL、phpMyAdmin 和 SSL 等功能
  3. 可預先匯入測試用內容
  • 按一下以分享至 Facebook(在新視窗中開啟)
  • 分享到 Twitter(在新視窗中開啟)
  • 分享到 LinkedIn(在新視窗中開啟)
  • 分享到 Pinterest(在新視窗中開啟)
  • 分享到 Pocket(在新視窗中開啟)

相關文章

本站聲明:網站內容來源免費資源網路社群https://free.com.tw,如有侵權,請聯繫我們,我們將及時處理

【精選推薦文章】

智慧手機時代的來臨,RWD網頁設計已成為網頁設計推薦首選

想知道網站建置、網站改版該如何進行嗎?將由專業工程師為您規劃客製化網頁設計及後台網頁設計

帶您來看台北網站建置台北網頁設計,各種案例分享

廣告預算用在刀口上,網站設計公司幫您達到更多曝光效益

完整的SEO優化方案怎麼寫?

完整的seo優化方案怎麼去寫?首先我們要知道seo優化方案對於優化的速度影響是非常重要的,如果網站建立初期有一份優秀的seo優化方案,之後按照這個方案一步步執行在必要的時候進行修正,一般都會在預期內達到效果甚至遠超預期。那麼一份完整的seo優化方案到底該怎麼寫呢?請看下文。

一、分析seo關鍵詞

如何進行關鍵詞分析?這個在我之前的文章中有寫過。

首先明確兩點:

在關鍵詞的選擇中,切記不可貪多,也就是不要選擇指數過大的詞,要選擇自己有把握的詞。個人建議新手可以選擇指數在70左右的詞,想挑戰可以選擇200以下的詞,指數可通過百度指數查詢。

不要選擇沒有流量的詞,就算是新手也不應該選擇沒有流量的詞,因為這樣的詞就算是沒有優化也很有可能排在前面。

明確上面兩點后,就可以去詳細的進行關鍵詞的分析了,一般分析過程是這樣的:

行業狀態,做seo不管是任何行業首先就要了解其行業情況。

建立行業關鍵詞表。

競爭度分析,主要就是分析關鍵詞的競爭度以及相對自己公司較強行業公司的競爭度。

關鍵詞的鋪設規劃。

二、關鍵詞部署策略

分析seo關鍵詞之後,就需要對關鍵詞進行部署了,主要分一下幾點:

1、網頁三要素布局關鍵詞。

網頁三要素即網頁標題(title)、關鍵詞(keyword)、描述(description),這三點無論在任何頁面都應該好好布置,尤其是標題,雖然現在主流seo觀念是關鍵詞的作用越來越小,但是有總比沒有好這個在這裡是適合的,所以還是寫上吧。

2、麵包屑導航中布局關鍵詞。

麵包屑中布局關鍵詞,不僅起到了強調本內容頁的重點,並且還增加了內頁內鏈。

3、文章標題中布局關鍵詞

標題應該在符合內容的情況下還要適當的的插入關鍵詞,並且標題使用的html標籤上一定要使用H1標籤,這是因為在html語言本身上

標籤的權重就遠遠大於其他標籤,能讓搜索引擎準確的抓到文章標題,並理解它在本頁的重要性,除此之外還有一些在html5中應用的語義化標籤也應當注意,這裏不需了解,之後會出相關文章。

4、正文內容中的關鍵詞。

關於這點我覺得不必要像網上多數seo教程所提到的那樣,要如何如何布局,其實只要圍繞詞把內容寫好即可,內容中的關鍵詞應該是自然出現的,而不是可以插入的。

5、相關推薦欄目中布局關鍵詞

這裏的意思就是說在文章相關內容推薦中最好出現和本文相關的。

6、內容圖片的alt屬性中添加關鍵詞

這個很好理解,因為百度蜘蛛等搜索引擎機器人並不能識別圖片,它們看到的都是網頁的源代碼,所以需要給圖片alt屬性添加上對圖片的描述,以便於讓蜘蛛理解從而獲得蜘蛛更好的信任。

三、網站內鏈建設

首先我們要知道內鏈的建設在seo優化過程中是必不可少的,相比於外鏈其作用在現今seo中更為重要。

合理的內鏈可增加蜘蛛的爬取次數,可加快網站收錄。

合理的內鏈布局可以提升一些頁面的權重,有利於頁面的排名提升。

合理的出現內鏈可給用戶一個可能存在的選擇,有利於用戶體驗。

那麼如何建設呢?其實很簡單,那就是“通達性”,即合理的詞鏈向合理的頁面,不一定要鏈向首頁,我們要在內容中從語義化的角度去考慮,用戶所需要的。為什麼不鏈向首頁呢?很簡單,現在搜索引擎對網頁內容的相關度的要求越來越高,而首頁一般是整個網站的起點,擁有很多潛在的相關詞,但是和某個關鍵詞的相關度一般來說沒有內頁文章高(不絕對,有些也可以使用首頁做單關鍵詞),而一篇內頁正文一般是某些詞的相關內容,所以鏈向相關內頁更容易獲得青睞。

四、網站地圖的製作

網站內鏈建設后,就是製作網站全站的地圖,其實這也是屬於內鏈範疇。網站地圖主要由兩種一種是給蜘蛛看的XML格式地圖,另一種是給用戶看的HTML地圖。

1、XML格式的網站地圖

製作XML格式的網站地圖的好處就是,可以加大搜索引擎蜘蛛的爬取深度,以及爬取效果,從而,提高網站站內文章的收錄情況了。

xml指可擴展標記語言,常常是用來傳輸數據和存儲數據的。其實蜘蛛地圖也可以採用其他文件格式,如txt,但是普遍的建議是採用xml格式,為什麼呢?因為xml有一些定義標籤能讓地圖具有更多的功能,使它能對蜘蛛起到指導作用。

2、HTML格式的網站地圖

HTML格式的網站地圖主要是給用戶看的,目的是為了給用戶起到導航作用來改善用戶的體驗,一般大型網站會有需要,小型網站一般不需要,主要是用來調整內鏈結構的,如果一個小型網站的內鏈結構不是很友好,也可以考慮使用html網站地圖來調整內鏈結構。

關於網站地圖詳細的可以參考:https://www.seonowhy.com/157.html

五、外鏈建設

內容為王,外鏈為皇,有朋友可能會說那個時代已經過去了,這樣說是對也不全對,外鏈的作用依然存在,只不過更加規範了,是曾今大批量發外鏈的時代過去了,現在的外鏈講究的是一個“質”而不是“量”。

外鏈獲取的方式多種多樣,這裏講一個最簡單多的方式——友鏈。

友鏈是網站相互投票的一種形式,友鏈的質量也會影響搜索引擎對網站質量判斷,所以在交換友鏈中一定要注意質量問題。主要可以參考這幾點:

1.行業相關性:

交換的對象應該是和自己網站行業類型差不多的

2.權重:

權重相當,灰色灰色、違法行業不可。

3.收錄:

收錄相當,收錄速度相當。

4.友鏈的數量:

一般控制在二十以內。

5.友鏈所在頁面:

除非特殊要求,一般在首頁。

6.注意友鏈欺騙:

通常採用的方法有:

使用nofollow標籤屏蔽蜘蛛,對應方法:在對方網站查看源代碼在你的鏈接上是否增加了rel=“nofollow”這個屬性,如果有,那就是被欺騙了。

使用JavaScript動態生成友鏈,對應方法:在瀏覽器中屏蔽JavaScript,然後查看對方網站是否依然有自己的鏈接。

最後我們歸納一下,完整的seo優化方案應該這樣寫:第一步根據行業分析關鍵詞萃取出首批關鍵詞並做存檔,第二步根據關鍵詞和網站欄目結構寫出關鍵詞部署位置和各欄目TDK文案,第三步即基礎內鏈建設,其中包括對內容的規範也包括網站結構的調整和網站地圖,最後是外鏈的建設。上面四步都是概念性的東西,最後變成方案是需要各自根據網站去量化、具體化。提醒一下,如開頭所說方案可能也需要根據情況修正的,不是一成不變的,而是隨着網站的發展或者搜索引擎算法的調整去做出對應的調整。

不知道seo整體優化方案怎麼做?A5服務為企業提供SEO診斷方案,快速讓你了解問題所在。

本站聲明:網站內容來源搜狐https://www.admin5.com/,如有侵權,請聯繫我們,我們將及時處理

【精選推薦文章】

自行創業 缺乏曝光? 下一步”網站設計“幫您第一時間規劃公司的門面形象

網頁設計一頭霧水??該從何著手呢? 找到專業技術的網頁設計公司,幫您輕鬆架站!

評比前十大台北網頁設計台北網站設計公司知名案例作品心得分享

台北網頁設計公司這麼多,該如何挑選?? 網頁設計報價省錢懶人包”嚨底家”