1. 程式人生 > >鏈表交集、合並、排序

鏈表交集、合並、排序

ext break bsp 重復元素 鏈表合並 順序 操作 存儲 lis

第四周

要求:

1、將兩個有序的遞增鏈表合並為一個遞增的有序鏈表。要求結果鏈表仍使用原來兩個鏈表的儲存空間,不另外占用其他的儲存空間。表中不允許有重復數據。

2、已知兩個鏈表A和B分別表示兩個集合,其元素遞增排列。設計一個算法用於求出A與B的交集,並存放在A鏈表中。

思路:首先就是創建鏈表。一般有前插法和後插法;二 要求遞增的話可以用一個排序算法(簡單看了一下冒泡排序)。三 鏈表顯示和銷毀函數。

四 重點就是合並和交集函數。註意就是對鏈表操作要釋放多余的存儲空間,比如:頭結點,重復元素結點等

先定義結構

typedef struct LNode//定義結構
{
    
int data; struct LNode *next; }LNode, *Head;

一、創建鏈表(後插法)

Head Create(void)//創建鏈表
{
    LNode *head, *r, *p;
    head = new LNode;
    if (head == NULL)
        cout << "頭結點創建失敗!\n";
    p = head;
    int x, cycle = 1;
    while (cycle) {
        cout << "輸入一個整數.\n";
        cin 
>> x; if (x != 0) { r = new LNode; r->data = x; p->next = r; p = r; } else { cycle = 0; } } p->next = NULL; cout << "鏈表創建成功!\n"; return head; }

二、排序(遞增)

Head Order(Head head)//
鏈表節點排序 { LNode *p = head->next, *q = head->next; if (!p) return head; int i = 0, temp = 0, flag = 1; while (q) { q = q->next; ++i;//數據節點個數i } while (flag && i >= 0) {//冒泡排序 flag = 0; while (p->next != NULL) { if (p->data > p->next->data) { temp = p->data; p->data = p->next->data; p->next->data = temp; flag = 1;//標誌置為1表示本輪有交換 } p = p->next; } --i; p = head->next;//重新指向首元結點為下輪準備 } return head; }

三、鏈表顯示

Status print(Head head)
{
    int i = 0;
    LNode *p = head;
    while (!p)
        return OK;
    while (p->next != NULL)
    {
        p = p->next;
        cout << p->data;
        cout << "   ";
        ++i;
    }
    cout << "   共有"<<i<<"個元素\n";
    return OK;
}

四、銷毀鏈表

Status DestroyList(Head head)
{
    LNode *p;
    while (head->next != NULL)
    {
        p = head;
        head = head->next;
        delete p;
    }
    delete head;
    return OK;
}

五、鏈表交集

交集AB鏈表放入A鏈表中,釋放B鏈表;head1為A鏈表,head2為B鏈表。

Head Intersection(Head head1, Head head2)//交集放入A鏈表
{
    LNode *head = NULL, *p1 = NULL, *p2 = NULL, *p = NULL;
    head = head1;
    //交集為空
    while (head1->next==NULL || head2->next==NULL) {
        while (head2->next != NULL)//A為空鏈表 直接刪除B鏈表
        {
            p = head2;
            head2 = head2->next;
            delete p;
        }
            delete head2;
            return head1;
            break;
    }
    LNode *move = head, *temp = NULL;
    p1 = head1->next;
    p2 = head2->next;
    delete head2;
    //AB均不為空
    while (p1&&p2->next != NULL){
        if (p1->data < p2->data)
            p1 = p1->next;
        else if (p1->data > p2->data)
            p2 = p2->next;
        else if (p1->data == p2->data)
        {
            move->next = p1;
            move = p1;
            p1 = p1->next;
        }
    }
    if (p2->next == NULL) {//判斷B鏈表最後一個結點
        if (p1->data == p2->data)
        {
            move->next = p1;
            move = p1;
            p1 = p1->next;
        }
    }
        move->next = NULL;//尾部指針為NULL
    return head;
}

六、鏈表合並

這裏AB合並後放入B鏈表中。

Head Combine(Head head1, Head head2)//合並後放入B鏈表
{
    LNode *head=head2, *p1=NULL, *p2=NULL;
    if (head1->next==NULL) {//A為空鏈表或者AB都為空
        delete head1;
        return head2;
    }
    else if (head2->next == NULL) {//B為空鏈表
        head2->next = head1->next;//A鏈表賦給B鏈表
        delete head1;
        return head2;
    }
    p1 = head1->next;
    p2 = head2->next;
    delete head1;
    LNode *move = head, *temp = NULL;
    //按遞增順序依次鏈接
    while (p1&&p2) {
        if (p1->data < p2->data) {
            move->next = p1;
            move = p1;
            p1 = p1->next;
        }
        else if (p1->data > p2->data) {
            move->next = p2;
            move = p2;
            p2 = p2->next;
        }
        else if(p1->data == p2->data) {//相同數據只保存一個,p1p2向後移一位
            temp = p2;
            move->next = p1;
            move = p1;
            p1 = p1->next;
            p2 = p2->next;
            delete temp;//刪除p2相同結點
        }

    }
    if (p1)//p2為NULL,直接連接p1後面的結點
        move->next = p1;
    if (p2)//p1為NULL,直接連接p2後面的結點
        move->next = p2;
    return head;
}

測試

int main()
{
    cout << "創建一個鏈表A. 輸入0結束\n";
    Head head1 = Create();
    cout << "創建一個鏈表B. 輸入0結束\n";
    Head head2 = Create();
    char ch;
    while (1) {
        cout << "---------------------------------------------------------------------------\n";
        cout << "+請選擇要進行的操作:<a>顯示A   <b>顯示B   <c>交集AB   <d>合並AB   <x>退出+\n";
        cout << "---------------------------------------------------------------------------\n";
        ch = _getwch();
        if (ch == a) {
            cout << "A鏈表:";
            print(Order(head1));
        }
        else if (ch == b) {
            cout << "B鏈表:";
            print(Order(head2));
        }
        else if (ch == c) {
            cout << "AB交集為:";
            print(Order(Intersection(head1, head2)));
            cout << "輸入任意字符結束\n";
            ch = _getwch();
            DestroyList(head1);
            break;
        }
        if (ch == d) {
            cout << "AB合並為:";
            print(Order(Combine(head1, head2)));
            cout << "輸入任意字符結束\n";
            ch = _getwch();
            DestroyList(head2);
            break;
        }
        else if (ch == x) {
                break;
        }
    }

}

運行結果:

交集:

技術分享圖片

合並:

技術分享圖片

鏈表交集、合並、排序