C資料結構-優化連結串列與鏈隊
阿新 • • 發佈:2018-12-21
優化連結串列與鏈隊
筆者上一個版本的連結串列,在尾部插入或刪除的操作時,需要使用for迴圈挪動到尾部,這樣時間複雜度就位O(n)。再用其來實現鏈隊的話,那麼鏈隊的入隊和出隊的時間複雜度也會因此受限。如果在連結串列中加入一個指標,指向尾部元素。那麼這個問題就可以迎刃而解。下面是優化過後的連結串列,和鏈隊的程式碼。
#ifndef LINKEDLIST_H #define LINKEDLIST_H #ifndef NULL #define NULL 0 #endif /* 元素型別 */ typedef int elem_t; /* 節點結構體 */ typedef struct _tag_linked_list_node { elem_t data; struct _tag_linked_list_node *next; }ll_node; /* 連結串列結構體 */ typedef struct _tag_linked_list { ll_node head; /* 啞結點 */ ll_node *tail; /* 尾部元素指標 */ int length; /* 連結串列長度 */ }linked_list; /** * 建立連結串列 * @return 返回連結串列指標,NULL表示建立失敗 */ linked_list *linked_list_create(); /** * 從頭部插入元素 * @param plist 連結串列指標 * @param pe 被插入元素的指標 * @return 1:成功 0:失敗 */ int linked_list_insert(linked_list *plist,elem_t *pe); /** * 從尾部插入元素 * @param plist 連結串列指標 * @param pe 被插入元素的指標 * @return 1:成功 0:失敗 */ int linked_list_append(linked_list *plist,elem_t *pe); /** * 查詢元素 * @param plist 連結串列指標 * @param i 元素位置索引 * @param pe 用於儲存被查詢元素的值的指標 * @return 1:成功 0:失敗 */ int linked_list_get(linked_list *plist,int i,elem_t *pe); /** * 按索引刪除元素 * @param plist 連結串列指標 * @param i 被刪除元素的索引 * @param pe 用於儲存被刪除元素的值的指標 * @return 1:成功 0:失敗 */ int linked_list_remove(linked_list *plist,int i,elem_t *pe); /** * 連結串列反轉 * @param plist 連結串列指標 * @return 1:成功 0:失敗 */ int linked_list_reverse(linked_list *plist); /** * 連結串列合併,將第二個連結串列連結到第一個連結串列,第二個連結串列指標置空 * @param dest 合併的目標連結串列 * @param pp_src 被合併的連結串列的指標的指標 * @return 返回合併後的連結串列的指標(第一個引數) */ linked_list *linked_list_merge(linked_list *dest,linked_list **pp_src); /** * 獲取連結串列的長度 * @param plist 連結串列的指標 * @return 返回連結串列的長度,-1表示出錯 */ int linked_list_length(linked_list *plist); /** * 判斷連結串列是否為空 * @param plist * @return */ int linked_list_empty(linked_list *plist); /** * 清空連結串列 * @param plist 連結串列指標 * @return 1:成功 0:失敗 */ int linked_list_clear(linked_list *plist); /** * 銷燬連結串列 * @param plist 連結串列指標 * @return 1:成功 0:失敗 */ int linked_list_destroy(linked_list *plist); #endif // LINKEDLIST_H
#include "LinkedList.h" #include <malloc.h> /** * 建立連結串列 * @return 返回連結串列指標,NULL表示建立失敗 */ linked_list *linked_list_create() { linked_list *plist = (linked_list *)malloc(sizeof(linked_list)); if(plist != NULL) { plist->length = 0; plist->head.next = NULL; plist->tail = NULL; } return plist; } /** * 從頭部插入元素 * @param plist 連結串列指標 * @param pe 被插入元素的指標 * @return 1:成功 0:失敗 */ int linked_list_insert(linked_list *plist,elem_t *pe) { int ret = ( (plist != NULL) && (pe != NULL)); if(ret) { ll_node *node = (ll_node *)malloc(sizeof(ll_node)); ll_node *head = &(plist->head); if(node != NULL) { node->next = head->next; head->next = node; node->data = *pe; /* 判斷是否是第一個元素 */ if(plist->length == 0) { /* 尾指標指向第一個元素 */ plist->tail = node; } plist->length++; } else { ret = 0; } } return ret; } /** * 從尾部插入元素 * @param plist 連結串列指標 * @param pe 被插入元素的指標 * @return 1:成功 0:失敗 */ int linked_list_append(linked_list *plist,elem_t *pe) { int ret = ( (plist != NULL) && (pe != NULL)); if(ret) { ll_node *node = (ll_node *)malloc(sizeof(ll_node)); if(node != NULL) { node->next = NULL; node->data = *pe; if(plist->length == 0) { plist->tail = node; plist->head.next = node; } else { plist->tail->next = node; plist->tail = node; } plist->length++; } else { ret = 0; } } return ret; } /** * 查詢元素 * @param plist 連結串列指標 * @param i 元素位置索引 * @param pe 用於儲存被查詢元素的值的指標 * @return 1:成功 0:失敗 */ int linked_list_get(linked_list *plist,int i,elem_t *pe) { int ret = ( (plist != NULL) && (pe != NULL) && (i >= 0) && (i < plist->length)); if(ret) { int pos = 0; ll_node *current = plist->head.next; /* 移動到尾部 */ for(pos = 0;pos < i;pos++) { current = current->next; } *pe = current->data; } return ret; } /** * 按索引刪除元素 * @param plist 連結串列指標 * @param i 被刪除元素的索引 * @param pe 用於儲存被刪除元素的值的指標 * @return 1:成功 0:失敗 */ int linked_list_remove(linked_list *plist,int i,elem_t *pe) { int ret = ( (plist != NULL) && (pe != NULL) && (i >= 0) && (i < plist->length)); if(ret) { int pos = 0; ll_node *pre = &(plist->head); for(pos = 0;pos < i;pos++) { pre = pre->next; } /* 儲存要被刪除的元素的值 */ *pe = pre->next->data; pre->next = pre->next->next; plist->length--; } return ret; } /** * 連結串列反轉 * @param plist 連結串列指標 * @return 1:成功 0:失敗 */ int linked_list_reverse(linked_list *plist) { int ret = (plist != NULL); if(ret) { if(plist->length > 1) { ll_node *tail = plist->tail; /* 將頭元素的位置調整到原尾元素的後部插入 */ while(plist->head.next != tail) { /* 儲存頭部元素的指標 */ ll_node *old_head = plist->head.next; /* 調整頭結點指標的位置,指向原頭部的下一個元素 */ plist->head.next = old_head->next; /* 將儲存的原頭部元素插入到原尾部元素的後面 */ old_head->next = tail->next; tail->next = old_head; } } } return ret; } /** * 連結串列合併,將第二個連結串列連結到第一個連結串列,第二個連結串列指標置空 * @param dest 合併的目標連結串列 * @param pp_src 被合併的連結串列的指標的指標 * @return 返回合併後的連結串列的指標(第一個引數) */ linked_list *linked_list_merge(linked_list *dest,linked_list **pp_src) { if((dest != NULL) && ( (*pp_src) != NULL) && ((*pp_src)->length != 0)) { dest->tail->next = (*pp_src)->head.next; dest->length += (*pp_src)->length; free(*pp_src); *pp_src = NULL; } return dest; } /** * 獲取連結串列的長度 * @param plist 連結串列的指標 * @return 返回連結串列的長度,-1表示出錯 */ int linked_list_length(linked_list *plist) { int ret = -1; if(plist != NULL) { ret = plist->length; } return ret; } /** * 判斷連結串列是否為空 * @param plist * @return */ int linked_list_empty(linked_list *plist) { return (plist->length == 0); } /** * 清空連結串列 * @param plist 連結串列指標 * @return 1:成功 0:失敗 */ int linked_list_clear(linked_list *plist) { int ret = ((plist != NULL) && (plist->length != 0)); if(ret) { ll_node *head = &(plist->head); while(head->next != NULL) { ll_node *del = head->next; head->next = del->next; free(del); } plist->length = 0; } return ret; } /** * 銷燬連結串列 * @param plist 連結串列指標 * @return 1:成功 0:失敗 */ int linked_list_destroy(linked_list *plist) { int ret = (plist != NULL); if(ret) { linked_list_clear(plist); free(plist); } return ret; }
#ifndef LINKEDQUEUE_H #define LINKEDQUEUE_H #include "LinkedList.h" typedef linked_list linked_queue; /** * 建立佇列 * @return */ linked_queue *linked_queue_create(); /** * 入隊 * @param p 佇列指標 * @return 成功:1,失敗:0 */ int linked_queue_enqueue(linked_queue *p,elem_t *pe); /** * 出隊 * @param p 佇列指標 * @return 成功:1,失敗:0 */ elem_t linked_queue_dequeue(linked_queue *p); /** * 獲取對頭元素的值 * @param p 佇列指標 * @return */ elem_t linked_queue_header(linked_queue *p); /** * 獲取佇列長度 * @param p * @return */ int linked_queue_length(linked_queue *p); /** * 佇列清空 * @param p * @return */ int linked_queue_clear(linked_queue *p); /** * 銷燬佇列 * @param p * @return */ int linked_queue_destroy(linked_queue *p); #endif // LINKEDQUEUE_H
#include "LinkedQueue.h"
/**
* 建立佇列
* @return
*/
linked_queue *linked_queue_create()
{
return linked_list_create();
}
/**
* 入隊
* @param p 佇列指標
* @return 成功:1,失敗:0
*/
int linked_queue_enqueue(linked_queue *p,elem_t *pe)
{
return linked_list_append(p,pe);
}
/**
* 出隊
* @param p 佇列指標
* @return 成功:1,失敗:0
*/
elem_t linked_queue_dequeue(linked_queue *p)
{
elem_t temp;
linked_list_remove(p,0,&temp);
return temp;
}
/**
* 獲取對頭元素的值
* @param p 佇列指標
* @return
*/
elem_t linked_queue_header(linked_queue *p)
{
elem_t temp;
linked_list_get(p,0,&temp);
return temp;
}
/**
* 獲取佇列長度
* @param p
* @return
*/
int linked_queue_length(linked_queue *p)
{
return linked_list_length(p);
}
/**
* 佇列清空
* @param p
* @return
*/
int linked_queue_clear(linked_queue *p)
{
return linked_list_clear(p);
}
/**
* 銷燬佇列
* @param p
* @return
*/
int linked_queue_destroy(linked_queue *p)
{
return linked_list_destroy(p);
}