2019年7月11日 星期四(數據結構和算法)

•對擁有C,C++,Java其它語言基礎的人員,強烈建議觀看c,c++,java版本的數據結構資料。

•數據結構的意義與重要性

•數據結構鏈表與隊列

•數據結構雙向鏈表與循環鏈表

•數據結構棧及其應用

•樹與二叉樹以及其應用

PHP數據結構和算法

1.數據結構的概念

數據結構就是研究數據的邏輯結構物理結構以及它們之間相互關係,並對這種結構定義相應的運算。

數據結構是計算機存儲、組織數據的方式及運算規則。

數據結構是指相互之間存在一種或多種特定關係的數據元素的集合。

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

2.物理存儲結構

1.順序存儲:把邏輯上相鄰的元素存儲在物理位置上也相鄰的存儲單元裏,元素之間的關係由存儲單元的鄰接關係來體現。一般適用於線性的數組和鏈表,對於非線性的樹和圖則不適合。

2.鏈接存儲:不要求邏輯上相鄰的元素在物理位置上也相鄰,藉助指示元素存儲地址的指針表示元素之間的邏輯關係。其優點是不會出現碎片現象,充分利用所有存儲單元;缺點是每個元素因存儲指針而佔用額外的存儲空間,並且只能實現順序存取。

3.索引存儲:在存儲元素信息的同時,還建立附加的索引表。索引表中的每一項稱爲索引項,索引項的一般形式是:(關鍵字,地址)。其優點是檢索速度快;缺點是增加了附加的索引表,會佔用較多的存儲空間。另外,在增加和刪除數據時要修改索引表,因而會花費較多的時間。

4.散列存儲:根據元素的關鍵字直接計算出該元素的存儲地址,又稱爲Hash存儲。其優點是檢索、增加和刪除結點的操作都很快;缺點是如果散列函數不好可能出現元素存儲單元的衝突,而解決衝突會增加時間和空間開銷。

3.時間複雜度

時間複雜度是一把直尺,用來度量程序執行的時間效率。

算法的時間複雜度通常有如下:

1.o(1)

2.o(logn)

3.o(n)

4.o(n^2)

5.o(n^k)

O(1) 常數階 < O(logn) 對數階 < O(n) 線性階 < O(nlogn) < O(n^2) 平方階 < O(n^3) < { O(2^n) < O(n!) < O(n^n) } 紅色算法複雜度不推薦,如果程序是如此高的複雜度,直接考慮換算法。

4.循環轉遞歸

任何時候循環可以實現的,都可以使用遞歸來實現。

function recursion($n,&$sum){
   for ($i=1; $i <=100 ; $i++){ 
       if($n==1){
           $sum++;
       }else{
           recursion($n-1,$sum);
       }
   }
}

輕鬆實現任意層循環。

5.時間複雜度

  1. a=a=a+b;b;b=aa-b;a=a=a-$b;

以上每條代碼頻率只有1,無論有多少條語句,時間複雜度都是o(1)

  1. $sum=0;

for(I=0;I=0;I<n;$I++)

sum+=sum+=I;

以上代碼運行次數爲2n+1,係數和+1都省略掉,時間複雜度爲o(n)

  1. $i=1;

​ while (i&lt;i&lt;n)

i=i=i*2;

時間複雜度爲o(log2n)

  1. $sum=0;                
    

​ for(i=0;i=0;i<n;n;i++)

​ for(j=0;j=0;j<n;n;j++)

​ $sum++;

時間複雜度爲 o(n^2)

6.空間複雜度

空間複雜度是對一個算法在運行過程中臨時佔用存儲空間(內存)大小的度量。

一個算法的空間複雜度包括算法程序所佔用的空間,同時還包含初始數據所佔用的空間以及算法執行過程中所需要的額外輔助空間。

(1)固定部分。主要包括指令空間(即代碼空間)、數據空間(常量、簡單變量)等所佔的空間。這部分屬於靜態空間。

(2)可變空間,這部分空間的主要包括動態分配的空間,以及遞歸棧所需的空間等。這部分的空間大小與算法有關。

7.時空轉換

用時間換空間,或者用空間來提升時間效率。

aa和b值互換程序。

a=11;a=11;b=13;

算法1: a=a=a+$b;

b=b=a-$b;

a=a=a-$b;

echo a..a.” ”.b;

算法2: $tmp = $b;

b=b=a;

a=a=tmp;

echo a..a.” ”.b;

寫程序的時候,如果內存不緊張的話,我們可以用空間來換時間。

8.數據結構三大特徵

在這裏插入圖片描述

9.程序是什麼?

程序 =?

程序=數據結構+算法

設計好數據結構,程序就等於成功了一半。

數據結構是程序設計的基石。

PHP 鏈表與隊列

1.鏈表的定義

•鏈表是一種物理存儲(內存)單元上非連續、非順序的存儲結構,數據元素的邏輯順序是通過對象引用來實現的。

•鏈表由一系列結點(鏈表中每一個元素稱爲結點)組成,結點可以在運行時動態生成。每個結點包括兩個部分:一個是存儲數據元素的數據域,另一個是存儲下一個結點的引用。

2.單鏈表

單鏈表有一個引用指向後續節點。

在這裏插入圖片描述
在這裏插入圖片描述

data爲數據,next爲指向下一個節點的引用

鏈表PHP模擬DEMO

class node{
	public $data;
	public $next;
}
class LinkList{
	public header;
	private size;
}	//操作函數getSize(),setHeader($v),__construct(),add($d)
//	   delete($d),update($old,$new),find($d),getAll()

3.雙向鏈表

雙向鏈表有兩個引用分別指向前後節點。優勢方便向前查詢數據。

在這裏插入圖片描述
在這裏插入圖片描述

data爲數據,pre爲指向前個節點的引用,next爲指向後個節點的引用。

鏈表PHP模擬DEMO

class node{
	public $data;
	public $prev;
	public $next;
}
class doubleLinkList{
	public header;
	private size;
}	//操作函數getSize(),setHeader($v),__construct(),add($d)
//	   delete($d),update($d),find($d),

4.循環鏈表

循環鏈表即單鏈表最後一個引用指向第一個節點。
在這裏插入圖片描述
在這裏插入圖片描述

約瑟夫環

聖夏彤 邴丹丹 臺浩邈 鮮依瑤 閃又青 威心遠 佛樂正 尋仙韻 別光華 柳舒蘭 
聞清婉 讓昕珏 出欣躍 慎詩丹 卿冬萱 拜若薇 黃夢秋 浮婭玟 駱飛章 劍成化 
平海榮 望凡霜 蔡雪萍 姓慧穎 秋訪夢 須盈秀 邰宣朗 林安彤 謬祺然 能駿琛 
湯香菱 查尋琴 乾問凝 冒聽筠 左詩蘭 市暄美 位水丹 裔翠芙 邗宏博 空永長 
進南霜 司空新雪 穆樂蓉 緒野雪 告天瑞 仁桂帆 齊珠雨 姒以冬 禽夏菡 呼延蘭英 
簡小雨 建彤蕊 偶迎南 南夏嵐 枝傲菡 羅蔚星 年博簡 夔代巧 戈曼蔓 赫麥冬 
光美如  戲柔惠 恭千秋 森寄蕾 亓嫺淑 豆飛瑤 菅爾容 齋依雲 荊紫杉 宦雪容 
酒含景 佔碧蓉 牽盼香 唐青雪 清映秋 瑞和璧 藍聽春 牛新潔 沐妙思 胥雍恬 
饒鴻光 丹樂然 抄曼吟 張廖智傑 府念雲 昔德宇 堯平安 尹芳澤 勤清妍 哀清瑩 
柴佩珍 夾谷昆琦 塔思琪 虞採萱 融水荷 招採萱 勢鴻志 次長嶽 費莫懷芹 始修真

n個小孩坐在一圈,每數到3就退出去,最後餘下的是誰?

用循環鏈表做。

$count = 1;
$list = $this->head;
while($list->next != $list){
    if($count%3==2){
        $list->next=$list->next->next;
    }else{
        $list=$list->next;
    }
    $count++;
}
echo $list->name;

5.數據結構隊列

•隊列是一種特殊的線性表(鏈表),特殊之處在於它只允許在表的前端(front)進行刪除操作,而在表的後端(rear)進行插入操作(FIFO),和棧一樣,隊列是一種操作受限制的線性表。進行插入操作的端稱爲隊尾,進行刪除操作的端稱爲隊頭。

•隊列中數據元素之間的關係是一對一的關係,即除了第一個和最後一個數據元素之外,其它數據元素都是首尾相接的。

在這裏插入圖片描述

隊列的PHP代碼

class node{
	public $data;
	public $next;
}	
class Queue{
	public $head;
	public $last;
	public $size;
}	//操作函數getSize(),__construct(),enqueue($d)
//	   dequeue(),getAll()

6.隊列的應用

•銀行排隊系統

•n個整數,最少選幾個數,使和不小於s (窮舉o(n^2),用隊列的o(n))

•在PHP中建議使用Spl庫SplQueue

PHP 棧使用

1.棧的概念

•棧(stack),它是一種運算受限的線性表。其限制是僅允許在表的一端進行插入和刪除運算。允許操作的一端被稱爲棧頂,相對地,把另一端稱爲棧底。向一個棧插入新元素又稱爲壓棧,它是把新元素放到棧頂元素的上面,使之成爲新的棧頂元素;從一個棧刪除元素被稱作出棧或退棧,就是把棧頂元素刪除掉,使其相鄰的下個元素成爲新的棧頂元素。
在這裏插入圖片描述

棧的PHP實現DEMO

1.定義node,設置屬性data,prev

2.定義stack類,設置棧頂top,size

3.編寫出棧push(),pop()函數

4.返回棧所有數據函數getAll()

5.最後我們使用棧來解決 匹配括號 應用

棧應用 進制轉換

•我們使用棧演示如下功能:

