小豬的資料結構學習筆記(二),小豬資料結構學習
小豬的資料結構學習筆記(二)
線性表中的順序表
本節引言:
在上個章節中,我們對資料結構與演算法的相關概念進行了瞭解,知道資料結構的
邏輯結構與物理結構的區別,演算法的特性以及設計要求;還學了如何去衡量一個演算法
的好壞,以及時間複雜度的計算!在本節中我們將接觸第一個資料結構——線性表;
而線性表有兩種表現形式,分別是順序表和鏈表;學好這一章很重要,是學習後面的基石;
這一節我們會重點學習下順序表,在這裡給大家一個忠告,學編程切忌眼高手低,看懂不代表自己
寫得出來,給出的實現代碼,自己要理解思路,自己寫出來!寫多了就有感覺了!多思考!!
另外附上學習資料結構的一個利器,資料結構示範動畫,在本文結尾給出!
好了,廢話就這麼多!
本節學習路線圖
路線圖解析:
①抽象資料類型就那三要素:資料,資料之間的關係,和資料的操作
②線性表就是按一條線排列的資料集合,1對1,除了首元和尾元,其他元素都有直接前驅和直接後繼
③順序表有點像以前學習的數組,要小心注意表中的第i個元素是對應 i - 1那個位置的資料的!!!!
④基本存放裝置結構要牢記,至於12個基本操作,除了插入和刪除有點小難度,其他的都很簡單,要自己將代碼寫多幾遍哦!
⑤求並集的那個,也不是很難懂,自己拿筆畫,想一想應該就懂了!去除表中的重複元素占時沒想到什麼好的方法,有好的歡迎提出!
本文:
一.抽象的資料類型
二.線性表中的順序表
三.相關操作的代碼實現與解析:
1.線性表的儲存結構:
<span style="font-family:Microsoft YaHei;">#define MAXSIZE 20#define INCREMENT 10#define OK 1#define ERROR 0#define TRUE 1#define FALSE 0//定義一個int資料類型的別名//這裡因為示範採用int,實際使用的通常是複合的資料類型 typedef int ElemType;typedef int Status;typedef struct{ElemType *elem; //儲存空間的起始地址 int length; //表的當前長度 int listsize; //表的總共儲存容量(sizeof(ElemType)) }SqList;</span>
2.構造空表
<span style="font-family:Microsoft YaHei;">//建立一個空表:void InitList(Sqlist &L){L.elem = (ElemType *)malloc(MAXSIZE * sizeof(ElemType));if(!L.elem) exit(ERROR);L.length = 0;L.listsize = MAXSIZE; } </span>
代碼解析
:步驟:
①申請表的儲存空間,將空間的其真實位址賦值給elem,然後通過判斷elem是否為空白,從而知道記憶體是否分配成功
②將表的當前長度length設定為0,將表的大小listsize設定為MAXSIZE
3.將表置為空白表
<span style="font-family:Microsoft YaHei;">//將表置為空白表 void ClearList(SqList &L){L.length = 0;} </span>
代碼解析:
只需要將表的長度length設定為0就可以了,很簡單吧
4.判斷是否為空白表
<span style="font-family:Microsoft YaHei;">//判斷表是否為空白表 Status ListEmpty(SqList L) { if(L.length == 0)return TRUE; else return False; }</span>
程式碼分析:
同樣只需要判斷length的值是否為0就可以了,很簡單
5.銷毀表
<span style="font-family:Microsoft YaHei;">//銷毀表void DestroyList(SqList &L){free(L.elem);L.elem = NULL;L.length = 0;L.listsize = 0;} </span>
程式碼分析:
步驟:
①調用free函數釋放L,elem指向的記憶體空間的記憶體
②將L.elem賦值為NULL,即null 指標
③將表的當前長度Length和表的最大長度listsize設定為0
6.獲得表中的資料元素數目
<span style="font-family:Microsoft YaHei;">//獲得當前表中元素的數目int ListLength(SqList L){return L.length; } </span>
程式碼分析:
直接返回當前長度length即可
7.獲得表中第i個資料元素的值
<span style="font-family:Microsoft YaHei;">//獲得表中第i個元素的值,通過e的值反映 Status GetElem(SqList L,int i,ElemType &e){if(i < 1|| i > L.length)return ERROR;e = *(l.elem + i - 1);return OK;} </span>
程式碼分析:
①先判斷第i個位置是否合法
②將對於位置的值賦值給e,另外減一是因為數組是下標是從0開始的!!
而我們看錶是從1開始算的,所以需要減一
8.尋找表中是否有滿足要求的元素
<span style="font-family:Microsoft YaHei;">//返回表中第一個滿足要求的元素的下標//這裡我們把要求假設為一個函數compare(int l_s,int e); //參數依次為表中元素與需要進行關係比較的參數e//第三個參數函數指標,旨錘向函數的指標 int LocateElem(SqList L,ElemType e,Status(*compare)(ElemType,ElemType)){int i = 1;ElemType *p = L.elem;while(i < L.length && !compare(*p++,e))i++;if(i <= L.length) return i;else return 0;} </span>
程式碼分析:
步驟:
①定義變數i和指標p分別執行表中第1個元素和表的首地址
②迴圈調用compare()函數與表中的元素進行比較
③如果i <= length的話說明找到了,返回對應元素的序號
④否則返回0表示找不到
9.返回某個節點的前驅
<span style="font-family:Microsoft YaHei;">//返回某個節點的直接前驅//第二和第三個參數分別為:指定的資料元素,before用來儲存它的前驅的 Status PriorElem(SqList L,ElemType choose,ElemType &before){int i = 2;ElemType *p = L.elem + 1;while(i <= L.length && *p != choose){p++;i++;}if(i > L.length)return ERROR;else{before = *--p;return OK; }} </span>
程式碼分析:
①首元是沒有前驅的,所以i從2,p從L.elem +1 開始算
②通過迴圈查看指定資料元素在表中的位置,如果i > L.length表示找不到,返回ERROR
③找到的話,通過*--p擷取該元素前驅的值賦值給before變數
10.返回某個節點的後繼
<span style="font-family:Microsoft YaHei;">//返回某個支點直接後繼//第二三個參數依次為:選定的資料元素的值,儲存後繼的變數 Status NextElem(SqList L,ElemType choose,ElemType &behind){int i = ;ElemType *p = L.elem;while(i < L.length && *p != choose){p++;i++;}if(i == L.length)return ERROR;else {behind = * ++p;return OK;}} </span>
程式碼分析:
①和上面的前驅差不多,要注意的是i == L.length就可以了,因為尾元沒有後繼,所以直接把尾元排除了!
11.往表中第i個位置插入元素
<span style="font-family:Microsoft YaHei;">//往表的第i個位置插入元素eStatus ListInsert(SqList &L,int i,ElemType e){ElemType *p,*q,*newbase;//插入位置為1-length,其他值不合法 if(i<1||i>L.length + 1)return ERROR;//如果表滿了的話,增加分配的空間 if(L.length == L.listsize){newbase = (ElemType)realloc(L.elem,(L.listsize + INCREMENT)*sizeof(ElemType));if(!newbase)exit(ERROR);L.elem = newbase;L.listsize += INCREMENT;}p = L.elem + i - 1;//向右移,先移動最後一個 for(q = L.elem + L.length - 1;q >= q;--q)*(q + 1) = *q;//將e插入,表長+1 *q = e;++L.length;return OK; } </span>
代碼解析:
12.刪除表中第i個位置的元素
<span style="font-family:Microsoft YaHei;">//刪除表中第i個位置的元素Status ListDelete(SqList &L,int n,ElemType &e){ElemType *p,*q;//判斷刪除的位置是否合法if(i < 1 && i > L.length)return ERROR;//指向刪除的位置,將值付給e p = L.elem + i - 1;e = *p;//指向尾元,由刪除位元置的後繼元素開始前移q = L.elem + L.length - 1;for(++p;p <= q;p++)*(p - 1) = *p;L.length--;return OK; }</span>
程式碼分析:
13.遍曆順序表所有元素
<span style="font-family:Microsoft YaHei;">//遍曆線性表所有元素void ListTraverse(SqList L,void(*visit)(ElemType&)){int i = 1;ElemType *p = L.elem;for(i ==1;i <= L.length;i++){visit(*p++);printf("\n");}} </span>
代碼解析:
代碼很簡單,就是從第一個元素開始,讓指標後移,依次調用visit()函數
實現表中元素的遍曆
14.應用小樣本:
已知A,B兩個順序表中的元素是按從小到大排列的;現在要你求兩個的並集C;
而且C中的元素也要按從小到大排序;不改變A和B中的資料!
是並集哦,就是C中不能有重複的元素
<span style="font-family:Microsoft YaHei;">void UnionList(SqList La,SqList Lb,SqList &Lc){//定義指向La,Lb表頭表位的指標,以及指向Lc的指標 ElemType *la,*la_end,*lb,*lb_end,*lc;la = La.elem;lb = La.elem;la_end = La.elem + La.length - 1;lb_end = Lb.elem + Lb.length - 1;//在這裡為lc分配記憶體空間,大小為La.length + Lb.lengthLc.listsize = Lc.length = La.length + La.length;lc = Lc.elem = (ElemType *)malloc(Lc.listsize * sizeof(ElemType));if(!Lc.elem)exit(ERROR);//將a,b中的元素進行合并//如果a,b中都有元素還沒有合并while(la <= la_end && pb <= lb_end){if(*la <= *lb)*lc++ = *la++;else *lc++ = *lb++;}//假如還有剩下的元素,要麼是a,要麼是bwhile(la <= la_end)*lc++ = *la++;while(lb <= lb_end)*lc++ = *lb++;//接著要將Lc中重複的元素刪除掉ElemType *p,*q;p = Lc.elem;q = p;//使用兩枚指標p,q,如果指標p沒有指向末尾 while(p != (Lc.length - 1)){//q指向p的尾碼,比較兩數的值 if(*p != *(++q)){p++;q = p;}//相等的話,刪除q指向的元素//再次進行比較,直到不重複為止 else{while(*p == *q)ListDelete(Lc,(p - Lc.elem),e);}} }</span>
ps:最後去除Lc中的重複元素的演算法似乎有點累贅,如有高效點的演算法,歡迎提出,萬分感激啊!
本章小結:
①什麼是抽象的資料類型ADT
②線性表的定義與線性表的特性
③順序表:地址連續的儲存單元一次儲存的線性表
④順序表的結構,三個基本屬性
⑤順序表的12個相關操作
⑥順序表的使用小樣本
學習資源下載:
本節代碼打包:點擊下載
資料結構示範工具:點擊下載
錯誤提示
孩子含鉛量高怎辦?
不要讓他吃爆米花阿