[代碼分享]靜態鏈表,接口仿照STL設計,操作未做封裝

很久沒有來CSDN,也很久沒有寫東西了。去年12月在OSCHINA註冊了號,發了兩段code。這次轉過來,以便日後查閱。

連接:http://www.oschina.net/code/snippet_737017_16964

這是一段靜態鏈表的實現,其間用到了一種簡單的內存管理策略——空閒鏈表。

這段代碼裏的“靜態”是一個預先分配好的 node array,實際情況下可能會是一個一次性申請的較大的memory block。

其實是在這段 node array上維護兩個鏈表,一個used list,一個free list,即代碼中的idata,和ifree。

// 靜態鏈表 的實現
#include <stdio.h>

#define MAXN 16 // capacity of list.
typedef int element; // element type.

// define boolean type:
typedef int bool;
#define true -1
#define false 0

#define NPTR -1 // null pointer definition. can not between 0 to MAXN-1.
typedef int pointer;

#define DEBUGVAL(x) printf("%s: %d\n", #x, (x)); // a macro for debug.

struct __node
{
	element data;
	pointer next;
}SLList[MAXN];
pointer ifree, idata;

#define nextof(p) SLList[p].next
#define dataof(p) SLList[p].data

#define _alloc(d) ifree; dataof(ifree)=(d); ifree != NPTR ? ifree=nextof(ifree) : NPTR
#define _free(p)  nextof(p)=ifree; ifree = p

void init()
{
	int i;
	ifree = 0;
	idata = NPTR;
	for( i=0; i < MAXN-1; i++) 
		nextof(i) = i+1;
	nextof(i) = NPTR;
}

// clear all nodes.
void clear() { init(); }

// push val to front.
bool push_front(element val)
{
	pointer tmp, np;
	if( ifree != NPTR ) {
		np = _alloc(val);
		nextof(np) = idata;
		idata = np;
		return true;
	}
	return false;
}

// push val to end of list.
bool push_back(element val)
{
	if( idata == NPTR ) { // 空表,直接寫入
		idata = _alloc(val);
		nextof(idata) = NPTR;
		return true;
	}
	if( ifree != NPTR ) { // 非空,先找到最後一個節點
		pointer last = idata, np;
		while( nextof(last) != NPTR ) last = nextof(last);		
		np = _alloc(val);
		nextof(np) = NPTR;
		nextof(last) = np;
		return true;
	}
	return false;
}

// insert val to after p pointed node.
bool insert_after(pointer p, element val)
{
	if( ifree != NPTR && p != NPTR ) {
		pointer pn = _alloc(val);
		nextof(pn) = nextof(p);
		nextof(p)  = pn;		
		return true;
	}
	return false;
}

// insert to the position in front of p.
bool insert(pointer ptr, element val)
{
	if( ifree == NPTR ) return false;  // 沒有結點,直接返回
	if( ptr == idata ) { // 有一個節點
		pointer np = _alloc(val);
		nextof(np) = idata;
		idata = np;	
		return true;
	}
	else { // 其他情況,先找 ptr 的前驅,再插入
		pointer p = idata;
		while(  p != NPTR ) {
			if( nextof(p) == ptr ) { // find p -- the prev node of ptr.
				return insert_after(p, val); // insert val after p.			
			}
		   p = nextof(p);
		}
	}
	return false;
}

// find element, return the prev node pointer.
pointer find_prev(element val)
{
	pointer p = idata;
	while(  p != NPTR ) {
		if( dataof( nextof(p) ) == val )
			return p;
		p = nextof(p);
	}
	return NPTR;
}

// find element, return the node  pointer.
pointer find(element val)
{
	pointer p = idata;
	while(  p != NPTR ) {
		if( dataof(p) == val ) return p;
		p = nextof(p);
	}
	return NPTR;
}

// pop front element.
void pop_front()
{
	if( idata != NPTR ) { // 將 data list 最前面的節點 移到 free list 上
#if 0
		pointer p = idata;		
		idata = nextof(idata); // idata = nextof(idata);
		nextof(p) = ifree;  // SLList[p].next = ifree;
		ifree = p; 
#else
		pointer p = idata;
		idata = nextof(idata);
		_free(p);
#endif
	}
}

// pop back element.
void pop_back()
{
	if( idata == NPTR ) return;
	if( nextof(idata) == NPTR ) { // only 1 node.
		nextof(idata) = ifree;
		ifree = idata;
		idata = NPTR;
	}
	else { // 找到最後一個節點 p,以及它的前驅 q.
		// TODO: find the lase nod p, and it's perv node q. 
		pointer p = idata, q; 
		while( nextof(p) != NPTR ) {
			q = p;
			p = nextof( p );
		}
		// remove *p to free list, update nextof(q) to NPTR.
		nextof(p) = ifree;
		ifree = p;
		nextof(q) = NPTR;
	}
}

完整代碼及測試見:http://www.oschina.net/code/snippet_737017_16964

記得曾經在反《算法導論》的時候好像看到書中提到靜態鏈表的實現問題,當時沒有在意,直到去年寫下這段代碼的時候任然沒有詳細去看;今天翻出電子版一看,有近兩頁篇幅描述。

《算法導論》中的描述還是較爲精煉的,文字不多,條理清晰,這裏有一副原書中的插圖,書中先講了在沒有指針的語言中如何表示指針和對象;


然後,話鋒一轉,在這樣的情況下“Thus, it is useful to manage the storage of objects not currently used in the linked-list representation so that one can be allocated.”

然後書中也給出了僞代碼:(要是早知道,我也那個夜晚也不用搞到兩點了

ALLOCATE-OBJECT()
 if free = NIL
   then error "out of space"
 else x ← free
   free ← next[x]
   return x
FREE-OBJECT(x)
1 next[x] ← free
2 free ← x


發佈了31 篇原創文章 · 獲贊 40 · 訪問量 14萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章