•十進制轉八進制

•十進制轉十六進制

棧應用 走迷宮

 /*     迷宮數組     1表示牆     0表示路     */  
    $maze = [ 
        [1,1,1,1,1,1,1,1,1,1],  
        [1,0,0,1,0,0,0,1,0,1],  
        [1,0,0,1,0,0,0,1,0,1],  
        [1,0,0,0,0,1,1,0,0,1],  
        [1,0,1,1,1,0,0,0,0,1],  
        [1,0,0,0,1,0,0,0,0,1],  
        [1,0,1,0,0,0,1,0,0,1],  
        [1,0,1,0,0,0,1,1,0,1],  
        [1,1,0,0,0,0,0,0,0,1],  
        [1,1,1,1,1,1,1,1,1,1],  
    ];

樹結構與二叉樹

1.樹的定義

•樹狀圖是一種數據結構,它是由n(n>=1)個有限節點組成一個具有層次關係的集合。把它叫做“樹”是因爲它看起來像一棵倒掛的樹,也就是說它是根朝上,而葉朝下的。
在這裏插入圖片描述

2.樹的相關述語

•結點:樹的結點包含一個數據元素和若干指向其子樹的分支

•結點的度(Degree):結點擁有的子樹。

•葉子結點(Leaf)/終端結點:度爲0的結點。

•分支結點/非終端結點:度不爲0的結點。

•內部結點:除根節點以外,分支結點也稱爲內部結點。

•樹的度:樹內各結點的度的最大值

在這裏插入圖片描述
在這裏插入圖片描述

3.結點之間的關係

•孩子(Child)和雙親(Parent):B 結點是A 結點的孩子,A結點是B 結點的雙親(注意是雙親,不是單親因爲雌雄同體,雙親既是父節點也是母節點,所以稱爲雙親)

•兄弟(sibling):同一個雙親的孩子之間互稱兄弟。

•結點的祖先:從根結點到該結點所經過分支上的所有結點。

•子孫:以某結點爲根的子樹中的任一結點都稱爲該節點的子孫。

•無序樹和有序樹:如果將樹中結點的各子樹看成從左至右是有次序的,不能互換的,則稱該數爲有序樹,否則爲無序樹。

•森林(forest):m(m>=0)棵互不相交樹的集合。
在這裏插入圖片描述

1.雙親表示法

以一組連續空間存儲樹的結點,同時在每個結點中,附設一個指示器指示其雙親結點到鏈表或數組中的位置。

2.孩子表示法

把每個結點的孩子結點排列起來,以單鏈表作爲存儲結構,則n個結點有n個孩子鏈表,如果是葉子結點則此單鏈表爲空。然後n個頭指針又組成一個線性表,採用順序存儲結構,存放進一個一維數組中。

3.雙親孩子表示法

比孩子表示法,多一個父親指針。

4.孩子兄弟表示法

1.任意一棵樹,它的結點的第一個孩子如果存在就是唯一的,它的右兄弟存在也是唯一的。因此,設置兩個指針,分別指向該結點的第一個孩子和此結點的右兄弟。

常用排序算法

排序算法

•冒泡排序(Bubble sort)

•選擇排序 ( Selection Sort )

•插入排序(Insertion sort)

•快速排序 ( Quick sort )

排序算法的穩定性

•假定在待排序的記錄序列中,存在多個具有相同的關鍵字的記錄,若經過排序,這些記錄的相對次序保持不變,即在原序列中,Ai=Aj,且Ai在Aj之前,而在排序後的序列中,Ai仍在Aj之前,則稱這種排序算法是穩定的;否則稱爲不穩定的。

•$arr = [ 9, 4, 6, 8, 17,12,44,12,56,71,21,19,81,99];

• 0 1 2 3 4 5 6 7 8 9 10 11 12 13

冒泡排序

•冒泡排序是一種簡單的排序算法。它重複地走訪過要排序的數列,一次比較兩個元素,如果它們的順序錯誤就把它們交換過來。走訪數列的工作是重複地進行直到沒有再需要交換,也就是說該數列已經排序完成。這個算法的名字由來是因爲越小的元素會經由交換慢慢“浮”到數列的頂端。

•特點,就是第一次的時候最大的元素到最後面。
在這裏插入圖片描述

選擇排序

•選擇排序(Selection-sort)是一種簡單直觀的排序算法。它的工作原理:首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然後,再從剩餘未排序元素中繼續尋找最小(大)元素,然後放到已排序序列的末尾。以此類推,直到所有元素均排序完畢。

插入排序

•插入排序(Insertion-Sort)的算法描述是一種簡單直觀的排序算法。它的工作原理是通過構建有序序列,對於未排序數據,在已排序序列中從後向前掃描,找到相應位置並插入。

快速排序

•快速排序的基本思想:通過一趟排序將待排記錄分隔成獨立的兩部分,其中一部分記錄的關鍵字均比另一部分的關鍵字小,則可分別對這兩部分記錄繼續進行排序,以達到整個序列有序。

排序算法

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章