人們進行程式設計時通常關注兩個重要問題,一是如何將待處理的資料儲存到計算機記憶體中,即資料表示;二是設計演算法操作這些資料,即資料處理。資料表示的本質是資料結構設計,資料處理的本質是演算法設計。pascal之父,瑞士著名計算機科學家沃思(niklaus wirth)教授曾提出:演算法+資料結構=程式。可以看出資料結構和演算法是程式的兩個重要組成部分,資料結構是指資料的邏輯結構和儲存方法,而演算法是指對資料的操作方法。盡快如c++的標準模板類stl已經設計好各種」輪子「,我們還是有必要了解輪子的構造的,這樣我們就具備了因地制宜的能力,根據具體場景選擇合適的資料結構和演算法去解決問題。
線性表按儲存方式可分為順序表和煉表。線性表的基本運算是指對線性表的操作,常見的包括:求長度、置空表、遍歷、查詢、修改、刪除、插入、排序等。此外還有複雜的運算,比如線性表的合併、反轉、求中值、刪除重複元素等。
順序表對應陣列,stl中vector也是這樣實現的。順序表的特點是元素按邏輯順序依次儲存在一塊連續的儲存空間中,故是一種隨機訪問結構。操作時間複雜度:查詢、修改、求長度o(1),插入、刪除、遍歷o(n)。
鍊錶包括單鏈表、迴圈鍊錶、雙向鍊錶和靜態鍊錶等。鍊錶採用動態儲存分配方式,需要時申請,不需要時釋放。操作時間複雜度:插入、刪除o(1),查詢、修改、遍歷、求長度o(n)。空間效能方面,順序表的儲存空間是靜態分配的,需提前確定其大小,更改的話容易造成浪費。適用於儲存規模確定,不經常變更或變更不大的場合;動態鍊錶是動態分配空間的,不容易溢位。適用於長度變化大的場合。但由於要儲存指標,故空間利用率較低。
c++的stl中有很多和線性表相關的容器,如向量(vector)、列表(list)等順序容器。
//使用容器,要包含標頭檔案
#includeusing std::vector;
//定義向量物件
vectorivec; //定義向量物件ivec
vectorivec1(ivec); //定義向量物件ivec1,並用ivec初始化
vectorivec2(n,i) ; //定義向量物件ivec2,包含n個值為i的元素
vectorivec3(n); //定義包含n個值為0的向量
vector::iterator it; //定義迭代器,模擬指標
vector> vivec; //定義二維向量,」>「之間要有空格
向量vector常用介面可參見向量vector常用介面,列表list的操作與向量相似,具體可參見列表list常用介面
棧(stack)是限定在尾部進行插入和刪除操作的線性表。允許插入和刪除操作的稱為棧頂(top),另一端稱為棧底(bottom)。因此,棧的操作是後進先出原則進行的。棧的基本運算包括:置空棧、入棧、出棧、取棧頂元素和判空。由於棧是受限的線性表,故可以由順序表和煉表來實現。
佇列也是受限的線性表。它只允許在一端插入,稱為隊尾(rear);另一端刪除,稱為對頭(front),在隊尾插入稱為入隊,對頭刪除稱為出隊。基本運算包括:置空隊、入隊、出隊、取隊頭和判隊空。它也可以由順序表或者鍊錶來實現。
串也稱字串,是由字元構成的有限序列。串中任意個連續字元構成的串稱為子串,原串稱為主串。字首子串指第乙個字元到某個字元構成的子串,字尾子串是某個字元到最後乙個字元構成的子串。串的基本操作包括:賦值、串連線、求長度、求子串、比較串大小、插入、修改、刪除等。串的模式匹配演算法包括樸素模式匹配演算法、kmp演算法和bm演算法等,需要研究一下。
此外,還有多維陣列和廣義表、樹(二叉樹、b-tree、紅黑樹等)和圖,這裡不做詳解,今後再做總結。
常見演算法有查詢和排序兩種,其中查詢是計算機資料處理經常用到的一種重要應用,當需要反覆在海量資料中查詢制定記錄時,查詢效率成為系統效能的關鍵。查詢演算法分為靜態查詢和動態查詢,其中靜態查詢包括:順序查詢、二分查詢和分塊查詢;動態查詢包括:二叉排序樹和平衡二叉樹。此外還有理論上最快的查詢技術——雜湊查詢。這裡只給出二分查詢的**。排序的目的是便於查詢,比如**號碼查詢、書的目錄編排、字典查詢等。常用的排序演算法有:插入排序、氣泡排序、堆排序、選擇排序和歸併排序等,它們的效能對比見下圖。
二分查詢又稱折半查詢,它要求待查序列按關鍵碼有序。它的基本思想是先確定待查記錄所在的區間,然後逐步縮小範圍直到找到或找不到該記錄為止。折半查詢要求線性表用順序表作為儲存結構,它特別需要注意的是邊界控制的問題。該演算法c++描述如下:
int search_bin(int a, int n, int target)//a[0]不用,a[1]~a[n]儲存資料
return 0;
}
直接插入排序的原理可模擬打牌時整理手中牌的過程,即不斷地將新來的元素插到有序序列的合適位置。它是一種穩定的排序演算法,特別適合於待排序序列基本有序的情況。該演算法c++描述如下:
void insertsort(int r,int n) //r[0]不用,n為元素個數
}
氣泡排序的方法是在待排序的元素中選擇兩個相鄰的元素進行比較,反序則交換,直至沒有反序為止。為了減少記錄的重複比較,這裡給出改進版的起泡排序,它是一種穩定的排序演算法。//普通版
void bubblesort(int r,int n)}}
}//改進版
void bubblesort(int r,int n)}}
}
快速排序是起泡排序的改進演算法,由於起泡排序是在相鄰位置進行的,故要比較移動多次才能到達目的地,而快排元素的比較和移動是從兩端向中間進行的,移動的距離比較遠,更靠近目的地,因此效率較高。
int partion(int r,int first,int end)
}}void heapsort(int r,int n)
}
歸併排序的基本思想是:將兩個或兩個以上的有序序列歸併成乙個有序序列.
//歸併兩個有序序列
void merge(int r,int r1,int s,int m,int t)
{ int i=s,j=m+1,k=s;
while(i<=m && j<=t)
{if(r[i]迄今為止,排序演算法還有很多。在常見的演算法中,就時間效能而言,在希爾排序、堆排序、快速排序和歸併排序演算法中,快速排序被認為是最快的一種,而在待排序元素個數比較多的情況下,歸併排序較堆排序更快。就穩定性而言,直接插入排序、氣泡排序和歸併排序是穩定的排序演算法,而簡單選擇排序、快排和堆排是不穩定的。元素較少時(n<50),可選擇直接插入排序或簡單選擇排序;元素初始狀態基本有序時,選擇直接插入排序或氣泡排序;元素較多時,選擇快排、堆排或者歸併,具體情況具體分析。
常用資料結構和排序演算法
在程式設計中,為了處理方便,把具有相同型別的若干 變數按有序的形式組織起來。這些按序排列的同類資料元素的集合稱為 陣列。在c語言中,陣列屬於構造資料型別。乙個陣列可以分解為多個陣列元素,這些陣列元素可以是基本資料型別或是構造型別。因此按陣列元素的型別不同,陣列又可分為數值陣列 字元陣列 指標陣列 結...
常用的資料結構和演算法
一,排序演算法 1.氣泡排序 2.選擇排序 3.插入排序 對於未排序的資料,在已排序列中從後向前找相應的位置插入 4.二分插入排序 插入排序的優化,通過二分法減少遍歷時間 5.希爾排序 先將要排序的序列分為若干子串行,在序列內分別直接插入排序,待整個分列基本有序時,在對全體 記錄進行直接插入排序 較...
資料結構常用演算法
將一整數序列中的所有負數轉移到所有正數之前 using system using system.collections.generic using system.linq using system.text namespace csharptest low while low high a low ...