1. 程式人生 > 實用技巧 >PHP接收$_POST表單值為字串或陣列時,對安全轉義的處理函式

PHP接收$_POST表單值為字串或陣列時,對安全轉義的處理函式

一、連結串列(Linked List)介紹

  連結串列是有序的列表,但是它在記憶體中式儲存如下

  1) 連結串列是以節點的方式來儲存,是鏈式儲存   2) 每個節點包含 data 域, next 域:指向下一個節點.   3) 如圖:發現連結串列的各個節點不一定是連續儲存.   4) 連結串列分帶頭節點的連結串列和沒有頭節點的連結串列,根據實際的需求來確定

二、單鏈表

  使用帶head頭的單向連結串列實現   原始碼:單鏈表

1,思路

準備
    1)首先定義node節點物件
    2)採用SingleLinkedList進行管理
    3)在SingleLinkedList中定義head節點為new Node(-1
,"","") 遍歷 1)定義臨時節點temp=head.next 2)while(temp!= null){temp=temp.next}遍歷並在其中列印temp 新增 1)定義一個臨時節點temp記錄到最後的位置 2)while(temp.next != null){temp=temp.next}移動指標 3)設定temp.next=node(新增的節點) 刪除 1)定義臨時節點temp=head,定義boolean flag為標識是否尋找到需要刪除的節點 2)while(temp.next != null){temp=temp.next}移動指標,判斷temp.next.no=no(輸入的節點id)為刪除節點的前一個節點並修改flag為刪除
3)判定 flag標識是否找到刪除節點,如果找到就執行temp.next=temp.next.next 修改 1)定義臨時節點temp=head,定義boolean flag為標識是否尋找到需要修改的節點 2)while(temp.next != null){temp=temp.next}移動指標,判斷temp.next.no==node.no(node為需要修改的節點)並修改flag為修改 3)判定 flag標識是否找到修改節點,如果找到就執行node.next=temp.next.next;temp.next=node

2,程式碼實現

/**
 * 新增節點
 
*/ public void add(Node node) { Node temp = head; while (true) { if (temp.next == null) { break; } temp = temp.next; } temp.next = node; } /** * 刪除節點 */ public void del(int no) { //臨時節點為需要刪除節點的前一個節點 Node temp = head; boolean flag = true; //標識是否已經尋找完畢 while (true) { //如果已經遍歷完畢 if (temp.next == null) { flag = false; break; } //找到需要刪除節點的上一個節點 if (temp.next.no == no) { break; } temp = temp.next; } if (!flag) { System.out.println("找不到需要刪除的節點!!!"); return; } //刪除對應的節點 temp.next = temp.next.next; } /** * 修改節點 */ public void update(Node node) { //臨時節點為需要修改節點的前一個節點 Node temp = head; //判斷是否在連結串列中找到對應的節點 boolean flag = true; while (true) { //沒有找到對應的節點 if (temp.next == null) { flag = false; break; } //找到對應的節點 if (temp.next.no == node.no) { break; } //後移 temp = temp.next; } if (!flag) { System.out.println("找不到需要修改的節點!!!"); return; } //修改 node.next = temp.next.next; temp.next = node; } /** * 遍歷單鏈表 */ public void list(){ //第一個節點 Node temp = head.next; while (true) { if (temp == null) { break; } System.out.println(temp); temp = temp.next; } }
View Code

3,單鏈表擴充套件(面試題)

  思路

查詢單鏈表中的倒數第k個節點
    1)獲取連結串列的長度(新方法),採用臨時變數count=0,定義臨時變數temp=head.next;while(temp!=null){count++;temp=temp.next},將最終的count返回
    2)使用num=length-k(倒數第k個),定義temp=head.next,flag=true
    3)while(temp!= null){temp=temp.next},將num--,當num==0時則break並且修改flag為找到對應節點
    4)判斷flag如果為找到狀態,則直接返回當前的temp
反轉單鏈表(改變連結串列結構)
    1)定義一個新的頭節點reverse,定義指標cur=head.next,定義臨時節點temp=null
    2)while(cur!=null){cur=cur.next}指標後移,指標後移之前先賦值temp=cur,然後將temp插入到reverse頭節點和reverse.next節點之間
    3)最後將原頭節點的下一個節點指向新頭節點的下一個節點,head.next = reverse.next
反向遍歷(不改變連結串列結構)
    1)定義棧Stack,定義臨時節點temp=head.next
    2)while(temp!=null){temp=temp.next}遍歷,並將每個temp都push到棧
    3)遍歷棧,pop棧中的元素

  程式碼

/**
 * 反向遍歷
 */
