1. 程式人生 > >C資料結構-優化連結串列與鏈隊

C資料結構-優化連結串列與鏈隊

優化連結串列與鏈隊

筆者上一個版本的連結串列,在尾部插入或刪除的操作時,需要使用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);
}