技能篇-數(shù)據(jù)結(jié)構(gòu)和算法篇-基礎(chǔ)算法與結(jié)構(gòu)( 一 )

TZ:我們恐懼的往往不是黑暗,而是光明

一 : 科普一分鐘

什么是數(shù)據(jù)結(jié)構(gòu)和算法,二者有和聯(lián)系呢.
其實(shí)一種是數(shù)據(jù)存儲的方式,一種是一種實(shí)現(xiàn)功能的手段.
我最近經(jīng)常做飯,打個比方,就好比做菜一樣,我們所用的食材就是數(shù)據(jù)結(jié)構(gòu),我們做同樣的菜,食材有新鮮的有不新鮮的,肉質(zhì)有老的有嫩的,同樣算法好比廚師的廚藝,有高手和菜鳥,兩者的配合會產(chǎn)生各種奇妙的結(jié)果,所以算法和數(shù)據(jù)結(jié)構(gòu) 是程序的重要組成部分.

二 : 數(shù)據(jù)結(jié)構(gòu)簡述和舉例

1. 概述:何為數(shù)據(jù)結(jié)構(gòu)?

數(shù)據(jù)結(jié)構(gòu)其實(shí)就是計(jì)算機(jī)存儲,組織數(shù)據(jù)的方式.
相互之間存在一種或者多種特定關(guān)系的數(shù)據(jù)元素的集合

2. 常見的數(shù)據(jù)結(jié)構(gòu)有哪些?

大家都學(xué)過數(shù)據(jù)結(jié)構(gòu)這門課程,接下來我們來復(fù)習(xí)一下,我們都學(xué)過哪些數(shù)據(jù)結(jié)構(gòu).
(1) 線性表
包括我們常用的數(shù)組,鏈表,棧,和隊(duì)列.
(2)樹
(3)圖

3.常見的邏輯結(jié)構(gòu)

什么是邏輯結(jié)構(gòu)?個人理解就是有點(diǎn)"紙上談兵"的意思,類似于草圖或者說是思路結(jié)構(gòu)
(1)集合結(jié)構(gòu) : 把雜亂的數(shù)據(jù)放進(jìn)一個大鍋里.

集合結(jié)構(gòu).jpg

(2)線性結(jié)構(gòu) : 內(nèi)存是連續(xù)的,類似于"鐵索連環(huán)"

線性結(jié)構(gòu) .jpg

(3)樹形結(jié)構(gòu) : 這個結(jié)構(gòu)的特點(diǎn)就是....暫時理解像一顆樹就好了

樹形結(jié)構(gòu) .jpg

(4)圖形結(jié)構(gòu) : 這個結(jié)構(gòu)特點(diǎn)內(nèi)存可以是連續(xù)的 也可以是不連續(xù)的

圖形結(jié)構(gòu)

4.存儲結(jié)構(gòu)
說完了邏輯結(jié)構(gòu),我們說說存儲結(jié)構(gòu),
(1) 順序存儲結(jié)構(gòu)

順序存儲.jpg

(2)鏈?zhǔn)酱鎯Y(jié)構(gòu)

鏈?zhǔn)酱鎯Y(jié)構(gòu).jpg
  1. 隊(duì)列

假如此時我們做一個解密算法
把一個數(shù)據(jù)串 第一個數(shù)扔掉,第二個數(shù)放到尾部,第三個數(shù)扔掉,第四個數(shù)放到尾部.....等等, 刪掉的數(shù)按照移除順序就是我們要的結(jié)果 如何實(shí)現(xiàn)呢?

這其實(shí)就是隊(duì)列 ,隊(duì)列是先進(jìn)先出的,就好像我們排隊(duì)買票,先站排的人最先買到票,最先離開,好像兩頭開口的一個通道.

我們用head 來標(biāo)注 隊(duì)列頭 用tail 來標(biāo)注隊(duì)列尾部
注意 這里說的隊(duì)尾 是值 尾部后+ 1 的位置

