列表的插入排序算法

場景

  • 插入排序算法的描述
    • 適用於序列 (列表/向量)
  • 實現
    • 將序列分成前後兩個序列, 前綴序列是有序的, 後繼序列是無序的,每次循環都將後繼序列的首個節點插入到前綴序列的合適位置

列表插入排序算法實現

// 插入排序: 對於起始於節點p的n個節點進行排序(包含N)    將序列分成有序的前綴和無序的後綴, 反覆的將無序後綴的首元素插入到前綴合適的位置
template <typename T> void List<T>::insertionSort(ListNodePosi (T) p, int n) {
    // p必需是合法的節點 && rank(p) + n <+ _size
    if (!valid(p)) {
        cout << "不合法的節點p" << endl;
        throw STATUS_ERROR;
    }
    ListNodePosi (T) node_small;
    for(int i = 0; i< n; i ++) {
        // 有序前綴中不大於無序後繼首元素的最後一個節點
         node_small = search(p->data, i, p);

        // 首元素插入前綴有序列表
        insertA(node_small, p->data);

        // 更新循環依據
        p = p->succ;

        // 元素後繼的首元素
       remove(p->pred);
    }
}

// 有序列表內節點p的個前驅元素中找到不大於e的最後一個元素
template <typename T> ListNodePosi(T) List<T>::search(T const &e, int n , ListNodePosi(T) p){
    // p可能是trailer
    // 0 <= n <= rank(p) < _size;
    if (n < 0 || n > _size) {
        throw STATUS_ERROR;
    }

    while(n-- >= 0) {
        p = p->pred;
        if (p->data <= e) {
            break;
        }
    }
    return p;
}


// 刪除特定的節點,返回特定的元素
template <typename T> T List<T>::remove(ListNodePosi(T) p) {
    // 備份待刪除節點
    T data = p->data;

    // 當前頁面的上一個節點的後繼節點改成p的後繼節點
    p->pred->succ = p->succ;

    // p的後繼節點改成p的前驅節點
    p->succ->pred = p->pred;

    delete p;

    // 規模減1
    _size --;
    return data;
}

完整代碼

  • ListNode.h 列表節點

using namespace std;
#define ListNodePosi(T) ListNode<T>*

typedef int T;
typedef int Rank;
typedef int RANK;

template<typename T>
struct ListNode {
    T data;
    ListNodePosi(T) pred; // 前綴
    ListNodePosi(T) succ; // 後繼

    // 構造函數
    ListNode(){};

    // 帶參數的構造函數
    ListNode(T e, ListNodePosi(T) p = NULL, ListNodePosi(T) s =NULL) : data(e), pred(p), succ(s) {};

    // 前插入
    ListNodePosi(T) insertAsPred(T const&e);

    // 後插入
    ListNodePosi(T) insertAsSucc(T const&e);
};

template<typename T> ListNodePosi(T)   ListNode<T>::insertAsPred(T const& e){
// 插入新增的節點
    ListNodePosi(T) new_node = new ListNode(e, pred, this);
// 新節點進入連接
    pred->succ = new_node;
    pred = new_node;
    return new_node;
};

// 插入當前節點後面
template<typename T> ListNodePosi(T)  ListNode<T>::insertAsSucc(T const& e){
// 新節點
    ListNodePosi(T) new_node = new ListNode(e, this, succ);

// 當前節點的原後綴節點的前綴節點改成新節點
    succ->pred = new_node;

// 當前節點的後綴節點改成
    succ = new_node;
    return new_node;
};
  • List.h 列表模板類

using namespace std;

#define STATUS_ERROR -1

template<typename T>
class List {
private:
    // 規模
    int _size;

    // 頭節點
    ListNodePosi(T) header;

    // 尾指針
    ListNodePosi(T) trailer;

protected:
    // 列表創建時初始化
    void init();

    // 清除所有節點
    int clear();

    // 複製列表中自位置p起的n項
    void copyNodes(ListNodePosi(T) p,int n);

public:
    // 構造方法
    List() { init(); };

