1、在標頭檔中
#ifndef _ACCOUNT_ //先行編譯選項,表示如果沒有定義這個宏 #define _ACCOUNT_ //建立以_ACCOUNT_命名的宏 並聲明類 #endif
2、鏈表
(1)解決數組必須連續儲存的問題
鏈表是可以不連續的,通過每個節點的指標串連
(2)節點中一部分空間用於存放資料,另一部分是一個指向下一個節點的指標
(3)每個節點都是一個結構
struct node{ int data; //儲存資料 node* next; //指向下一個節點的指標,是自己這個結構的類型 }
(4)尾節點 --- 鏈表中的最後一個節點 --- 指標指向NULL
前端節點 --- 要訪問鏈表中的元素,必須要知道前端節點的位置
把地址放在一個指標中 --- 頭指標指向前端節點,只是一個指標 --- 是必須存在的元素
(5)對鏈表的常見操作 --- 增刪改查
(6)鏈表與數組的區別
數組:空間必須連續,數組是定長的,插入和刪除需要遍曆整個數組,效率不高。
取元素可直接使用下標,訪問方便
鏈表:空間在記憶體中不必連續,通過指標串連
鏈表是不定長的,可以隨時添加新節點,通過指標關聯
對鏈表的插入刪除,不需要移動節點位置,只對指標操作即可
訪問元素,要從頭指標開始遍曆
當資料需要頻繁的插入刪除的時候,需要使用鏈表
當改動不大,查詢頻繁的時候,使用數組
潛規則 : 能用數組就不用鏈表
View Code
====================================================================== link.h ====================================================================== #ifndef _LINK_ #define _LINK_ using namespace std; class Node{ //節點類 public : int val; //儲存資料 Node* next ; //儲存下一個節點的地址 Node(){ //建構函式,把指標初始化為NULL next = NULL; } }; class Link{ protected : Node* head; //頭指標 public : Link(); ~Link(); void insertTail(int); void insertHead(int); void del(int); int indexOf(int); //查詢一個元素的下標 void update(int , int); void disp(); }; #endif
View Code
====================================================================== link.cc ====================================================================== #include "link.h" #include <iostream> using namespace std; Link::Link(){ head = NULL; } Link:: ~Link(){//釋放空間,從頭向尾釋放 if(head != NULL){ Node *p = head; head = head->next; //把前端節點向後移動 delete p; //拋棄原來的那個前端節點 cout << "delete one ... " << endl; } } //尾插入 void Link::insertTail(int v){ Node *p = new Node; p->val = v; if(head == NULL){ head = p; //讓新節點的指標指向新節點,即把新節點的地址儲存在頭指標中 return ; } Node * temp = head ; //用一個臨時指標,從前端節點開始找到 尾 while(temp -> next != NULL){ //表示temp不是尾節點 temp = temp -> next ; //用temp後面的一個指標為自己賦值,即指向下一個節點 } temp -> next = p; //尾插入,最後一個節點的指標儲存新節點的地址 } //頭插入 void Link::insertHead(int v){ Node *p = new Node; //建立新節點 p->val = v ; //儲存資料 p->next = head; //讓新節點的指標和頭指標一樣指向第一個節點 head = p; //讓前端節點指向新節點 } void Link::del(int v){ //找到被刪除的節點 , if(head == NULL ){ return ; } if(head -> val == v){ Node *p = head; head = head->next; delete head; } Node *p1 = head->next; //找值相同的一個 Node *p2 = head ; //跟在p1後面 while(p1 != NULL){ if(p1->val == v){ p2->next = p1 -> next; delete p1; break; } p1 = p1->next; p2 = p2->next; } } int Link::indexOf(int v){ //查詢一個元素的下標 Node * p = head ; int counter = 0 ; while( p != NULL ){ if( p->val == v ){ return counter ; } p=p->next ; counter++ ; } return -1 ; } void Link::update(int v1 , int v2){ Node * p = head ; while( p != NULL ){ if( p->val == v1 ){ p->val = v2 ; } p = p->next ; } } void Link::disp(){ Node *p = head; while(p != NULL){ cout << p->val << " " ; p = p->next; } cout << endl; }
3、二叉樹
每個節點最多隻有兩個分支的樹,它有一個根指標,要指向這棵樹的根節點(最頂端的節點).
左子樹上的值小於其父節點的值,右子樹上的值都大於其父節點上的值。 --- 排序二叉樹
(1)周遊(遍曆) :先序 --- 中左右
中序 --- 左中右
後序 --- 左右中
(2)非常方便尋找
二叉尋找樹的常見操作:
1) 插入. 範例程式碼如下:
View Code
Node* Tree::_insert(int v, Node* r){ //真正實現插入操作,返回插入以後的根 if(r == NULL){ //是一棵空樹 (空子樹) Node* p = new Node(v); //建立新節點 r = p; //讓新節點成為根或者子節點 return r; } if( v < r->val){ //插到左子樹上 r->left = _insert(v,r->left); return r; }else{ //插到右子樹上 r->right = _insert(v,r->right); return r; }}
2) 尋找. 範例程式碼如下:
View Code
Node* & find( bnode* & root, const DATA& cd ) { if( root==NULL ) // 如果root節點是空,則為空白樹 return root; // 返回root指向的地址,即NULL else if( root->data==cd ) // 如果root節點就是要尋找的數值 return root; // 返回root指向的地址,為了清晰,和上面的分開寫 else if( cd < root->data ) // 如果root節點指向的值大於要尋找的值 return find( root->left, cd ); // 返回尋找root的左子樹返回的地址 else return find( root->right, cd ); // 否則返回尋找root的右子樹返回的地址 }
3) 刪除. 範例程式碼如下:
被刪除的是樹根(1)則選擇右子樹的樹根做新樹根,左子樹可以整個掛在右子樹最左側的一個左節點上
右子樹中最左邊的一個節點,是最靠近左子樹的樹根的
(2)讓左子樹中的最大節點做新樹根
View Code
Node* _del( int value , Node* r ){ if( r == NULL ){ //刪除空樹 return r ; } if( r->value == value ){ //刪除樹根 if(r->left==r->right){ //左右子樹都是NULL的情況下 delete r ; return NULL; }else if( r->right == NULL ){ //只有右子樹,沒有左子樹的時候 Node * p = r; r = r->left ; delete p ; return r ; }else if( r->left == NULL ){ //只有右子樹,沒有左子樹 Node *p = r ; r=r->right ; delete p ; return r ; }else{ //左右子樹都有 Node * p1 = r -> right ; Node * p2 = r -> right ; while( p2->left != NULL ){ p2 = p2->left ; } p2->left = r->left ; delete r ; return p1 ; } } if( value <= r->value ){ r->left = _del( value , r->left); return r ; }else{ r->right =_del( value, r->right ); return r ; } return r ;}
作業:修改鏈表程式,能夠刪除全部相同元素;在指定位置後插入資料