public void reversePrint() {
    //定義棧作為儲存
    Stack<Node> nodes = new Stack<>();

    Node temp = head;
    while (true) {
        if (temp.next == null) {
            break;
        }
        nodes.push(temp.next);
        temp = temp.next;
    }

    while (!nodes.empty()) {
        System.out.println(nodes.pop());
    }
}

/**
 * 反轉(改變結構)
 */
public void reverse(){
    //定義一個新的頭節點
    Node reverse = new Node(-1,"","");
    //指標
    Node cur = head.next;
    //臨時變數為當前節點
    Node temp = null;
    while (true) {
        if (cur == null) {
            break;
        }
        //當前值為指標指向的值
        temp = cur;
        //指標後移
        cur = cur.next;
        //當前節點為 頭節點的下一個接待你
        temp.next = reverse.next;
        //頭節點的下一個節點為當前接待你
        reverse.next = temp;
    }
    //將原始頭節點下一個節點指向  新頭節點的下一個節點
    head.next = reverse.next;
}

/**
 * 查詢單鏈表中的倒數第 k 個節點
 */
public static Node getByNum(Node head,int num){
    int k = getLength(head) - num;
    if (k < 0) {
        return new Node(-1,"k大於長度","-1");
    }
    Node temp = head.next;
    //判斷是否找不到
    boolean flag = false;
    while (true) {
        if (temp == null) {
            break;
        }
        if (k == 0) {
            flag = true;
            break;
        }
        k--;
        temp = temp.next;
    }
    if (!flag) {
        //越界了,k為負數
        return new Node(-1,"k為負數","-1");
    }
    return temp;
}

/**
 * 求單鏈表中有效節點的個數
 */
public static int getLength(Node head){
    int count = 0;
    Node temp = head.next;
    while (true) {
        if (temp == null) {
            break;
        }
        count++;
        temp = temp.next;
    }
    return count;
}
View Code

三、雙向連結串列

  原始碼:雙向連結串列

1,思路

準備
    1)首先定義node節點物件,存在next和pre兩個屬性
    2)採用DoubleLinkedList進行管理
    3)在DoubleLinkedList中定義head節點為new Node(-1,"","")
遍歷
    1)定義臨時節點temp=head.next
    2)while(temp!= null){temp=temp.next}遍歷並在其中列印temp
新增
    1)定義一個臨時節點temp記錄到最後的位置
    2)while(temp.next != null){temp=temp.next}移動指標
    3)設定temp.next=node(新增的節點),node.pre=temp(雙向關聯)
刪除(自我刪除)
    1)定義臨時節點temp=head.next(需要被刪除的節點),定義boolean flag為標識是否尋找到需要刪除的節點
    2)while(temp!= null){temp=temp.next}移動指標,判斷temp.no=no(輸入的節點id)為刪除節點,temp.pre.next=temp.next,如果temp.next不為空temp.next.pre=temp.pre,並修改flag為刪除
    3)判定 flag標識是否找到刪除節點
修改
    1)定義臨時節點temp=head.next,定義boolean flag為標識是否尋找到需要修改的節點
    2)while(temp!= null){temp=temp.next}移動指標,判斷temp.no==node.no(node為需要修改的節點),修改temp的屬性(或者修改next,pre指向),並修改flag為修改,break
    3)判定 flag標識是否找到修改節點,沒找到給出提示

2,程式碼

private DoubleNode head = new DoubleNode(-1, "", "");

/**
 * 刪除節點
 */
public void delete(int no) {
    if (no <= 0) {
        System.out.println("刪除節點的no不規範!!!");
        return;
    }
    DoubleNode temp = head.next;
    boolean flag = false;
    while (temp != null) {
        if (temp.no == no) {
            temp.pre.next = temp.next;
            if (temp.next != null) {
                temp.next.pre = temp.pre;
            }
            flag = true;
        }
        temp = temp.next;
    }

    if (!flag) {
        System.out.println("需要被刪除的節點不存在");
    }
}

/**
 * 修改節點
 */
public void update(DoubleNode node) {
    if (node == null || node.no <= 0) {
        System.out.println("被修改的節點不規範!!!");
        return;
    }
    DoubleNode temp = head.next;
    boolean flag = false;
    while (temp != null) {
        if (temp.no == node.no) {
            temp.name = node.name;
            temp.nickname = node.nickname;
            /*node.next = temp.next;
            node.pre = temp.pre;
            temp.pre.next = node;
            if (temp.next != null) {
                temp.next.pre = node;
            }*/
            flag = true;
        }
        temp = temp.next;
    }
    if (!flag) {
        System.out.println("找不到節點!!!");
    }
}

