版權聲明:本文為部落客原創文章 && 轉載請著名出處 @ http://blog.csdn.net/gatieme
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <assert.h>
//#define debug // 調試插樁資訊宏
///*////////////////////////////////////////////////////////////////////////////
///
/// 帶頭結點的單連結清單結構體
typedef int elemtype; // 自定義資料類型
//typedef struct cirlinklistnode* pcirlinklistnode; // 連結清單結點指針域
// 連結清單結點資料域
typedef struct cirlinklistnode
{
elemtype m_data; // 資料域
struct cirlinklistnode *m_next; // 指針域
}cirlinklistnode;
// 帶頭結點的單項連結清單
typedef struct cirlinklist
cirlinklistnode *m_head; // 連結清單頭結點
cirlinklistnode *m_tail; // 循環連結清單尾部
int m_length; // 單連結清單資料結點個數指針域
// this->m_head == this->m_tail->m_next; // 如果隻設尾結點要了解此等價關系
}cirlinklist;
/// 建立和初始化單連結清單
/// 開辟一個單連結清單資料結構,并初始化頭結點,然後将建立好的單連結清單指針傳回
/// cirlinklist* creatcirlinklist(void)
/// 初始化單連結清單
/// void initcirlinklist(cirlinklist *list)
///*///////////////////////////////////////////////////////////////////////////
/**
cirlinklist* creatcirlinklist(void)
參數
list : 指向一個連結清單指針,此處傳入表頭位址
傳回值
若成功傳回建立好的單連結清單的指針
功能
開辟一個單連結清單資料結構,并初始化頭結點,然後将建立好的單連結清單指針傳回
注意
使用createcirlinklist建立的單連結清單,需要用destroycirlinklist來銷毀
以免發生記憶體洩漏
*/
cirlinklist* createcirlinklist(void)
cirlinklist *list = null;
if((list = (cirlinklist *)malloc(sizeof(cirlinklist))) == null) // 開辟單連結清單的空間
{ // 開辟失敗
fprintf(stderr, "not enough memory when create list...\n");
exit(exit_failure);
}
initcirlinklist(list); // 初始化單連結清單
return list;
}
void initcirlinklist(cirlinklist *list)
無
初始化單連結清單, 執行以下操作
①開辟頭結點的空間 ②進行必要的初始化[頭結點的初始化和單連結清單結點數目的初始化]
使用initcirlinklist初始化的單連結清單(初始化時malloc了頭結點m_head的空間)
而使用用finitcirlinklist來進行後處理(後處理時free了頭結點的m_head空間)
void initcirlinklist(cirlinklist *list)
if((list->m_head = malloc(sizeof(cirlinklistnode))) == null) // 為頭結點開辟空間
fprintf(stderr, "not enough memory when malloc head...");
// 初始化頭結點資訊
list->m_head->m_next = list->m_head; // 初始化隻有頭結點[空循環連結清單的特征]
list->m_head->m_data = 0; // 資料元素個數為0
list->m_length = 0; // 資料元素個數為0
list->m_tail = list->m_head; // 尾指針指向頭結點
/// 銷毀以及後處理單連結清單
/// 銷毀用createcirlinklist建立的單連結清單
/// void destroycirlinklist(cirlinklist *list)
/// 後處理單連結清單,
/// void finitcirlinklist(cirlinklist *list)
/// 清空單連結清單中的所有元素
/// void clearcirlinklist(cirlinklist *list)
void destroycirlinklist(cirlinklist *list)
銷毀用createcirlinklist建立的單連結清單,執行以下操作
①清空單連結清單 ②釋放頭結點 ③釋放單連結清單
cirlinklist* destroycirlinklist(cirlinklist *list)
clearcirlinklist(list); // 清空連結清單
finitcirlinklist(list); // 銷毀頭結點
if(list != null) // 銷毀連結清單的空間
{
free(list);
list = null;
void finitcirlinklist(cirlinklist *list)
後處理單連結清單, 執行以下操作
void finitcirlinklist(cirlinklist *list)
assert(list->m_head->m_next == list->m_head); // 後處理指針針對空連結清單
// assert(list->m_length == 0);
if(list->m_head != null) // 如果此時頭結點空間未被銷毀
free(list->m_head);
list->m_head = null;
list->m_length = -1; // 未經初始化的單連結清單元素個數記為-1
void clearcirlinklist(cirlinklist *list)
清空單連結清單中的所有元素
void clearcirlinklist(cirlinklist *list)
while(list->m_head->m_next != list->m_head)
deletenode(list, 0);
/// 查找函數
/// 查找到連結清單list中第position個結點
/// cirlinklistnode* findposnode(cirlinklist *list, int position)
/// 在連結清單list中找到currnode的前一個結點
/// cirlinklistnode *findprevnode(cirlinklist *list, cirlinklistnode *currnode)
/// 判斷結點node指向的區域是不是連結清單中的結點
/// int isnodeinlist(cirlinklist *list, cirlinklistnode *node)
/// 找到資料域為data的結點首次出現的位置并傳回結點資訊
/// cirlinklistnode* finddatanode(cirlinklist *list, elemtype data, int *position)
cirlinklistnode* findposnode(cirlinklist *list, int position)
positon : 帶查找的連結清單指針的位置
若成功傳回指向待查找結點的指針
若失敗傳回null
該函數的功能是: 查找到連結清單list中第position個結點
cirlinklistnode* findposnode(cirlinklist *list, int position)
assert(list != null); // 連結清單不能為空
assert(position >= -1 && position < list->m_length); // 插入的w位置隻能在[-1~length]
cirlinklistnode *pnode = list->m_head->m_next;
// cirlinklistnode *pnode = list->m_tail->m_next; // 當循環連結清單隻設尾指針時采用此代碼
if(position == -1) // -1表示尋找頭指針的前驅
return list->m_head; // 直接傳回前驅
int pos = 0;
while(pnode != list->m_head && pos < position) // 周遊單連結清單,找到第position個結點的位置
pnode = pnode->m_next;
pos++;
if(pos < position) // 如果找到連結清單尾部還沒有找到
return null;
else
#ifdef debug
printf("find the %d point success...[%p]\n", position, pnode);
#endif // debug
return pnode;
cirlinklistnode *findprevnode(cirlinklist *list, cirlinklistnode *currnode);
list : 指向一個連結清單指針,此處傳入表頭位址
currnode : 待查找的連結清單指針的位置
在連結清單list中找到currnode的前一個結點
cirlinklistnode *findprevnode(cirlinklist *list, cirlinklistnode *currnode)
assert(list != null);
assert(currnode != null);
cirlinklistnode *pnode = list->m_head;
while(pnode->m_next != list->m_head && pnode->m_next != currnode)
if(pnode->m_next == currnode) // 查找成功
else // 查找失敗
int isnodeinlist(cirlinklist *list, cirlinklistnode *node)
node : 指向待查找的結點的指針
若成功 傳回結點node在連結清單中的位置
若失敗 傳回-1
判斷結點node指向的區域是不是連結清單中的結點
int isnodeinlist(cirlinklist *list, cirlinklistnode *node)
assert(list != null); // 連結清單不能為空 assert(node != null); // 待查找的指針不能為空
while(pnode != list->m_head && pnode != node) // 周遊單連結清單,找到第position個結點的位置
if(pnode != node)
{ // 查找成功
return -1;
{ // 查找失敗
printf("find the [%p] point in the first %d pointer of the list...\n", fnode, pos);
return pos;
cirlinklistnode* finddatanode(cirlinklist *list, elemtype data, int *position
data : 待查找的結點的資料資訊
找到資料域為data的結點首次出現的位置并傳回結點資訊
cirlinklistnode* finddatanode(cirlinklist *list, elemtype data, int *position)
cirlinklistnode *node = list->m_head->m_next;
int pos = 0;
while(node != list->m_head && node->m_data != data)
node = node->m_next;
*position = pos; // 将出現的位置傳遞回去
return node; // 傳回結點的資訊
/// 插入函數
/// 将資料data插傳入連結表的prevnode結點的下一個位置個位置
/// cirlinklistnode *addnode(cirlinklist *list, cirlinklistnode *prevnode, elemtype data)
/// 将資料data插傳入連結表的第position個位置
/// cirlinklistnode *insertnode(cirlinklist *list, int position, elemtype data)
cirlinklistnode* addnode(cirlinklist *list, cirlinklistnode *prevnode, elemtype data);
prevnode : 待插入位置的前一個結點
data : 待插入結點的資料
該函數的功能是: 将資料data插傳入連結表的prevnode結點的下一個位置個位置
cirlinklistnode* addnode(cirlinklist *list, cirlinklistnode *prevnode, elemtype data)
assert(prevnode != null); // 插入點不能是空指針
cirlinklistnode *newnode = null;
if((newnode = (cirlinklistnode *)malloc(sizeof(cirlinklistnode))) == null) // 為新結點開辟空間
{ // 開辟新結點失敗
fprintf(stderr, "not enough memeory\n");
// 開辟新結點成功
newnode->m_data = data;
newnode->m_next = null;
// 将指針newnode連接配接在pnode的後面
newnode->m_next = prevnode->m_next;
prevnode->m_next = newnode;
list->m_length++; // 結點數目增加一個
list->m_head->m_data++; // 頭結點的資料域同樣存儲着結點總數
//}
printf("the new node is inserted after point pointer[%p]\n", pnode);
return newnode;
void insertnode(cirlinklist *list, int position, elemtype data)
positon : 待插入結點的位置
data : 待插入結點的資料
該函數的功能是: 将資料data插傳入連結表的第position個位置
cirlinklistnode* insertnode(cirlinklist *list, int position, elemtype data)
assert(list != null);
assert(position >=0 && position < list->m_length + 1);
cirlinklistnode *prevnode = findposnode(list, position - 1); // 找到待插入位置的前一個結點
// 下面調用insertpointnode直接将結點插入到pnode結點後面
if((newnode = addnode(list, prevnode, data)) != null) // 将新的結點插入到待插入前一個指針的後面
{ // 插入成功
return newnode; // 傳回新插入的結點
printf("insert the value %d into list at position %d...\n", data, position);
return null; // 插入失敗傳回null
// // 以可以使用下面的代碼
// if((newnode = (cirlinklistnode *)malloc(sizeof(cirlinklistnode))) == null) // 為新結點開辟空間
// { // 開辟新結點失敗
// fprintf(stderr, "not enough memeory\n");
// exit(exit_failure);
// }
// else
// { // 開辟新結點成功
// newnode->m_data = data;
// newnode->m_next = null;
//
// // 将指針newnode連接配接在pnode的後面
// newnode->m_next = prevnode->m_next;
// prevnode->m_next = newnode;
// list->m_length++; // 結點數目增加一個
// list->m_head->m_data++; // 頭結點的資料域同樣存儲着結點總數
/// 删除函數
/// 删除連結清單list中prevnode結點之後的指針個指針
/// void deletenode(cirlinklist *list, int position)
/// elemtype subnode(cirlinklist *list, cirlinklistnode *prevnode)
/// elemtype deletecurrnode(cirlinklist *list, cirlinklistnode *currnode)
void deletenode(cirlinklist *list, int position)
positon : 待删除結點的位置
傳回待删除結點的資料域
将單連結清單的第position個結點删除
elemtype deletenode(cirlinklist *list, int position)
assert(position >=0 && position < list->m_length);
cirlinklistnode *prevnode = findposnode(list, position - 1); // 找到第position - 1個結點
// 删除pnode的後一個結點
cirlinklistnode *delnode = prevnode->m_next;
elemtype delelem = delnode->m_data;
prevnode->m_next = delnode->m_next;
free(delnode);
list->m_length--; // 結點數目減少一個
list->m_head->m_data--; // 頭結點的資料域同樣存儲着結點總數
return delelem;
elemtype subnode(cirlinklist *list, cirlinklistnode *prevnode)
删除連結清單list中prevnode結點之後的指針個指針
elemtype subnode(cirlinklist *list, cirlinklistnode *prevnode)
assert(list != null); // 連結清單不能為空
assert(prevnode != null); // 待删除結點的前一個位置不能為空
assert(isnodeinlist(list, prevnode) != -1); // 待删除位置的前一個結點必須在連結清單中
elemtype deletecurrnode(cirlinklist *list, cirlinklistnode *currnode);
elemtype deletecurrnode(cirlinklist *list, cirlinklistnode *currnode)
assert(list != null); // 連結清單不能為空
assert(currnode != null); // 待删除結點的前一個位置不能為空
assert(isnodeinlist(list, currnode) != -1); // 待删除的結點必須在連結清單中
elemtype delelem = -1; // 待删除結點的資料域
cirlinklistnode *delnode = null; // 指向将要删除的結點的指針
// if(list->m_length == 0)
// {
// return -1;
// printf("length = %d\n", list->m_length);
if(currnode->m_next != list->m_head) // 如果待删除結點不是最後一個結點
// 将currnode的後一個結點delnode作為删除結點,
delnode = currnode->m_next;
currnode->m_next = delnode->m_next; //從連結清單中删除delnode
// 并将delnode的資料域儲存到delnode中
delelem = currnode->m_data; // delelem儲存currnode的資料域
currnode->m_data = delnode->m_data; // 真正删除的結點其實是currnode下一個結點, 是以用currnode儲存下一個結點的資料域
else // 否則待删除結點是最後一個結點
// 直接将最後一個結點删除即可, 應該把其前一個結點的指針域指派為空
delnode = currnode;
// 下面應該将currnnode的前一個結點的指針域指派為空[時間複雜度o(n)]
cirlinklistnode *prevnode = findprevnode(list, currnode);
prevnode->m_next = list->m_head; /// bug1 最後一個結點的後一個結點
/// 其他函數
/// 顯示單連結清單的資訊
/// void showlist(cirlinklist *list
/// void setnode(cirlinklist *list, int position, elemtype data)
/// 擷取單連結清單list第position個結點的資料域
/// elemtype getnode(cirlinklist *list, int position)
/// 擷取單連結清單list的長度[即元素個數]
/// int lengthcirlinklist(cirlinklist *list)
/// 判斷目前連結清單是否是空連結清單
/// bool isemptycirlinklist(cirlinklist *list)
void showcirlinklist(cirlinklist *list)
顯示單連結清單的資訊
void showlist(cirlinklist *list)
// assert(list->m_head != null)
if(list->m_head == null) // 單連結清單可能沒有被初始化
fprintf(stderr, "you can't show the list without the list initlinklist...\n");
return ;
printf("there are %d data in list\n", list->m_length);
if(list->m_length == 0)
cirlinklistnode *pnode = list->m_head->m_next; // 從頭指針開始周遊
while(pnode != list->m_head) //開始周遊單連結清單
printf("%d ", pnode->m_data);
printf("\n");
// elemtype data;
// for(int pos = 0; pos < list->m_length; pos++)
// data = getnode(list, pos);
// printf("%d ", data);
// printf("\n");
void setnode(cirlinklist *list, int position, elemtype data)
positon : 待修改的結點的資料
data : 待更正的新資料域
修改單連結清單list第position個結點的資料域為data
void setnode(cirlinklist *list, int position, elemtype data)
cirlinklistnode *pnode = findposnode(list, position); // 找到單連結清單的第position個結點
pnode->m_data = data;
elemtype getnode(cirlinklist *list, int position
positon : 待查詢的結點的位置
擷取到的結點資料
擷取單連結清單list第position個結點的資料域
elemtype getnode(cirlinklist *list, int position)
return pnode->m_data;
int lengthcirlinklist(cirlinklist *list)
單連結清單的長度
擷取單連結清單的長度
int lengthcirlinklist(cirlinklist *list)
return list->m_length;
bool isemptycirlinklist(cirlinklist *list)
如果單連結清單是空表,傳回true
否則傳回false
bool isemptycirlinklist(cirlinklist *list)
return (list->m_head->m_next == list->m_head);
// return (list->m_tail == this->m_head);
cirlinklistnode* getfisrtnode(cirlinklist *list)
傳回頭指針
擷取循環連結清單的頭指針
cirlinklistnode* getfisrtnode(cirlinklist *list)
return list->m_head->m_next;
// return list->m_tail->m_next->m_next; // 隻設尾指針的時候使用此代碼
cirlinklistnode* getheadnode(cirlinklist *list)
傳回頭結點的位址
擷取指向頭結點的指針
cirlinklistnode* getheadnode(cirlinklist *list)
return list->m_head;
// return list->m_tail->m_next; // 隻設尾指針的時候使用此代碼
#define list_size 7
// 主函數
int main(void)
int pos;
printf("test 1...\n");
cirlinklist *plist = createcirlinklist( ); // 建立單連結清單
for(int pos = 0; pos < list_size; pos++) // 循環向單連結清單中插入資料
insertnode(plist, pos, pos + 1);
showlist(plist); // 插入結束後顯示單連結清單的資訊
deletenode(plist, 0); // 删除第一個元素
showlist(plist);
deletenode(plist, 1); // 删除第二個元素
clearcirlinklist(plist); // 将單連結清單清空
destroycirlinklist(plist); // 将單連結清單銷毀
plist = null;
printf("\n\ntest 2...\n");
cirlinklist list;
initcirlinklist(&list); // 初始化單連結清單
for(int pos = 0; pos < list_size; pos++) // 訓話向單連結清單中插入資料
insertnode(&list, pos, pos + 1);
showlist(&list); // 顯示單連結清單
clearcirlinklist(&list); // 清空單連結清單
// finitlinklist(&list); // error== list->m_head->m_next == null
showlist(&list);
printf("\n\ntest 3...\n");
cirlinklistnode *prevnode = list.m_head;
cirlinklistnode *addnode = null;
for(int pos = 0; pos < list_size; pos++)
if((addnode = addnode(&list, prevnode, pos + 1)) != null)
{
prevnode = addnode;
}
while(isemptycirlinklist(&list) != true) // 循環删除單連結清單中的資料
//printf("%p == %p\n", list.m_head->m_next, list.m_head);
deletecurrnode(&list, list.m_head->m_next);
return exit_success;
}
轉載:http://blog.csdn.net/gatieme/article/details/42714079