    // 析構方法
    ~List(){
        clear();
        delete trailer;
        delete header;
    };//釋放所有節點

    // 獲取規模
    Rank size() { return _size; };

    // 列表是否爲空
    bool empty() { return _size < 1; }

    // 重載[]
    T& operator[](Rank r);

    // 獲取首節點
    ListNodePosi(T) const first() {
        return header->succ;
    }

    // 獲取末節點
    ListNodePosi(T) const last() {
        return trailer->pred;
    }

    // 某個節點是否合法
    bool valid(ListNodePosi(T) p) {
        // 節點不爲空並且不是頭尾節點
        return p && p != trailer && p != header;
    }

    // 插入首節點
    ListNodePosi(T) insertAsFirst(T const& e){
      _size ++;
      return header->insertAsSucc(e);
    };

    // 插入尾節點
    ListNodePosi(T) insertAsLast(T const& e);

    // 將e當作節點p的後繼插入
    ListNodePosi(T) insertA(ListNodePosi(T) p, T const& e);

    // 將e當作節點p的前驅插入
    ListNodePosi(T) insertB(ListNodePosi(T) p, T const& e);

    // 刪除特定的節點,返回特定的元素
    T remove(ListNodePosi(T) p);

    // 遍歷 函數指針機制遍歷
    void traverse(void (*)(T&));

    // 無序去重
    int deduplicate();

    // 無序列表中查找  沒有找到返回NULL
    ListNodePosi(T) find(T const &e, int n , ListNodePosi(T) p);

    // 有序列表內節點p的個前驅元素中找到不大於e的最後一個元素
    ListNodePosi(T) search(T const &e, int n , ListNodePosi(T) p);

    // 插入排序
    void insertionSort(ListNodePosi(T) p,int n);
};

// 有序列表內節點p的個前驅元素中找到不大於e的最後一個元素
template <typename T> ListNodePosi(T) List<T>::search(T const &e, int n , ListNodePosi(T) p){
    // p可能是trailer
    // 0 <= n <= rank(p) < _size;
    if (n < 0 || n > _size) {
        throw STATUS_ERROR;
    }

    while(n-- >= 0) {
        p = p->pred;
        if (p->data <= e) {
            break;
        }
    }
    return p;
}

// 插入排序: 對於起始於節點p的n個節點進行排序(包含N)    將序列分成有序的前綴和無序的後綴, 反覆的將無序後綴的首元素插入到前綴合適的位置
template <typename T> void List<T>::insertionSort(ListNodePosi (T) p, int n) {
    // p必需是合法的節點 && rank(p) + n <+ _size
    if (!valid(p)) {
        cout << "不合法的節點p" << endl;
        throw STATUS_ERROR;
    }
    ListNodePosi (T) node_small;
    for(int i = 0; i< n; i ++) {
        // 有序前綴中不大於無序後繼首元素的最後一個節點
         node_small = search(p->data, i, p);

        // 首元素插入前綴有序列表
        insertA(node_small, p->data);

        // 更新循環依據
        p = p->succ;

        // 元素後繼的首元素
       remove(p->pred);
    }
}

// 無序列表中查找, 在節點p的n個前驅元素中查數據e, 並返回邏輯次序最大的節點
template <typename T>
ListNodePosi(T) List<T>::find(T const &e, int n , ListNodePosi(T) p){
    // 如果n 異常
    if (n < 0  || n >= _size) {
        throw STATUS_ERROR;
    }

    // 另外rank(p) >= n
    while(n-- > 0) {

        // 循環直到n個結束
        p = p->pred;

        // 如果p節點之前沒有n個節點, 則拋出異常
        if (p == header) {
            throw STATUS_ERROR;
        }

        if (p->data == e) {
            return p;
        }
    }

    return NULL;
}

