鏈表ALDS1-3-C:Doubly Linked List

         如圖4.8所示,表中的各元素稱作“結點”。雙向鏈表的結點是結構體,由數據本體(這裏是整數key)、指向前一元素的指針prev以及指向後一元素的指針next組成。這些結構體通過指針連接成一個鏈,就形成了雙向鏈表。


program4.3 C++雙向鏈表的結點

strcut Node {
   int key;
   Node *prev, *next; 
};

        另外,在表頭設置一個特殊的結點可以簡化鏈表的實現。我們將這個結點稱爲“頭結點”。頭結點中雖然不包含實際數據,但他可以讓我們更輕鬆的對鏈表做更改。比如加入頭結點之後,我們將更容易實現刪除元素的操作。



      init函數用於初始化鏈表。如圖4.9所示,它會生成一個NIL結點作爲鏈表的頭結點,然後讓prev和next都指向這個結點,從而創造一個空表。

program4.4 初始化雙向鏈表

Node *nil;

void init() {
	nil = (Node *)malloc(sizeof(Node));
	nil->next = nil;
	nil->prev = nil;
} 
        頭結點是添加元素的起點。這裏的malloc是C語言標準庫中的函數,用於動態申請指定大小的空間。另外,“->”是通過指針變量訪問成員的運算符,稱爲箭頭運算符。




        insert函數用於生成包含所輸入鍵值的結點,並將該結點添加到標的開頭。如圖4.10所示這個函數會以頭結點爲起點分四步改變指針所指的方向。


program4.5 往雙向表中插入元素

void insert(int key) {
	Node *x = (Node *)malloc(sizeof(Node));
	x->key = key;
	//在頭結點後添加元素
	x->next = nil->next;
	nil->next->prev = x;
	nil->next = x;
	x->prev = nil; 
} 




      listSearch函數用於搜索元素,它可以在鏈表中尋找包含指定鍵值的結點,並返回其指針。假設cur爲指向當前位置結點的指針,只要從頭結點的next所指的結點,即鏈表開頭的元素開始逐個執行cur = cur -> next,即可逐一訪問每個結點。

program4.6 在雙向鏈表中搜索元素

Node* listSearch(int key) {
	Node *cur = nil->next;  //從頭結點後面的元素開始訪問
	while( cur != nil && cur->key != key) {
		cur = cur->next;
	} 
	retrun cur;
}

        在訪問過程中發現key或者指針回到頭結點NIL時結束搜索,並返回此時cur的值。




        deleteNode函數會通過如圖4.11所示的步驟改變指針所指的位置,從而刪除指定的結點t。在C++中,我們必須手動釋放已刪除結點的內存。這裏的free時C語言標準庫中的函數,用於釋放已不需要的內存空間。


program4.7 從雙向鏈表中刪除元素

void deleteNode(Node *t) {
	if( t == nil )  return;
	t->prev->next = t->next;
	t->next->prev = t->prev;
	free(t);
}

void deleteFirst() {
	deleteNode( nil->next );
}

void deleteLast() {
	deleteNode( nil->prev );
}

void deleteKey(int key)  {
	//刪除已搜索到的結點
	deleteNode( listSearch(key)); 
}




例題;


代碼:

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
struct Node  {
	int key;
	Node *next,*prev;
};

Node *nil;

void init()  {      //初始化 
	nil = (Node *)malloc(sizeof(Node));
	nil->next = nil;
	nil->prev = nil;
}

Node* listSearch(int key)  {    //找出含有鍵值key的結點 
    Node *cur = nil->next;
    while( cur != nil && cur->key != key)  {
    	cur = cur->next;
	}
	return cur;
}

void insert(int key)  {       //在頭節點後插入某個元素 
	Node *x = (Node *)malloc(sizeof(Node));
	x->key = key;
	x->next = nil->next;
	nil->next->prev = x;
	nil->next = x;
	x->prev = nil;
}

void deleteNode(Node *t)  {     //刪除結點 被下面調用函數  調用 
	if( t == nil)  return;
	t->prev->next = t->next;
	t->next->prev = t->prev;
	free(t);  //釋放已經不需要的內存空間 
}

void deleteFirst()  {    //刪除頭結點next所指向的結點 
	deleteNode(nil->next);
}

void deleteLast()  {    //刪除頭結點prev所指向的結點 
	deleteNode(nil->prev);
}

void deleteKey(int key) {
	deleteNode(listSearch(key));  //刪掉搜索到的結點 
}

void printList()  {      //打印鏈表 
	Node *cur = nil->next;
	int isf = 0;
	while(1)  {
		if( cur == nil ) break;
		if(isf++ > 0) printf(" ");
		printf("%d",cur->key);
		cur = cur->next;
	}
	printf("\n");
} 
int main()
{
	int n,key,i;
	char com[20];
	cin>>n;
	init();
	int size = 0,np = 0,nd = 0;
	for( i=0; i<n; i++ )  {
		scanf("%s%d",com,&key);
		if( com[0] == 'i')  {  insert(key);  np++;  size++;}
			 else if( com[0] == 'd')  {
			if( strlen(com) > 6)  {
				if( com[6] == 'F')  deleteFirst();
				else if( com[6] == 'L')  deleteLast();
				}  else  {
					deleteKey(key);  nd++;
				}
				size--;
			}
		}
		printList();
	return 0;
}
/*
7
insert 5 
insert 2
insert 3
insert 1
delete 3
insert 6
delete 5
*/





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章