/**
 * 新增節點
 */
public void add(DoubleNode node) {
    DoubleNode temp = head;
    while (true) {
        if (temp.next == null) {
            break;
        }
        temp = temp.next;
    }
    temp.next = node;
    node.pre = temp;
}

/**
 * 遍歷節點
 */
public void list() {
    DoubleNode temp = head.next;
    while (true) {
        if (temp == null) {
            break;
        }
        System.out.println(temp);
        temp = temp.next;
    }
}
View Code

四、環形連結串列(約瑟夫問題)

  原始碼:環形連結串列

1,應用場景

  Josephu 問題為: 設編號為 1, 2, … n 的 n 個人圍坐一圈, 約定編號為 k(1<=k<=n) 的人從 1 開始報數, 數到 m 的那個人出列, 它的下一位又從 1 開始報數, 數到 m 的那個人又出列, 依次類推, 直到所有人出列為止, 由此產生一個出隊編號的序列。

2,建立環形連結串列

  思路

準備
    1)提前建立CircleNode物件為定義的節點
    2)定義CircleLinkedList為環形連結串列的管理類
    3)在CircleLinkedList中定義CircleNode first = null,定義連結串列的第一個節點
新增
    1)判定first==null,如果為空則是第一次新增,那麼first=node,並且node.next=first
    2)如果first節點不為空,定義temp=first節點,while(temp.next!=first){temp=temp.next}遍歷後移至first節點的前一個節點。
    3)將node節點加到temp節點後first節點前,temp.next=node並且node.next=first
遍歷
    1)定義temp=first,先列印first節點
    2)while(temp.next!=first){temp=temp.next}列印temp.next

  程式碼

/**
 * 遍歷
 */
public void show() {
    if (first == null) {
        System.out.println("當前連結串列為空連結串列!!!");
        return;
    }
    CircleNode temp = first;
    System.out.printf("當前編號為%d\n", first.no);
    while (temp.next != first) {
        System.out.printf("當前編號為%d\n", temp.next.no);
        temp = temp.next;
    }
}

/**
 * 初始化環形佇列
 */
public void init(int num) {
    if (num < 1) {
        System.out.println("初始化環形連結串列小於1,失敗!!!");
        return;
    }
    for (int i = 1; i <= num; i++) {
        CircleNode circleNode = new CircleNode(i);
        add(circleNode);
    }
}

/**
 * 新增node
 */
public void add(CircleNode node) {
    if (node == null) {
        System.out.println("需要新增的節點不存在!!!");
        return;
    }
    if (first == null) {
        first = node;
        node.next = first;
    }
    CircleNode temp = first;
    while (true) {
        if (temp.next == first) {
            break;
        }
        temp = temp.next;
    }
    temp.next = node;
    node.next = first;
}
View Code

3,出圈

  思路

1)獲取環形連結串列的總長度
2)定義出圈的方法需要接收step步長和start開始位置
3)定義cur=first需要出圈的節點,定義pre=first出圈的前一個節點while(pre.next!=first){pre=pre.next}
4)for迴圈start次,同時移動cur=cur.next和pre=pre.next
5)while(cur.next!=cur){...cur=cur.next}移動cur指標。在while迴圈中增加for迴圈step-1次,每次將pre和cur都後移,那麼移動完成之後設定pre.next=cur.next這樣就會去除cur
6)留存的就是最後的cur

  程式碼

/**
 * 出圈
 *
 * @param step  步長
 * @param start 開始的位置
 */
public void out(int step, int start) {
    int length = getLength();
    if (length < 1 || step < 1 || start > length) {
        System.out.println("引數不合規!");
        return;
    }
    //定義需要出圈的節點
    CircleNode cur = first;
    //需要出圈節點的前一個節點
    CircleNode pre = first;
    while (pre.next != first) {
        pre = pre.next;
    }
    //開始的位置
    for (int i = 0; i < start; i++) {
        pre = pre.next;
        cur = cur.next;
    }
    while (cur.next != cur) {
        for (int i = 0; i < step-1; i++) {
            pre = pre.next;
            cur = cur.next;
        }
        System.out.printf("出圈編號為:%d\n",cur.no);
        pre.next = cur.next;
        cur = cur.next;
    }
    System.out.printf("出圈編號為:%d\n",cur.no);
}

/**
 * 獲取環形連結串列的長度
 */
public int getLength() {
    if (first == null) {
        return 0;
    }
    int count = 1;
    CircleNode temp = first;
    while (temp.next != first) {
        count++;
        temp = temp.next;
    }
    return count;
}
View Code