一、單鏈表
單向鏈表(單鏈表)是鏈表的一種,其特點是鏈表的連結方向是單向的,對鏈表的訪問要通過順序讀取從頭部開始;鏈表是使用指標進行構造的列表;又稱為節點列表,因為鏈表是由一個個節點群組裝起來的;其中每個節點都有指標成員變數指列表中的下一個節點;
列表是由節點構成,由head指標指向第一個成為表頭的節點而終止於最後一個指向nuLL的指標;
1.建立鏈表(尾插法):
尾插法的基本思想:
1.產生一個節點,將讀入的資料存放到新節點的資料域中
2.把新節點插到當前鏈表的尾節點之後
3.重複上述過程,直至輸入結束標誌
尾插法讀入資料的順序和線性表的邏輯順序是相同的
void creat_list( Node* &head) { //傳入指向表頭的指標,這個指標要儲存下來。 注意Node* &, 是Node* 類型的引用Node *pre,*newNode;head = pre = new Node; //產生表頭結點newNode = new Node; //建立新節點cin>>newNode->num; //輸入新節點的值while(newNode->num) { //判斷輸入結束的條件pre-> next = newNode; //上一個節點串連新節點pre = newNode; //因為馬上要申請新空間,此時的新節點即將變成“上一個節點”,儲存給prenewNode = new Node; //再次申請新空間cin >> newNode->num; //輸入值}pre->next = NULL; //結束後,將單鏈表最後一個節點rear指標置為空白,標誌著結束}
2.建立鏈表(頭插法)
頭插法的基本思想:
1.產生一個節點,將讀入的資料存放到新節點的資料域中
2.把新節點作為第一個表節點查到單簽鏈表前端節點之後
3.重複上訴過程,直至輸入結束標誌為止
頭插法讀入資料的順序和線性表的邏輯順序是相反的。
void creat_head(Node* &head) {Node *newNode; head = new Node; head->next = NULL;newNode = new Node;cin>>newNode->num; //輸入資料while(newNode->num){newNode->next = head->next;head->next = newNode;newNode = new Node;cin >> newNode->num;}}
3.單鏈表尋找:按值尋找
Node* search_value(Node *head, int x){ //x為要尋找的值Node *p=head->next;while(p!=NULL && p->num!=x)p = p->next;if(p->num ==x )return (p);return NULL;}
4.單鏈表尋找:按位置尋找
Node* search_local(Node *head, int i) { //i為要尋找的位置Node *p=head;int count=0;while(p->next!=NULL && count<i) {p = p->next;++count;}if(count==i)return (p);return NULL;}
5.單鏈表插入:前插(後插)
操作過程:
1.產生一個新節點newNode,將值x賦給新節點newNode的資料域
2.從表前端節點開始,尋找p的前驅節點q
3.修改有關節點的指標域,將newNode指標域指向p節點,q節點指向newNode
Node* inset_front(Node *head,int i,int x){ //x為要插入的值,i是位置Node *p,*newNode;newNode = new Node; //申請新空間newNode->num = x; //賦值p = search_local(head,i-1); //只要把i-1改成i,就變成了插在i的後面(後插法)newNode->next = p->next;p->next = newNode;return head;}
6.單鏈表的刪除(刪除鏈表中的值x)
操作過程:
1.假設有兩個節點pre和p,pre是p的前驅節點,p為要刪除的節點
2.找pre,從鏈表head的頭結點開始,一次向後進行搜尋,當pre-next = p時,找到
3.修改pre-next = p-next,把p的前驅節點指向p的後繼節點,並且刪除空間
Node* delete_link(Node *head,int x){Node *pre,*p; //pre存p的前驅節點p = head;while(p!=NULL && p->num!=x) {pre=p;p = p->next;}if(p!=NULL) {pre->next = p->next;delete (p);return head;}else {cout<<"要刪除的值不存在\n";return NULL;}}
二、迴圈列表
迴圈鏈表:表中最後一個節點的指標域不再是空,而是指向第一個節點,整個鏈表形成一個環。
特點:從表中任一節點出發,就可搜尋到其他所有節點
作用:在許多實際應用中,對鏈表的操作運算是在表頭、表尾進行的,這時可以改變鏈表的標識方法,不用頭指標
而用指向尾節點的尾指標rear來標識,以提高效率。
和單鏈表的比較:
單鏈表中,找到第一個元素時間為O(1),最後一個元素為O(n);
而應用迴圈鏈表,則找到最後一個元素為O(1),由於最後一個元素指向第一個元素,因此找到第一個元素也為O(1)
運算: 迴圈鏈表與單鏈表的運算基本一致,區別在於判斷遍曆表完成條件不同,單鏈表判斷當前指標域是否為空白,而迴圈
鏈表判斷當前節點指標域是否為表頭指標。
//下面以尋找運算為例
//下面以尋找運算為例Node* search_value(Node *head, int x){ //x為要尋找的值Node *p=head->next;while(p->next!=head && p->num!=x) // p->next!=headp = p->next;if(p->num ==x )return (p);return NULL;}
三、雙向鏈表
雙向鏈表:指沿著前驅和後繼方向都能遍曆的線性鏈表。
其每個節點都有兩個指標域:一個指向其後繼節點,另一個指向其前驅結點。
雙向鏈表的節點類型定義為:
struct Dnode{int data; //data儲存表中的元素 Dnode *next,*prior; //next指向後一節點指標,prior指向前一節點指標};
雙向鏈表優點: 雙向鏈表既有向前的指標域,又有向後的指標域,這就使得雙向鏈表的前插和後插
以及刪除操作都很方便,只需要修改幾個節點的指標域,而不必進行大量的資料交換和遍曆操作
// 節點類型struct Dnode{ int data; //data儲存表中的元素 Dnode *next,*prior; //next指向後一節點指標,prior指向前一節點指標};//雙向鏈表的前插(在某節點p之前插入一個新節點s)Dnode *insert_before(Dnode *head,Dnode *p, int x){Dnode *s; //s為要插入的節點s = new Dnode; //建立新節點s->data = x; //給s節點的資料域賦值s->next = p;//步驟1:將節點s的後繼指標指向p;s->prior = p->prior;//步驟2:將節點s的前驅指標指向節點p的前驅節點p->prior->next = s;//步驟3:將p的前驅結點的後繼指標修改為指向新節點s;p->prior = s;//步驟4:將節點p的前驅指標修改為指向新節點s.return head;}//雙向鏈表的後插(在某節點p之後插入一個新節點s):Dnode *insert_back(Dnode *head,Dnode *p, int x){Dnode *s; //s為要插入的節點s = new Dnode; //建立新節點s->data = x; //給s節點的資料域賦值s->next = p->next;//步驟1:將節點s的後繼指標指向p;s->prior = p;//步驟2:將節點s的前驅指標指向節點p的前驅節點p->next->prior = s;//步驟3:將p的前驅結點的後繼指標修改為指向新節點s;p->next = s;//步驟4:將節點p的前驅指標修改為指向新節點s.return head;}//雙向鏈表節點的刪除:Dnode *delete_Dnode(Dnode *head,Dnode *p){if(p != NULL){p->prior->next = p->next; //步驟1:將p的前驅節點的後繼指標改為指向p的後繼p->next->prior = p->prior; //步驟2:將p的後繼結點的前驅指標改為指向p的前驅delete (p);//步驟3:釋放p的儲存空間return head;//返回帶頭結點雙向鏈表的頭指標}elsereturn NULL;}
—— 生命的意義,在於賦予它意義。
原創
http://blog.csdn.net/shuangde800
, By
D_Double