#include <stdio.h>
int main()
 {
    int q[102] = {0,6,3,1,7,5,8,2,9,4},head,tail;
  //初始化隊(duì)列
head = 1;
tail = 10;

while(head < tail){

//打印隊(duì)首
printf("%d",q[head]);

//出隊(duì)
head ++

//將新隊(duì)首數(shù)添加到隊(duì)尾

q[tail] = q[head];
tail++;
//再次隊(duì)首移除出隊(duì)
head++
}

return 0;
 }

6.棧
簡單的說一下棧,我們吃的薯片或者彈夾,都類似棧,先進(jìn)后出.
現(xiàn)在我們做個簡單的小例子簡單分析一下
做一個判斷一個串 是否是回文
什么是回文, AABB ,ABBA ,ABCBA這種對稱的叫回文

我們用一個指向棧頂?shù)淖兞縯op

#include<stdio.h>
#include<string.h>
char a[101],s[101];
int i,len,mid,next,top;
gets(a)//讀入一個串
len = strlen(a);
mid = len/2 - 1;

top = 0;
//mid前面數(shù)一次入棧
for(i = 0; i <= mid ;i++){
s[++top] = a[i];

}
//判斷奇偶性
if(len%2 == 0)
  next = mid + 1;
else
 next = mid + 2;

//匹配
for(i = mext ; i<len-1;i++){
if(a[i] != s[stop])
breal;
top -- ;
}


if(top == 0){
printf("是回文");

}else{

printf("不是回文");
}
return 0;
  1. 鏈表
鏈表.jpg

每一個鏈表的節(jié)點(diǎn)有兩個部分組成,左邊的部分存放的是具體的數(shù)值,右邊存放的是下一個節(jié)點(diǎn)的地址.我們可以用一個結(jié)構(gòu)體來描述它

struct node{
int data;
struct node *next;
}

現(xiàn)在實(shí)現(xiàn) 插入某個數(shù)到序列里,簡單來說就是拆鏈和補(bǔ)鏈的過程.

#include <sdio.h>
#include <stdlib.h>
struct node{
int data;
struct node *next;
};

int main(){
 struct node *head,*p,*q,*t;
int i,n,a;
scanf("%d",&n);
head = NULL;//初始化
for(i = 1;i <= n;i++)
{
scanf("%d",&a);
//動態(tài)申請空間
p = (stuct node*)malloc(sizeof(stuct node));
p->data = a;//存放到當(dāng)前節(jié)點(diǎn)
p ->next = NULL;
if(head ==NULL){
  head = p;//創(chuàng)建第一個節(jié)點(diǎn)
}else{
    q->next= p;
}
q = p;


//輸入插入的數(shù)
scanf("%d",&a);
t = head;
while(t != NULL){
if(t->next ==NULL || t-> next->data > a){
 p = (struct node*)malloc(sizeof( struct node));
  //核心
 p->data = a;
p->next= t->next;
t->next = p;
break; 

}

t= t->next;

}
}


//輸出
t = head
while(t !=NULL){

printf("%d",t->data);
t= t->next;
}

return 0;
}

對于數(shù)據(jù)結(jié)構(gòu)和其存儲代碼只是簡單描述,日后慢慢講解.

三 : 算法簡述和常用基礎(chǔ)算法-排序

在工作中和學(xué)習(xí)中我們經(jīng)常聽到算法算法的,在上學(xué)的時候我們通常會學(xué)習(xí)算法這門單獨(dú)學(xué)科的課程,講的主要是,通過計(jì)算機(jī)語言編程解決一些和應(yīng)用題一樣的一些問題.

好,算法可以理解為是一種手段,或者一種解決方式,一系列的計(jì)算步驟,用來將輸入數(shù)據(jù)轉(zhuǎn)化為輸出結(jié)果

1.算法的意義

(1)用于解決特定的問題
(2)解決同一個問題的不同算法的效率常常相差很大,這種差距的影響往往比硬件和軟件方便的差距還要大.

2. 常用算法

(1)排序
(2)加密

3. 算法的優(yōu)劣

怎樣科學(xué)的評判一個算法的優(yōu)劣,算法那么重要,不同的算法會很大程度上影響運(yùn)行效率
時間復(fù)雜度 : 估算程序指令的執(zhí)行次數(shù)
空間復(fù)雜度 估算所需占用的存儲空間

這兩個的計(jì)算方式我們以后的博客仔細(xì)講解

4. 算法的優(yōu)化方向

(1)用盡量少的內(nèi)存空間
(2)用盡量少的執(zhí)行步驟
(3)空間換時間
(4)時間換空間

5. 排序算法

(1)桶排序

1965年有兩個大神, E.J IssacR.C Singleton 提出來的基本思想.
下面簡單總結(jié)一下這種算法的思想

#include <stdio.h>
int main()
{
int a[10] , i,j,t;
for (i = 0 ; i <= 10 ; i++)
{
//初始化一下數(shù)組
a[i] = 0;
};

//循環(huán)輸入7個數(shù) 對應(yīng)的數(shù)字放到對應(yīng)的桶中
for (int i = 0 ; i <7; i++ )
{
scanf("%d",&t);
a[t]++;
};

//輸出打印
for(i = 0; i<= 10;i++){
  for(j = 0;j <= a[i]; j++)
    printf("%d",i);//每個桶中的數(shù)出現(xiàn)幾次就打印幾次
};

return 0;
}

總結(jié)分析 : 這是一個簡化版的桶排序實(shí)際上桶排序要復(fù)雜很多這里就是和大家分析一下思路,下面畫一個圖來捋順一下

桶排序.jpg

每個桶的號碼就是存放自己的專屬數(shù)字,比如說1號桶專門存放的就是數(shù)字 1 5號桶專門存放 數(shù)組 5 初見幾次 就往對應(yīng)的桶里面 增加一次,也就是代碼中的 a[t]++;

可以看的出來這種算法需要的空間很大,也就是說,我們要準(zhǔn)備很多的 這點(diǎn)并不可取

接下來看看其時間復(fù)雜度O(M+N) (計(jì)算方式以后博客會說明)

(2)冒泡排序

1956 年就有人曾經(jīng)研究過冒泡排序,之后很多人研究改進(jìn)過,但結(jié)果都令人失望,正如 高德納 所說 冒泡排序除了它迷人的名字和導(dǎo)致了某些有趣的理論問題這一事實(shí)之外,似乎沒什么值得推薦的

#include <stdio.h>
int main(){

int a[100],i,j,t,n;
//輸入n 個數(shù)存放到數(shù)組 a中
for(i = 0 ; i <= n ; i++){
   scanf("%d",&a[i]);
};

//冒泡排序交換核心
for(i = 0 ; j <= n-1;i++){
   for(j = 1 ; j < n - i;j++)
     {
         if( a[j] < a[j+1] ){
               t = a[j]; a[j] = a[j+1]; a[j+1] = t;
            }
     }
}

//輸出結(jié)果 
for(i = 0 ;i <= n;i++){

printf("%d".a[i]);
}

return 0;
}

總結(jié) : 冒泡排序就是兩兩交互比較大小,核心代碼中的外層循環(huán) 是 走的 數(shù) 控制交換了幾趟,每一趟都能決定出一個最大的數(shù) 或者 最小的數(shù) ,為什么是 n-1 因?yàn)樽詈笠惶瞬挥门芤泊_定了,因?yàn)榫褪O履且粋€數(shù)了,同理內(nèi)層循環(huán) n - i 因?yàn)槊刻私粨Q 確定了一個數(shù) ,所以我們內(nèi)層循環(huán) 的時候 就要 排除那個已經(jīng) 確定的 數(shù).

接下來看看 冒泡排序時間復(fù)雜度 ->O(N2)

(3)快速排序

1960年 東尼霍爾 提出了快速排序 ,之后又有人做了優(yōu)化.

思路 : 簡單排序就是確定一個數(shù) 基數(shù)基數(shù)左邊的數(shù)小于基數(shù)(這里說的是遞增),讓基數(shù)右邊的數(shù)大于基數(shù),
然后再去基數(shù)左邊做同樣操作 ,基數(shù)右邊做同樣操作

接下來上圖來分析一下

快速排序.jpg

圖中 (1) 我們通常把首個數(shù)設(shè)置為基數(shù) 我們在序列左邊放了一個檢索 i 在 序列 右邊放了一個檢索 j 進(jìn)行檢索

當(dāng)i 發(fā)現(xiàn)了 比 '6' 大的數(shù)則停下,當(dāng) j 發(fā)現(xiàn)了 比 6 小的數(shù)則停下,然后 把發(fā)現(xiàn)的數(shù)交換位置 如圖(2)

交換完畢 i 和 j 繼續(xù)移動 如圖(3) 繼續(xù)交換 最后 i 和 j 相遇 檢索完畢

最后把 3 和 6 交換位置,以 6為基數(shù)的 檢索結(jié)束 ,接下來 6 左邊的數(shù) 和 6 右邊的數(shù)進(jìn)行 同理操作

#include <stdio.h>

int a[101],n;

//我們把排序封裝成方法 參數(shù) 分別是 左邊啟點(diǎn) 和 右邊啟點(diǎn)
void quicksort (int left,int right){
int i,j,t,temp;

if(left > right)
return;
};


temp = a[left];//確定基數(shù)
i = left;
j = right;
while(i != j){
//右邊先開始檢索
while( a[j] >= temp && i < j)
     j--;
}

//從左往右檢索
while( a[i] <= temp && i < j ){
  i++
}

//交換兩個數(shù)的位置
if( i < j) //沒有相遇
{
  t = a[i];
 a[i] = a[j];
a[j] = t;
}

}

//基數(shù)歸位

a[left] = a[i];
a[i] = temp;

quicksort(left,i-1);//處理基數(shù)左邊的
quicksort(i+1,right);//處理基數(shù)右邊的

return;
}

  int main()
 {
 int i,j;
//讀取數(shù)據(jù)
scanf("%d",&n);
for(i = 1;i < n;i++)
 scanf("%d",&a[1]);
}

//調(diào)用
quicksort(1,n);
//輸出
for(i = 1; i <= n ;i++){
   printf("%d", a[i]);
}

return 0;

總結(jié) : 為什么 j 要先移動,而 i 要后移動呢

因我我們把基數(shù)設(shè)置在了左邊,我們假設(shè)一種特殊情況,就是數(shù)據(jù)序列已經(jīng)是從小到大拍好了的,假如我們從左邊開始檢索,因?yàn)榛鶖?shù)在左邊,循環(huán)條件可訂貨滿足,所以,i 肯定移動到下一個,所以就發(fā)生了錯誤,所以我們要右j邊先移動.

四 : 總結(jié)

簡單的聊過了數(shù)據(jù)結(jié)構(gòu)和算法,一個好的程序,我們不僅要考慮它的運(yùn)行速度,也要配上好的數(shù)據(jù)結(jié)構(gòu),也就是數(shù)據(jù)的存儲方式,數(shù)據(jù)結(jié)構(gòu)往往配合著算法的使用 更佳炫酷.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末锦援,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子托慨,更是在濱河造成了極大的恐慌拘泞,老刑警劉巖攒驰,帶你破解...
    沈念sama閱讀 211,290評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件项戴,死亡現(xiàn)場離奇詭異宛裕,居然都是意外死亡穆碎,警方通過查閱死者的電腦和手機(jī)牙勘,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,107評論 2 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來所禀,“玉大人方面,你說我怎么就攤上這事∩牵” “怎么了恭金?”我有些...
    開封第一講書人閱讀 156,872評論 0 347
  • 文/不壞的土叔 我叫張陵,是天一觀的道長褂策。 經(jīng)常有香客問我横腿,道長,這世上最難降的妖魔是什么斤寂? 我笑而不...
    開封第一講書人閱讀 56,415評論 1 283
  • 正文 為了忘掉前任蔑水,我火速辦了婚禮,結(jié)果婚禮上扬蕊,老公的妹妹穿的比我還像新娘搀别。我一直安慰自己,他們只是感情好尾抑,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,453評論 6 385
  • 文/花漫 我一把揭開白布歇父。 她就那樣靜靜地躺著,像睡著了一般再愈。 火紅的嫁衣襯著肌膚如雪榜苫。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,784評論 1 290
  • 那天翎冲,我揣著相機(jī)與錄音垂睬,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛驹饺,可吹牛的內(nèi)容都是我干的钳枕。 我是一名探鬼主播,決...
    沈念sama閱讀 38,927評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼赏壹,長吁一口氣:“原來是場噩夢啊……” “哼鱼炒!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起蝌借,我...
    開封第一講書人閱讀 37,691評論 0 266
  • 序言:老撾萬榮一對情侶失蹤昔瞧,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后菩佑,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體自晰,經(jīng)...
    沈念sama閱讀 44,137評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,472評論 2 326
  • 正文 我和宋清朗相戀三年稍坯,在試婚紗的時候發(fā)現(xiàn)自己被綠了缀磕。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,622評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡劣光,死狀恐怖袜蚕,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情绢涡,我是刑警寧澤牲剃,帶...
    沈念sama閱讀 34,289評論 4 329
  • 正文 年R本政府宣布,位于F島的核電站雄可,受9級特大地震影響凿傅,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜数苫,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,887評論 3 312
  • 文/蒙蒙 一聪舒、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧虐急,春花似錦箱残、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至敬惦,卻和暖如春盼理,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背俄删。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工宏怔, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留奏路,地道東北人。 一個月前我還...
    沈念sama閱讀 46,316評論 2 360
  • 正文 我出身青樓臊诊,卻偏偏與公主長得像鸽粉,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子妨猩,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,490評論 2 348

推薦閱讀更多精彩內(nèi)容

  • 概述 排序有內(nèi)部排序和外部排序潜叛,內(nèi)部排序是數(shù)據(jù)記錄在內(nèi)存中進(jìn)行排序秽褒,而外部排序是因排序的數(shù)據(jù)很大壶硅,一次不能容納全部...
    蟻前閱讀 5,168評論 0 52
  • 概述:排序有內(nèi)部排序和外部排序,內(nèi)部排序是數(shù)據(jù)記錄在內(nèi)存中進(jìn)行排序销斟,而外部排序是因排序的數(shù)據(jù)很大庐椒,一次不能容納全部...
    每天刷兩次牙閱讀 3,729評論 0 15
  • 查找和排序都是程序設(shè)計(jì)中經(jīng)常用到的算法。查找相對而言較為簡單蚂踊,不外乎順序查找约谈、二分查找、哈希表查找和二叉排序樹查找...
    eagleRock閱讀 5,568評論 0 14
  • 9.3.3 快速排序 ??快速排序?qū)⒃瓟?shù)組劃分為兩個子數(shù)組犁钟,第一個子數(shù)組中元素小于等于某個邊界值棱诱,第二個子數(shù)組中的...
    RichardJieChen閱讀 1,839評論 0 3
  • 2017.5.19 1、早上戶外活動涝动、活動中我應(yīng)該屬于他燃型迈勋。 活動要求是集齊大家身上所有物品進(jìn)行連接、那組最長就...
    Iris_1987閱讀 176評論 0 0