// 無序列表去重
template <typename T> int List<T>::deduplicate()
{
    // 平凡列表自然無重複
    if (_size < 2) {
        return 0;
    }

    int old_size = _size;

     // 從第二個元素開始每個元素都要和邏輯次序在它之前的節點進行比較
     // 循環節點
    ListNodePosi(T) p = first();
    RANK r = 1;
    while((p = p->succ) != trailer) {

        // p節點之前是否存在這個數據
        ListNodePosi(T) exist_node = find(p->data, r, p);
        exist_node ? remove(exist_node) : r ++;
    }

    return old_size - _size;
}


// 藉助函數指針
template <typename T> void List<T>::traverse(void (*visit)(T &)) {
    for (ListNodePosi(T) p = header->succ; p != trailer ; p = p->succ) {
        visit(p->data);
    }
}

// 刪除特定的節點,返回特定的元素
template <typename T> T List<T>::remove(ListNodePosi(T) p) {
    // 備份待刪除節點
    T data = p->data;

    // 當前頁面的上一個節點的後繼節點改成p的後繼節點
    p->pred->succ = p->succ;

    // p的後繼節點改成p的前驅節點
    p->succ->pred = p->pred;

    delete p;

    // 規模減1
    _size --;
    return data;
}

// 清理掉所有的數據節點,並返回原有節點的數量
template <typename T> int List<T>::clear(){
    int old_size = _size;

    // 反覆刪除首節點,直到列表數據爲空
    while (_size > 0) {
        remove(first());
    }

    return old_size;
}

// 插入尾節點
template <typename T>
ListNodePosi(T) List<T>::insertAsLast(T const& e){
    _size ++;
    return trailer->insertAsPred(e);
}

// 將e當作節點p的後繼插入
template <typename T>
ListNodePosi(T) List<T>::insertA(ListNodePosi(T) p, T const& e){
    _size ++;
    return p->insertAsSucc(e);
}

// 將e當作節點p的前驅插入
template <typename T>
ListNodePosi(T) List<T>::insertB(ListNodePosi(T) p, T const& e){
    // 生成一個新的節點
    _size ++;
    return p->insertAsPred(e);
}


// 重載[]
template<typename T>
T& List<T>::operator[](Rank r) {
    if (r < 0 || r > _size) {
        return -1;
    }

    // 首節點
    ListNodePosi(T) p = first();

    for (int i = 1; i < r; ++i) {
        p = p->succ;
    }
    return p->data;
}

// 初始化列表函數
template<typename T>
void List<T>::init() {
    // 生成頭節點
    header = new ListNode<T>;

    // 生成尾節點
    trailer =new  ListNode<T>;

    // 生成頭尾節點的聯繫
    header->succ = trailer;
    trailer->pred = header;

    header->pred = NULL;
    trailer->succ = NULL;

    // 規模初始化0
    _size = 0;
}


  • main.cpp 主運行程序
#include <iostream>
#include <string>
#include "listNode.h"
#include "list.h"

using namespace std;

#define MAX_AGE 20
#define MIN_AGE 15
#define SIZE 10

int getRandAge()
{
    return MIN_AGE + rand()%(MAX_AGE - MIN_AGE);
};


// 打印列表
template <typename T> void print(T data)
{
    cout << data << " " ;
}

// 給列表賦值
template <typename T> void initAges(List<T> *ages)
{
    int age;
    for (int i = 0; i <SIZE ; ++i) {
        age = getRandAge();
        cout << "age=" << age << endl;
        ages->insertAsFirst(age);
    }
}

// 打印列表
void printAges(List<int> ages){
    // 打印列表的數據
    cout << " 11" << endl;
    ages.traverse(print);
    cout << " 22 "<< endl;
}

int main() {
    List<T> ages;

    // 賦值
    initAges(&ages);

    // 無序列表去重
    ages.deduplicate();

    cout << " " << endl;
    ages.traverse(print);
    cout << " "<< endl;

    // 插入排序
    ages.insertionSort(ages.first(), ages.size());

    // 打印年齡
//    printAges(ages);

    cout << " " << endl;
    ages.traverse(print);
    cout << " "<< endl;

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