【聲明】
歡迎轉載,但請保留文章原始出處→_→
生命壹號:http://www.cnblogs.com/smyhvae/
文章來源:http://www.cnblogs.com/smyhvae/p/4724692.html
一、數據結構涵蓋的內容:
二、算法的基本概念:
1、算法的概念:
Algorithm,是對特定問題求解步驟的一種描述,它是指令的有限序列,其中每一條指令表示一個或者多個操作。
2、算法的特性:
- 有窮性:指令序列是有限的
- 確定性:每條語句的含義明確,無二義性
- 可行性:每條語句都應在有限的時間內完成
- 輸入:零個或者多個輸入
- 輸出:一個或者多個輸出
3、算法與程序的區別:
程序:
(program)程序是軟件開發人員根據用戶需求開發的、用程序設計語言描述的適合計算機執行的指令(語句)序列。
程序包含的四個要素:
數據結構
算法
程序設計方法
編程語言
程序與算法不同。程序是算法用某種程序設計語言的具體實現。程序可以不滿足算法的有窮性,比如操作系統也是一種程序,如果你願意,你的電腦可以一直開着,保持操作系統的運行。
比如:
while(true) { ... } //是一段程序,但不是一個算法
4、程序、算法、軟件之間的關系:
程序:算法的計算機實現。用某種編程語言實現。
算法:表示問題的解。
軟件:程序+文檔
如下圖所示:
程序設計=數據結構+算 法
三、數據類型:
1、數據類型:
是指一個值的集合和定義在集合上的操作集合。例如:java的整數類型(Integer),就不僅僅表示整數數值的集合,還包括對整數類型進行的操作集合,加、減、乘、除、模等操作。
我們通常所指的數據類型是某種高級語言支持的基本數據類型。 比如java的基本數據類型:int、double、float、char等等。
Java中的數據類型:
2、抽象數據類型:
一個數學模型以及定義在這個模型上的一組操作(由用戶定義,用以表示應用問題的數據模型)。
看起來抽象數據類型和數據類型的定義基本相同。不同點在於:數據類型通常是指某種高級語言的,而抽象數據類型用戶重新設計,一種概念。這里的"抽象"的含義在於數學抽象。
- 原子類型:比如整型
- 固定聚合類型:比如復數,兩個實數確定的次序構成
- 可變聚合類型:比如汽車類型,構成的成分是不確定的。(因為小轎車、大卡車的構成是不同的)
抽象數據類型抽象的層次越高,那么可復用性也越高。比如:java中的Object是對所有對象的抽象,那么就可以作為所有類的父類。
四、抽象數據類型的表示(代碼舉例):
- C語言使用結構體
- Java語言使用類
下面分別用C語言與java語言,來定義學生抽象數據類型。已知學生的信息如下:
學號:111222 姓名:生命壹號 性別:男 出生日期:1991-11 專業:電子與通信工程(計算機方向) 電子郵箱:smyhvae@163.com
1、用C代碼定義一個學生類:
test1.c:
#include <stdio.h> //日期結構體 typedef struct { int year;//年 int month;//月 int day;//日 }Date; //學生結構體 typedef struct { char sid[20];//學號 char name[20];//姓名 char gender;//性別 Date birthday;//出生日期 char contact[50];//聯系方式 }Students; void PrintStudentsInfo(Students s) { printf("學號:%s\n",s.sid); printf("姓名:%s\n",s.name); printf("性別:%c\n",s.gender); printf("出生日期:%d-%d-%d\n",s.birthday.year,s.birthday.month,s.birthday.day); printf("聯系方式:%s\n",s.contact); } int main() { Students s1;//生成一個學生對象 Date d1; d1.year = 1995; d1.month = 6; d1.day =30; strcpy(s1.sid,"S0001"); strcpy(s1.name,"張三豐"); strcpy(s1.contact,"西安市高新四路50號"); s1.gender = 'M'; s1.birthday = d1; PrintStudentsInfo(s1); getch(); return 0; }
運行效果:
2、用Java代碼定義一個學生類:
(1)Student.java:
1 package test1; 2 3 import java.text.SimpleDateFormat; 4 import java.util.Date; 5 6 /** 7 * Created by smyhvae on 2015/8/12. 8 */ 9 public class Student { 10 String num; //學號 11 String name; //姓名 12 char sex; //性別 13 Date birthday; //出生日期 14 String contact; //聯系方式 15 16 public String getNum() { 17 return num; 18 } 19 20 public void setNum(String num) { 21 this.num = num; 22 } 23 24 public String getName() { 25 return name; 26 } 27 28 public void setName(String name) { 29 this.name = name; 30 } 31 32 public char getSex() { 33 return sex; 34 } 35 36 public void setSex(char sex) { 37 this.sex = sex; 38 } 39 40 public Date getBirthday() { 41 return birthday; 42 } 43 44 public void setBirthday(Date birthday) { 45 this.birthday = birthday; 46 } 47 48 public String getContact() { 49 return contact; 50 } 51 52 public void setContact(String contact) { 53 this.contact = contact; 54 } 55 56 @Override 57 public String toString() { 58 59 SimpleDateFormat sdf = new SimpleDateFormat("YYYY-mm-dd"); //將Date日期轉化為String字符串打印出來 60 61 return "Student{" + 62 "num='" + num + '\'' + 63 ", name='" + name + '\'' + 64 ", sex=" + sex + 65 ", birthday=" + sdf.format(birthday) + 66 ", contact='" + contact + '\'' + 67 '}'; 68 } 69 70 }
(2)JavaTest.java:(給學生類賦值並打印出來)
1 package test1; 2 3 import java.text.ParseException; 4 import java.util.Calendar; 5 import java.util.Date; 6 7 /** 8 * Created by smyhvae on 2015/8/12. 9 */ 10 public class JavaTest { 11 12 public static void main(String[] args) throws ParseException { 13 14 Student s = new Student(); 15 s.setNum("111222"); 16 s.setName("生命壹號"); 17 s.setSex('男'); //這里面賦值可以用中文 18 s.setContact("smyhvae@163.com"); 19 20 Calendar calendar = Calendar.getInstance(); 21 calendar.set(1991, 11, 28); 22 Date date = calendar.getTime(); 23 s.setBirthday(date); 24 25 System.out.println(s.toString()); 26 27 } 28 29 }
運行效果如下:
五、算法的設計目標:
1、算法的設計目標:
(1)正確性:滿足具體問題的解,基本目標。
(2)可讀性:有利於人去理解算法。
(3)健壯性:輸入非法數據,能適當做出處理,不產生莫名其妙的輸出。
(4)高效性:包括時間的高效性(時間復雜度)和空間的高效性(空間復雜度)。
2、算法性能指標:
(1)算法的時間效率也稱為時間復雜度。
(2)算法的空間效率也稱為空間復雜度。
(3)同一問題可用不同算法解決,而一個算法的質量優劣將影響到算法乃至程序的效率。算法分析的目的在於選擇合適算法和改進算法。一個算法的評價主要從時間復雜度和空間復雜度來考慮。
(4)算法時間的高效性和空間的高效性通常是矛盾的。所有一般只會取一個平衡點。(這里體現的是一種哲學思想,研究計算機,不就是研究時間和空間的概念嘛,魚與熊掌不可兼得哦)
(5)通常我們假設程序運行在內存中,且內存容量足夠使用,所以更多的是討論時間復雜度。
六、算法的時間復雜度:
算法的時間復雜度反映了算法執行的時間長短。度量一個算法在計算機上執行的時間通常有兩種方式:
1.事后統計法:
2.事前分析法:(常用)
編寫算法使用的高級語言
編程產生的機器語言代碼質量
機器指令執行速度
問題規模
注:算法的時間復雜度是由最深層嵌套語句的頻度決定的。
2、O()函數:
表示算法的時間效率與算法所處理的數據元素個數n函數關系的最常用函數,即O()函數。
定義:
一般情況下,算法中基本操作重復執行的次數是問題規模n的某個函數,用T(n)表示,若有某個輔助函數f(n),使得當n趨近於無窮大時,T(n)/f(n)的極限值為不等於零的常數,則稱f(n)是T(n)的同數量級函數。記作T(n)=O(f(n)),稱O(f(n)) 為算法的漸進時間復雜度,簡稱時間復雜度。看下圖便知:
情況一:T(n)與問題規模n無關
當算法的時間復雜度T(n)與問題規模n無關時,此時算法的時間復雜度T(n)=O(1)。
情況二:T(n)與問題規模n有關
例1:設數組a和b在前面部分已經賦值,求如下兩個n階矩陣相乘算法的時間復雜度:
for(i=0;i<n;i++) { for(j=0;j<n;j++) { c[i][j]=0; //基本語句1 for(k=0;k<n;k++) { c[i][j]=c[i][j]+a[i][k]*b[k][j];//基本語句2 } } }
上方代碼中:
例2:設n為如下算法處理的數據元素個數,求算法時間復雜度。代碼如下:
for(i=1;i<=n;i=i*2) { System.out.println(i); }
分析:
例3:分析冒泡排序算法的時間復雜度。代碼如下:
//冒泡排序算法 public static void bubbleSort(int[] data) { if (data == null) { return; } for (int i = 0; i < data.length - 1; i++) { boolean flag = false;
for (int j = 0; j < data.length - 1 - i; j++) { if (data[j] > data[j + 1]) { int temp = data[j]; data[j] = data[j + 1]; data[j + 1] = temp; flag = true; } }
if (!flag) { return; } } }
時間復雜度分析:
(1)最佳情況下,冒泡排序算法只需要遍歷一次就能確定數組已經排序好了,此時的時間復雜度為O(n);
(2)最差情況下,需要進行n-1次遍歷,則需進行n(n-1)/2次比較和記錄移動,此時冒泡排序算法的時間復雜度T(n)=O(n2)。
3、時間復雜度的大小關系:
以下六種計算算法時間的多項式是最常用的。其關系為:
指數時間的關系為:
當n取很大的值時,指數時間算法和多項式時間算法在所需時間上非常懸殊。
小知識:
NP(nondeterministic polynomial)難問題:是指算法復雜度難以用多項式表示的問題,算法復雜度通常是n的指數級,常規算法很難求解。
七、算法的空間復雜度:
空間復雜度是指算法在運行期間所需要的內存空間的數量級。記作:S(n)=O(f(n)),其中n為問題的規模(或大小)。
注:由於大部分算法的空間復雜度問題並不嚴重,並且算法的空間復雜度分析方法和算法的時間復雜度分析方法基本相同,所以一般數據結構只討論算法的時間復雜度,不討論算法的空間復雜度。
代碼舉例:分析如下算法的空間復雜度
static void reserse(int[] a,int[] b) { int n= a.length; for(int i=0;i<n;i++) { b[i]=a[n-1-i]; } }
上方代碼中,當程序調用reserse(a,b)函數時,要分配的內存空間包括:引用a,引用b,局部變量n和局部變量i;
因此f(n)=c;其中c為常量。所以該算法的空間復雜度S(n)=O(1)。
八、總結:
算法的時間復雜度和兩個因素有關:算法中的最大嵌套循環層數;最大嵌套循環結構中每次循環的次數。
一般來說,具有多項式時間復雜度的算法是可以接受的;具有指數(不是對數)時間復雜度的算法,只有當n足夠小時才可以使用。一般效率較好的算法要控制在O(N)或者O(log2 N)
手有玫瑰,贈人余香。支付寶掃一掃吧: