最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

【郝斌】-數(shù)據(jù)結(jié)構(gòu)入門

2021-08-13 08:31 作者:zhangruiwen119  | 我要投稿

數(shù)據(jù)結(jié)構(gòu)概述:

定義:如何把現(xiàn)實(shí)中大量而復(fù)雜的問題以特定的數(shù)據(jù)類型(個(gè)體)和特定的數(shù)據(jù)結(jié)構(gòu)(個(gè)體之間關(guān)系)保存到儲(chǔ)存器(內(nèi)存)中,并在此基礎(chǔ)上為實(shí)現(xiàn)某個(gè)功能(比如查找/刪除/排序)而執(zhí)行的相應(yīng)操作(又叫算法)。

常見數(shù)據(jù)結(jié)構(gòu):

鏈表

圖(任意節(jié)點(diǎn)都和其它節(jié)點(diǎn)聯(lián)系


數(shù)據(jù)結(jié)構(gòu)=個(gè)體+個(gè)體的關(guān)系

算法=對(duì)存儲(chǔ)數(shù)據(jù)的操作


算法(解題的方法和步驟


衡量算法的標(biāo)準(zhǔn)

1.時(shí)間復(fù)雜度

大概需要執(zhí)行的次數(shù)(非時(shí)間)(機(jī)器計(jì)算能力的不同


2.空間復(fù)雜度

算法執(zhí)行過程中大概所占用的最大內(nèi)存


3.難易程度(可讀性


4.健壯性(輸入非法時(shí)也能做出正確反應(yīng)


數(shù)據(jù)結(jié)構(gòu)的地位:軟件中最核心的課程


程序=數(shù)據(jù)的存儲(chǔ)+數(shù)據(jù)的操作+可以被計(jì)算機(jī)執(zhí)行的語言


預(yù)備知識(shí):

指針

定義:

地址:

內(nèi)存單元的編號(hào)(從0開始的非負(fù)整數(shù)

范圍:0—FFFFFFFF(4G-1的內(nèi)存大小

指針:指針《==》地址

指針變量是存放內(nèi)存單元地址的變量

指針的本質(zhì)是一個(gè)操作受限的非負(fù)整數(shù)

分類:

1.基本類型的指針


2.


注意:1.指針變量只能存放內(nèi)存單元地址,而非內(nèi)容

void f(int *p)//定義了一個(gè)形參,名字叫P,類型為int*;

a[3]=*(3+a);

printf("%p\n",a+3) 16進(jìn)制輸出,等價(jià)于輸出該對(duì)應(yīng)地址 printf("%p/n",*a+3) <==>輸出a[0]+3這個(gè)數(shù)對(duì)應(yīng)的地址




***:指針變量不論指向的變量占多少字節(jié),本身只占四個(gè)。


結(jié)構(gòu)體:

為什么會(huì)出現(xiàn)結(jié)構(gòu)體:為了表示某些復(fù)雜的數(shù)據(jù),而普通的基本類型變量無法滿足需求


什么是結(jié)構(gòu)體:用戶根據(jù)實(shí)際需要自行定義的復(fù)合數(shù)據(jù)類型

如何使用結(jié)構(gòu)體

struct stduent

{

};

int main()

{

struct student st={ , , };

}

int main()

{

struct student *pst=&st;

pst->sid=99;(等價(jià)于 (*pst)。sid ,pst所指向的結(jié)構(gòu)體變量中的sid這個(gè)成員

}

注意事項(xiàng)

結(jié)構(gòu)體變量不能加減乘除,只能相互賦值;

普通結(jié)構(gòu)體變量和結(jié)構(gòu)體指針變量作為函數(shù)傳參的問題

例:

int main()

{

gst(st);

gst1(&st);

}

void g(struct studenct st)

{

……;

}

void g1(struct studenct *st)

{

……;

}


將主函數(shù)中的所有東西全部賦值到函數(shù)g中,浪費(fèi)空間和內(nèi)存,沒有使用指針g1方便


動(dòng)態(tài)內(nèi)存的分配與釋放:

動(dòng)態(tài)構(gòu)建一維數(shù)組

int main ()

{

int len;

scanf("%d",&len);

int *pArr=(int *)malloc(sizeof(int) *len);

//(int *):強(qiáng)制轉(zhuǎn)換 動(dòng)態(tài)數(shù)組第一個(gè)字節(jié)地址(干地址,無實(shí)際意義),以確定數(shù)組的類型(即所占地址/字節(jié)數(shù)


free(pArr);//把pArr所代表的動(dòng)態(tài)分配的內(nèi)存釋放;

}

**跨函數(shù)申請(qǐng)內(nèi)存只能通過動(dòng)態(tài)申請(qǐng)內(nèi)存實(shí)現(xiàn)(但是要記得釋放)

例:

#include <stdio.h>

int main()

{

int *p;

fun(&p);

}

int fun(int **q)

{

*q= (int *) malloc (sizeof(int));

}


模塊一:線性結(jié)構(gòu)【把所有的結(jié)點(diǎn)(類似于數(shù)組的元素)用一根直線穿起來】

連續(xù)儲(chǔ)存【數(shù)組】

1.什么叫數(shù)組:

元素類型相同,大小相等

2.數(shù)組的優(yōu)缺點(diǎn)(與鏈表相比較):

優(yōu):①:存取速度快(可通過下標(biāo)查找

缺:①事先必須知道數(shù)組的長(zhǎng)度

②:插入刪除元素慢

③容易受到空間的限制

④:需要大塊連續(xù)的內(nèi)存塊

樣例

#include <stdio.h>

#include <stdlib.h>//包含exit函數(shù)

#include <malloc.h>//包含malloc函數(shù)

//定義了一個(gè)數(shù)據(jù)類型,該數(shù)據(jù)類型名字叫struct Arr,該數(shù)據(jù)類型含有三個(gè)成員,分別是*pbase……,沒有定義變量

struct Arr

{

int *pBase;//存儲(chǔ)數(shù)組元素中第一個(gè)元素的地址

int len;//數(shù)組所能容納的最多元素的個(gè)數(shù)

int cnt;//當(dāng)前數(shù)組有效元素的個(gè)數(shù)

};

void init_arr(struct Arr *pArr,int length);初始化

bool append_arr(struct Arr *pArr,int val);//追加(注意數(shù)組滿了不能放入)

bool insert_arr(struct Arr *pArr,int pos;int val);//插入到第pos個(gè)數(shù) ,pos的值從1開始 表示下標(biāo)為0的

bool delete_arr(struct Arr *pArr,int pos;int val);

int get();

bool is_empty(strcut Arr *pArr);//判數(shù)組是否為空

bool is_full();//判斷數(shù)組是否滿了

void sort_arr(strcut Arr *pArr);//排序

void show_arr(strcut Arr *pArr);//輸出

void inversion_arr(strcut Arr *pArr);//倒置

find_val_arr();

deleteAll(4);

int main()

{

struct Arr arr;//粗體只是定義數(shù)據(jù)類型,此時(shí)數(shù)組內(nèi)元素為垃圾值,定義arr才是變量

int val;

init_arr(&arr,6);//

show_arr(&arr);

append(&arr,1);

if (delete_arr(&arr,1,&val))

printf("刪除成功!\n");

return 0;

}

void init_arr(struct Arr *pArr,int length)

{

pArr->pBase=(int *) malloc(sizeof(int)*length);

//判斷分配地址是否成功

if (NULL ==pAee->pBase)

{

//內(nèi)存分布失敗

exit(-1);

}

array.len=99;

}

void show_arr(strcut Arr *pArr)

{

if is_empty(pArr)//此處pArr已經(jīng)是arr地址,不可以加取地址符使得另一函數(shù)調(diào)用現(xiàn)在的*pArr的地址

printf("是空數(shù)組\n“);

else for (int i=0;i<=pArr->cnt;i++)

{

pritnf("%d ", pArr->pBase[i]);

}

printf("\n");

}

bool is_empty(strcut Arr *pArr)

{

if (pArr->cnt==0)

return 1;//true

else return 0;//false

}

bool is_full(struct Arr *pArr)

{

if (pArr->cnt==pArr->len)

return 1;//true

else return 0;//false

}

bool append_arr(struct Arr *pArr,int val)

{

if (is_full(pArr)==1)

return 0;//數(shù)組滿了false

else //不滿時(shí)追加

{

pArr->pBase[pArr->cnt]=val;

pArr->cnt)++;

return true;

}

}

bool insert_arr(struct Arr *pArr,int pos;int val)

{

if (is->full(pArr))

return false;

if (pos<1||pos>=pArr->cnt+1)//超出容量

return false;

for (i=pArr->cnt-1;i>=pos-1;i--);

{

pArr->pBase[i]=pArr->pBase[i+1];

}

pArr->pBase[pos-1]=val;

return 1;//true

}

bool delete_arr(struct Arr *pArr,int pos;int *pVal);

{

if (is_empty(pArr))

return 0;//false

if (pos<1||pos>pArr->cnt)

return 0;//false

???//*pVal=pArr->pBase[pos-1];//刪除成功時(shí)返回被刪除的數(shù)據(jù) 以便撤回

for (i=pos;i<pArr->cnt;i++)

{

pArr->pBase[i]=pArr->pBase[i-1];

}

pArr->cnt --;

}

void inversion_arr(strcut Arr *pArr);//倒置

{

int i=0;

int j=pArr->cnt-1;

while (i<j)

{

t=pArr->pBase[j];

pArr->pBase[i]=pArr->pBase[j];

i++;

j--;

}

}

void sort_arr(st ruct Arr*pArr)(冒泡)

{

int i,j,t ;

for (i=0; i<pArr->cnt ; ++i)

{

for (j=i+1; j<pArr->cnt ; ++j)

{

if (pArr->pBase[i] > pArr->pBaso[j])

{

t = pArr->pBase[i] ;

pArr-> pBase[i]=pArr>pBase[j];

pArr->pBase[j][ = t ;

}

}

}


離散存儲(chǔ)【鏈表】

# include <stdio. h>

typedef int ZHANGSAN; //為int再重新多取一個(gè)名字,ZHANGSAN等價(jià)于int

typedef struct Student

{

int sid;

char name [100] ;

char sex;

}ST;//除ST外相當(dāng)于已有的一個(gè)數(shù)據(jù)類型(類似int

ST是為該數(shù)據(jù)類型重新取得名字

int main(void)

{

int i =10; //等價(jià)于 ZHANGSANi=10;

ZHANGSAN j=20;

printf("%d\n", j);

struct Student st ;

struct Student *ps = st ;return 0;

}

若ST換成*PST

一直到*位置都是一個(gè)數(shù)據(jù)類型 使得PST成為指針


typedef struct Student

{

int sid;

char name [100] ;

char sex;

}*PST;

int main(void)

{

struct Student st ;

PST ps=&st;

ps->sid=99;

}

若PSTU后跟上STU

typedef struct Student

{

int sid;

char name [100] ;

char sex;

}*PSTU,STU;//等價(jià)ST代表struct student,

PST代表struct Student*

int main(void)

{

STU st ;

PSTU ps=&st;

ps->sid=99;

}


離散存儲(chǔ)(鏈表)

離散:各個(gè)結(jié)點(diǎn)之間有可以被計(jì)算出的間距

定義:①n個(gè)節(jié)點(diǎn)離散分配②彼此通過指針相連③每個(gè)節(jié)點(diǎn)有且只有一個(gè)前驅(qū)和后繼節(jié)點(diǎn),首無前驅(qū),尾無后驅(qū))

優(yōu)點(diǎn):①空間沒有限制②插入刪除元素快

缺點(diǎn):存取數(shù)據(jù)速度慢

專業(yè)術(shù)語:

有效節(jié)點(diǎn):存放有效數(shù)據(jù)的節(jié)點(diǎn)

首節(jié)點(diǎn):第一個(gè)有效節(jié)點(diǎn)

尾節(jié)點(diǎn):最后一個(gè)有效節(jié)點(diǎn)

頭結(jié)點(diǎn):鏈表中在首節(jié)點(diǎn)前加一個(gè)沒有有效數(shù)據(jù)的節(jié)點(diǎn),主要是方便對(duì)鏈表的操作,其數(shù)據(jù)類型和首節(jié)點(diǎn)一致

頭指針:指向頭節(jié)點(diǎn)的指針變量

尾指針:指向尾節(jié)點(diǎn)的指針變量

如果希望通過一個(gè)函數(shù)來對(duì)鏈表進(jìn)行處理,我們至少需要知道鏈表的哪些參數(shù):

頭指針 ***(通過頭指針可以推算出鏈表的其他所有信息

(不是頭結(jié)點(diǎn) 是因?yàn)楸苊獠僮鲿r(shí)結(jié)點(diǎn)內(nèi)數(shù)據(jù)較多

(首節(jié)點(diǎn)非必須,可由頭節(jié)點(diǎn)退出;

長(zhǎng)度非必須,可以通過循環(huán)查找結(jié)點(diǎn)為NULL時(shí)的結(jié)點(diǎn) ++即為長(zhǎng)度)


鏈表的創(chuàng)建

#include <stdio.h>

#include <stdlib.h>?

#include <malloc.h>

typedef struct Node

{

??int data;//數(shù)據(jù)域

??struct Node *pNext;//指針域

}NODE,*PNODE;?


//NODE 等價(jià)于struct Node,PNODE 等價(jià)于struct Node*

PNODE create_list(void);

void traverse_list(PNODE pHead);//遍歷

bool is_empty(PNODE pHead);

int length_list(PNODE pHead);

void sort_list(PNODE pHead);?

bool delete_list(PNODE pHead,int pos,int *pval);

bool insert_list(PNODE pHead,int pos,int val);

int main()

{??

??int val;

??PNODE pHead = NULL;?

??//等價(jià)于struct Node * pHead = NULL;

??pHead = create_list();?//功能:創(chuàng)建一個(gè)非循環(huán)單鏈表,將該鏈表的頭結(jié)點(diǎn)地址賦值給pHead

??traverse_list (pHead) ;//遍歷

??insert_list(pHead,4,-33);//

??if (is_empty(pHead))

????printf("鏈表為空\(chéng)n");

??else printf("鏈表不空\(chéng)n");

??int?len=length_list(pHead);;

??printf("鏈表的長(zhǎng)度是%d\n",len);

??traverse_list(pHead);//遍歷

??sort_list(pHead);//排序

??traverse_list(pHead);//檢驗(yàn)遍歷是否成功

??if (delete_list(pHead,4,&val) )

????printf("刪除成功,您刪除的元素是:%d\n", val) ;

??else

????printf("刪除失敗!您刪除的元素不存在\n") ;

??return 0;

}

PNODE create_list()

{

????int len;///提示輸入鏈表的長(zhǎng)度

????int i;

????int val;//臨時(shí)存放用戶輸入節(jié)點(diǎn)的值

????//分配一個(gè)不存放有效數(shù)據(jù)的頭節(jié)點(diǎn)

????PNODE?pHead =(PNODE)malloc (sizeof(NODE));

????if (NULL==pHead)

????{

??????printf("分配失敗\n");

??????exit(-1);

????}

????PNODE pTail = pHead;

????pTail->pNext = NULL;//在用戶輸入0時(shí)清空指針域避免出現(xiàn)問題

????printf("輸入鏈表的節(jié)點(diǎn)個(gè)數(shù):len=");

????scanf("%d",&len);

????printf("\n");

????for (i=0;i<len;i++)

????{

??????printf("請(qǐng)輸入第%d個(gè)節(jié)點(diǎn)的值:",i+1);?

??????scanf("%d",&val);

??????PNODE?pNew =(PNODE)malloc (sizeof(NODE));

??????if (NULL==pNew)

??????{

????????printf("分配失敗\n");

????????exit(-1);

??????}

??????//使得pnew永遠(yuǎn)指向尾節(jié)點(diǎn)

??????pNew->data = val;

??????pTail->pNext =pNew;

??????pNew->pNext = NULL;

??????pTail = pNew;

????}

????return pHead;

}


void traverse_list(PNODE pHead)//遍歷

{

??//定義指針p,指向頭結(jié)點(diǎn)指針域(第一個(gè)有效節(jié)點(diǎn)),非空則繼續(xù),空則輸出??

??PNODE p=pHead->pNext;

??while (p!=NULL)

??{

????printf("%d ",p->data);

????p=p->pNext;

??}

??printf("\n");

}

bool is_empty(PNODE pHead)

{

??if (pHead->pNext==NULL)

????return 1;

??else return 0;?

}


int length_list(PNODE pHead)

{

????PNODE p=pHead->pNext;

????int len=0;

????while (NULL!=p)

????{

??????len++;

??????p=p->pNext;?

????}

????return len;

}


void sort_list(PNODE pHead)

{


??int i,j,t;

??int len= length_list(pHead);

??PNODE p,q;

??for (i=0,p=pHead->pNext;i<len-1;i++,p=p->pNext)

????for (j=i+1,q=p->pNext;j<len;++j,q=q->pNext)

????{

??????if (p->data > q->data)

??????//類似于數(shù)組中的: a[i] > a[j]

??????{

????????t=p->data; //類似于數(shù)組中的t =a[i];

????????p->data = q->data;//類似數(shù)組中a[i] = a[j]???

q->data = t;

??????}?

????}??

}

bool insert_list(PNODE pHead,int pos,int val)//插入

{

????int i = 0;

????PNODE p = pHead;??

????while (NULL!=p && i<pos-1)

????{

??????p=p->pNext;

??????i++;

????}

????if (i>pos-1 || NULL==p)

??????return 0;

????PNODE pNew=(PNODE)malloc(sizeof(NODE)) ;??????

????if(NULL ==pNew)

????{

???????printf("動(dòng)態(tài)分配內(nèi)存失敗!\n");

???????exit(-1) ;

????}

????pNew->data=val;

????PNODE q=p->pNext;

????p->pNext=pNew;

????pNew->pNext=q;

????return 1;

}

bool delete_list(PNODE pHead,int pos,int *pVal)

{

????int i = 0;

????PNODE p = pHead ;??

????while (NULL!=p->pNext && i<pos-1)

????{

??????p=p->pNext;

??????i++;

????}

????if (i>pos-1 || NULL==p->pNext)

??????return 0;

????PNODE q = p->pNext ;

????*pVal =q->data;

????//刪除p節(jié)點(diǎn)后面的結(jié)點(diǎn)

????p->pNext = p->pNext->pNext ;

????free(q) ;

????q= NULL;

????return 1;

}


鏈表的分類:

單鏈表

雙鏈表:每個(gè)節(jié)點(diǎn)有兩個(gè)指針域,且最后一個(gè)節(jié)點(diǎn)指針域不指向第一個(gè)節(jié)點(diǎn)

循環(huán)鏈表:最后一個(gè)節(jié)點(diǎn)的指針域指向了第一個(gè)節(jié)點(diǎn)

非循環(huán)鏈表:

算法:

狄義的算法是與數(shù)據(jù)的存數(shù)方式密切相關(guān)

廣義的算法是與數(shù)據(jù)的存儲(chǔ)方式無關(guān)

泛型:

利用某種技術(shù)達(dá)到的效果款是:不同的存數(shù)方式,執(zhí)行的操作是一樣的


遍歷

查找

清空

銷毀

求長(zhǎng)度

排序

刪除節(jié)點(diǎn)

插入節(jié)點(diǎn)

偽算法

①:插入

錯(cuò)誤:(p->pNext= q;q->pNext = p->pNext)

//單純的檢索不到原來p后面的節(jié)點(diǎn)

正確:定義一臨時(shí)指針r來指向p后面的節(jié)點(diǎn)

(r=p->pNext;p->pNext= q;q->pNext = r;)

(q->pNext=p->pNext;p->pNext=q;)

②:刪除(p所指的后一個(gè)節(jié)點(diǎn)

錯(cuò)誤(p->pNext= p->pNext->pNext ) //內(nèi)存未釋放 使得電腦內(nèi)存被占用

正確:定義一臨時(shí)指針r來指向p后面的節(jié)點(diǎn)

(r=p->pNext;p->pNext=r->pNext;free(r);)

③:


線性結(jié)構(gòu)的兩種常見應(yīng)用:

1.棧

定義:一種可以實(shí)現(xiàn)”先進(jìn)后出“的存儲(chǔ)結(jié)構(gòu)

分類:

靜態(tài)棧:從下往上存放0123 只能依次從上往下刪除3210

動(dòng)態(tài)棧 從下往上存放0123 可以通過最上面的元素刪除3210中任意的


算法

出棧

入棧(壓棧)


應(yīng)用

函數(shù)調(diào)用

中斷

表達(dá)式求值(2個(gè)棧做計(jì)算器

內(nèi)存分配

緩沖處理

迷宮


棧的建立:

#include <stdio.h>

#include <malloc.h>

#include <stdlib. h>

typedef struct Node

{

int data;

struct?Node *pNext ;

}NODE,*PNODE;

typedef struct Stack

{

PNODE pTop; //指向棧頂

PNODE pBottom ;//指向棧底

}STACK,*PSTACK;

void init(PSTACK ps)

{

pS->pTop(PNODE)malloc(sizoof(NODE));

if(NULL == pS->pTop)

{

printf(”動(dòng)態(tài)內(nèi)存分配失敗!\n");

exit (-1);

}

else

{

pS->pBottom= ps-> pTop;

pS->pTop->pNext = NULL;

//等價(jià)于pS->Bottom->pNext = NULL;

}

}

void push(PSTACK S,int val)

{

PNODE pNew=(PNODE)malloc(sizoof(NODE));

pNew->data = val ;

pNew->pNext =pS->pTop;

//pS->Top不能改成pS->Bottom

ps->pTop = pNew;

return ;

}

void traverse(PSTACK pS)

{

PNODE p = pS->pTop; .

while (p != pS->pBottom)

{

printf ("%d",p->data) ;

p=p->pNext;

}

printf("\n");

return;

}

//把ps所指向的棧出棧一次,并把出棧的元素存入pVal形參所指向的變量中,如果出棧失敗返回0(即棧為空),否則返回1

bool empty(PSTACK pS)

{

if (pS->pTop==pS->pBottom)

return 1;

else return 0;

}

//把ps所指向的棧出棧一次并把出棧的元素存入pval所指向的變量中,如果出棧成功返回true,否則false

bool pop(PSTACK pS,int * pVal)

{

if(empty(pS))//pS本身存放的就是S的地址

return 0;

else

{

PNODE r = pS->pTop;

*pVal=r->data;

pS->gTop = r->pNext ;

free(r) ;

r = NULL;

return 1;|

}

}

void clear(PSTACK PS)//只是刪除棧中所有數(shù)據(jù)

{

if (empty(pS))

return;

else

{

PNODE p= pS->pTop;

PNODE q = NULL;

while (p != pS->pBottom)

{

q = p->pNext;

free(p);

p=q;

}

pS->pTop = pS->pBottom;

}

}


int main(void)

{

STACK S;

init(&S);//創(chuàng)建空棧 寫S地址才能改變它的值

push(&S,1);//入棧

push(&S,2);//入棧

traverse(&S);//遍歷輸出


if (pop(&S,&val))

{

printf("出棧成功 出棧元素是%d\n",val);

}

else printf("出棧失敗\n");

clear("&S");

traverse(&S);

}


2.隊(duì)列:

定義:可以滿足先進(jìn)先出的一種存儲(chǔ)結(jié)構(gòu)

分類:鏈?zhǔn)疥?duì)列(鏈表

靜態(tài)隊(duì)列(數(shù)組

靜態(tài)隊(duì)列通常必須是循環(huán)隊(duì)列


循環(huán)隊(duì)列的講解:

1.靜態(tài)隊(duì)列為什么必須是循環(huán)隊(duì)列

溢出時(shí)回到頭

2.循環(huán)隊(duì)列需要幾個(gè)參數(shù)來確定及其含義

需要2個(gè)參數(shù)來確定

front

rear

2個(gè)參數(shù)不同場(chǎng)合有不同的含義建議初學(xué)者先記住,然后慢慢體會(huì)

1).隊(duì)列初始化

front 和rear的值都是0

2).隊(duì)列非空

front代表的是隊(duì)列的第一個(gè)元素

rear代表的是隊(duì)列的最后一個(gè)有效元素的下一個(gè)元素

3)﹒隊(duì)列空

front和rear的值相等,但不一定是0

3.循環(huán)隊(duì)列各個(gè)參數(shù)的含義(2已經(jīng)講完

4.循環(huán)隊(duì)列入隊(duì)偽算法講解

①將值存入r所代表的位置

②r=(r+1)%數(shù)組長(zhǎng)度

5.循環(huán)隊(duì)列出隊(duì)偽算法講解

①f=(f+1)%數(shù)組長(zhǎng)度(自己判斷是否要?jiǎng)?chuàng)建一個(gè)val來存儲(chǔ)出隊(duì)的數(shù)據(jù))

6.如何判斷循環(huán)隊(duì)列是否為空

front=rear

7.如何判斷循環(huán)隊(duì)列是否已滿

預(yù)備知識(shí):front和rear的值大小關(guān)系不確定,可大可小可相等

判斷方法:

常用:少用一個(gè)元素,如果fr緊挨則隊(duì)列已滿

不常用:多增加一個(gè)標(biāo)識(shí)參數(shù),長(zhǎng)度等于數(shù)組長(zhǎng)度或者r和f重合時(shí)

if((r+1)%數(shù)組長(zhǎng)度==f) 滿;

else 不滿

3.隊(duì)列的具體應(yīng)用:所有和時(shí)間有關(guān)的操作


循環(huán)隊(duì)列程序演示

#include <stdio.h>

#include <malloc.h>

struct Queue

{

int * pBase;

int front;

int rear;

}QUEUE;

void init_queue(QUEUE *pQ);//初始化

bool full_queue (QUEUE * pQ)

{

if ( (pQ->rear + 1)% 6 == pQ->front )

return true;

else

return false;

}


bool en_queue(QUEUE *pQ,int val);//入隊(duì)

{

if ( full_queue (pQ) )

{

return false;

}

else

{

pQ->pBase [pQ->rear] = val;

pQ->rear = (pQ->rear+1)%6 ;

return true;

}

}

bool emput_queue(QUEUE *pQ)

{

if (pQ->front==pQ->rear)

return 1;

else return 0;

}

bool out_queue(QUEUE *pQ,int *pVal)

{

if (emput_queue(pQ))

return 0;

else

{

*pVal = pQ->pBase[pQ->front] ;

pQ->front = (pQ->front+1)%6;

return 1

}


}


void tarverse_queue(QUEUE *pQ)

{

int i=pQ->front;

while (i!=pQ->rear)

{

printf("%d ",pQ->Base[i]);

i=(i+1)%6;

}

}

int main(viod)

{

int val;

QUEUE Q;

init(&Q);

en_queue(&Q,1);

en_queue(&Q,2);

en_queue(&Q,3);

en_queue(&Q,4);

en_queue(&Q,5);

en_queue(&Q,6);

traverse_queue(&Q);

if (out_queue(&Q,&val))

{

printf("出隊(duì)成功,出隊(duì)元素是:%d\n“,val;

}

else printf("出隊(duì)失敗\n");

return 0;

}

3.遞歸:

定義:

一個(gè)函數(shù)直接或者間接的調(diào)用自己

直接:f套f 間接:f套g g套f

遞歸滿足三個(gè)條件:

1、遞歸必須得有一個(gè)明確的中止條件

2、該函數(shù)所處理的數(shù)據(jù)規(guī)模必須在遞減

3、這個(gè)轉(zhuǎn)化必須是可解的

循環(huán)和遞歸

遞歸:

易于理解

速度慢

存儲(chǔ)空間大

循環(huán):

不易理解

速度快

存儲(chǔ)空間小

注意事項(xiàng):

當(dāng)在一個(gè)函數(shù)的運(yùn)行期間調(diào)用另一個(gè)函數(shù)時(shí),在運(yùn)行被調(diào)函數(shù)之前,系統(tǒng)需要完成三件事:

1.將所有的實(shí)際參數(shù),返回地址等信息傳遞給被調(diào)函數(shù)保存

2為被調(diào)函數(shù)的局部變量(也包括形參)分配存儲(chǔ)空間

3.將控制轉(zhuǎn)移到被調(diào)函數(shù)的入口

從被調(diào)函數(shù)返回主調(diào)函數(shù)之前,系統(tǒng)也要完成三件事:

1.保存被調(diào)函數(shù)的返回結(jié)果

2釋放被調(diào)函數(shù)所占的存儲(chǔ)空間

3.依照被調(diào)函數(shù)保存的返回地址將控制轉(zhuǎn)移到調(diào)用函數(shù)

應(yīng)用:

①、高斯求和

②、階乘

③、漢諾塔

④、走迷宮


模塊二:非線性結(jié)構(gòu)

專業(yè)定義

1.有且僅有一個(gè)根節(jié)點(diǎn)

2.有若干個(gè)互不相交的子樹,這些子樹本身也是一棵樹


通俗定義:

1.樹由節(jié)點(diǎn)和邊(指針域)組成

2.每個(gè)節(jié)點(diǎn)只有一個(gè)父節(jié)點(diǎn)但可以有多個(gè)子節(jié)點(diǎn)(除根節(jié)點(diǎn)無父節(jié)點(diǎn)

樹的專業(yè)術(shù)語:

深度:

從根節(jié)點(diǎn)到最底層節(jié)點(diǎn)的層數(shù)稱之為深度

根節(jié)點(diǎn)是第一層

葉子節(jié)點(diǎn):

沒有子節(jié)點(diǎn)的節(jié)點(diǎn)

非終端節(jié)點(diǎn)

實(shí)陳就是非葉子節(jié)點(diǎn)

子節(jié)點(diǎn)的個(gè)數(shù)稱為度


樹的分類

一般樹:任意一個(gè)節(jié)點(diǎn)的子節(jié)點(diǎn)個(gè)數(shù)都不受限制

二叉樹:任意一個(gè)節(jié)點(diǎn)的子節(jié)點(diǎn)最多兩個(gè),且子節(jié)點(diǎn)的位置不可更改

二叉樹的分類

一般二叉樹

滿二叉樹

在不增加樹的層數(shù)的前提下,無法再增加一個(gè)節(jié)點(diǎn)的二叉樹是滿二叉樹

完全二叉樹

如果只刪除了滿二叉樹最底層最邊的連續(xù)若干個(gè)節(jié)點(diǎn),這樣形成的二叉樹是完全二叉樹

森林:n個(gè)互不相交的樹的集合

樹的存儲(chǔ)

二叉樹的存儲(chǔ)

連續(xù)存儲(chǔ)【完全二叉樹】

由于先中后三種樹的轉(zhuǎn)化方式都無法重新推到出樹并且不一致,只能補(bǔ)足

優(yōu)點(diǎn):查找某個(gè)節(jié)點(diǎn)的父節(jié)點(diǎn)和子節(jié)點(diǎn)(也包括判斷有沒有

缺點(diǎn): 耗內(nèi)存過大

鏈?zhǔn)酱鎯?chǔ):

一般樹的存儲(chǔ):(無序

雙親表示法

求父節(jié)點(diǎn)方便

孩子表示法

求子節(jié)點(diǎn)方便


雙親孩子表示法

集以上兩種的特長(zhǎng),缺點(diǎn)是編程麻煩


二叉樹表示法

把一個(gè)普通樹轉(zhuǎn)化成二叉樹來存儲(chǔ)

具體轉(zhuǎn)換方法:

設(shè)法保證任意一個(gè)節(jié)點(diǎn)的左指針域指向它的第一個(gè)孩子,右指針域指向它的兄弟

滿足此條件,就可以把一個(gè)普通樹轉(zhuǎn)化為二叉樹

森林的存儲(chǔ)

先把森林轉(zhuǎn)化為二叉樹,再存儲(chǔ)二叉樹


二叉樹的操作

遍歷

先序遍歷

先訪問根節(jié)點(diǎn)

再先序訪問左子樹

先序訪問右子樹



中序遍歷

中序遍歷左子樹

再訪問根節(jié)點(diǎn)

再中序遍歷右子樹


后序遍歷[最后訪問根節(jié)點(diǎn)]

先中序詘歷左子樹

再中序遍歷右子樹

再訪問根節(jié)點(diǎn)

已知兩種遍歷序列求原始二叉樹

通過先序和中序或者中序和后序我們可以 還原出原始的二叉樹

但是通過先序和后序是無法還原出原始的二叉樹的

先序中序求樹技巧

①先序第一個(gè)為根節(jié)點(diǎn)

②中序中的字母在先序中先出現(xiàn)的為那層的根節(jié)點(diǎn)

后序中序求樹技巧

①后序最后一個(gè)為根節(jié)點(diǎn)

②中序中的字母在后序中后出現(xiàn)的為那層的根節(jié)點(diǎn)


應(yīng)用

樹是數(shù)據(jù)庫中數(shù)據(jù)組織一種重要形式

操作系統(tǒng)子父進(jìn)程的關(guān)系本身就是一糅樹

面向?qū)ο笳Z言中類的維承關(guān)系

赫夫曼樹

二叉鏈表的創(chuàng)建(如圖



#include <stdio.h>

struct BTNode

{

int dat a;

struct BTNode * pLchild; / /p是指針 L是左 child是孩子

struct BTNode * pRchild;

}

int main(void)

{

struct BTNode * pT = CreateBTree(void) ;

//先中后序遍歷

PreTraverseBTree(pT);

InTraverseBTree(pT);

PostTraverseBTree(pT) ;


return 0;

}

struct BTNode *CreateBTree(void)

{

struct BTNode * pA= (struct BTNode *)malloc(sizeof (struct BTNode));

struct BTNode * pB= (struct BTNode *)malloc(sizeof (struct BTNode));

struct BTNode * pC= (struct BTNode *)malloc(sizeof (struct BTNode));

struct BTNode * pD= (struct BTNode *)malloc(sizeof (struct BTNode));

struct BTNode * pE= (struct BTNode *)malloc(sizeof (struct BTNode));

pA->data = 'A';

pB->data =‘B’;

pC->data = 'C';

pD->data = 'D';

pE->data = ’E’;

pA-> pLchild = pB;

pA->pRchild = pC;

pB-> pLchild = pB-> pRchild = NULL;

pC->pLchild = pD;

pC->pRchild = NULL;

pD->pLchild = NULL;

pD-> pRchild = pE;

pE->pLchild = pE->pRchild=NULL;

return pA ;

}

void PreTraverseBTree(strcut BTNode * PT);

{

if (pT!=NULL)

{

printf("%c\n",pT->data);

if(NULL != pT-> pLchild)

PreTraverseBTree(pT->pLchild);

if(NULL != pT-> pRchild)

PreTraverseBTree(pT->pRchiid):

}

//pT->pLchild可以代表整個(gè)左子樹

/*偽算法

先訪問根節(jié)點(diǎn)

再先序訪問左子樹

再先序訪問右子樹*/

}

void InTraverseBTree(struct BTNode * pT)

if (NULL != pT)

{..

if (NULL != pT->pLchild)

InTraverseBree(pT->pLchild) ;

printf("%c\n",pT->data);

if (NULL != pT->pRchild){

InTraverseBTree(pT->pRchild) :1/pT->pLchild可以代表整個(gè)左子樹

}



{

數(shù)據(jù)庫

字段:反映事物的屬性

記錄:一個(gè)整體的事務(wù)


表:同一類事物的集合

}

【郝斌】-數(shù)據(jù)結(jié)構(gòu)入門的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國(guó)家法律
绥中县| 翼城县| 信丰县| 双江| 尼玛县| 麻栗坡县| 西城区| 澜沧| 镇原县| 东光县| 根河市| 通化市| 北海市| 巩义市| 福海县| 安塞县| 红安县| 仪陇县| 马尔康县| 广河县| 鹤庆县| 石棉县| 连山| 津南区| 邓州市| 民勤县| 全南县| 岳阳市| 武山县| 平武县| 遵化市| 巴林左旗| 南华县| 仁寿县| 阿瓦提县| 姚安县| 和田市| 平陆县| 平南县| 若尔盖县| 邛崃市|