<acronym id="xonnx"></acronym>
      <td id="xonnx"></td>
    1. <pre id="xonnx"></pre>

      1. 專注電子技術學習與研究
        當前位置:單片機教程網 >> MCU設計實例 >> 瀏覽文章

        集合交差并三種操作的C實現

        作者:龔平   來源:本站原創   點擊數:  更新時間:2014年03月13日   【字體:

           這段時間一直在看C++相關的數據結構,感覺STL庫的出現確實給C++實現一些基本的數據結構更加的方便,特別是map、list、set、vector的靈活運用能實現很多強大的數據結構,記得在一本書中曾經讀到過“C++中算法的重要性沒有C語言中那么明顯,而是設計方法的問題”這句話的正確性有待于進一步的考察,但是面向對象中的更多的是依靠繼承多態性實現多對象編程,而在C語言中更多的事依靠算法和數據結構;艘煌砩喜捎肅語言實現了一個簡單的集合操作,支持集合的創建,元素的查詢,刪除,支持集合的交集、差集、并集計算。
         
            首先說明一下集合的ADT,肯定有包括基本的創建、刪除操作。以及某一個元素的插入和刪除操作。集合的一個重要特征就是元素的不重復性。這種方式我在實現的過程中通過鏈表管理一個集合,按照元素的大小進行排列,之所以排列主要是為了方便刪除、查找元素的操作。實質上集合對元素的順序是沒有要求的。
            集合的交集:是指兩個集合元素相同的部分構成的集合。
            集合的差集:是指其中一個集合中除去另一個集合相同元素以后剩余的元素構成的集合。
            集合的并集:是指兩個集合的所有元素構成的集合。
         
            其中需要注意的就是集合的元素是不能重復的,本來我打算采用二叉查找樹的方式實現,因為這種樹型結構便于快速的查詢,但是我采用元素的升序排序就能避免集合中漫無目的的查詢操作。畢竟實現二叉查找樹也增加了一個指針成員,而且還需要大量的操作。
         
        簡要的說明一下我的過程:
        基本的集合結構體:

         

            typedef struct linknode
            {
                struct linknode *next;
                int value;
            }Node_t, *Node_handle_t;

            typedef struct set
            {
                unsigned int size;
                Node_handle_t head;
            }Set;

         
        集合的創建,該函數的實現是集合實現的最復雜的一個函數,之所以這么復雜是因為很多的操作都是基于該函數完成的,當然也可以采用更精細的函數來實現,我開始的想法是將元素插入和創建操作合并,都基于一個函數進行操作,但是寫完以后發現函數太長,而且比較爛,不夠必將還是完成了一些基本的操作。采用了升序存儲的方式,主要是為了后續的查找操作,注意鏈表的更新操作。

         

            bool create_set(Set **sets, int data)
            {
                Set * temp = (Set *)malloc(sizeof(Set)/sizeof(char));
                Node_t *node = NULL;
                Node_t *head = NULL;

                if(*sets == NULL)
                {
                    temp->size = 0;
                    temp->head = NULL;
                    *sets = temp;
                    node = (Node_t *)malloc(sizeof(Node_t)/sizeof(char));
                    if(node != NULL)
                    {
                        node->next = NULL;
                        node->value = data;
                        /*更新集合指針*/
                        temp->head = node;
                        temp->size ++;
                        *sets = temp;
                       
                        temp = NULL;
                        return true;
                    }
                }
                else/*已經存在部分集合*/
                {
                    /******************************
                    采用順序存儲的方式插入新的元素
                    首先查找是否存在值,有不做任何操作
                    不存在,則按值大小找到合適的位置
                    ******************************/

                    /*遍歷*/
                    if((*sets)->head != NULL)
                    {
                        /*更新表頭*/
                        if((*sets)->head->value > data)
                        {
                            node = (Node_t *)malloc(sizeof(Node_t)/sizeof(char));
                            if(node == NULL)
                                return false;
                            node->next = (*sets)->head;
                            node->value = data;
                            (*sets)->head = node;
                            (*sets)->size ++;

                            return true;
                        }
                        else if((*sets)->head->value == data)
                        {
                            return true;
                        }

                        /*從下一個節點開始*/
                        head = (*sets)->head;
                        node = head;

                        while(head->next != NULL)
                        {
                            /*已經存在*/
                            if(head->next->value == data)
                            {
                                return true;
                            }
                            /*找到合適的位置,并插入*/
                            else if(head->next->value > data)
                            {
                                node = (Node_t *)malloc(sizeof(Node_t)/sizeof(char));
                                if(node == NULL)
                                    return false;
                                node->value = data;
                                node->next = head->next;
                                head->next = node;
                                (*sets)->size ++;

                                return true;
                            }
                            else
                            {
                                head = head->next;
                            }
                        }
                        /*說明以上不存在該值*/
                        node = (Node_t *)malloc(sizeof(Node_t)/sizeof(char));
                        if(node == NULL)
                            return false;
                        node->value = data;
                        node->next = NULL;
                        head->next = node;
                        (*sets)->size ++;
                        return true;
                    }
                    else
                    {
                        node = (Node_t *)malloc(sizeof(Node_t)/sizeof(char));
                        if(node == NULL)
                            return false;
                        node->value = data;
                        node->next = NULL;
                        (*sets)->head = node;
                        (*sets)->size ++;
                        return true;
                    }
                }
                return false;
            }


        查找、刪除元素操作,充分利用了前面的升序存儲關系。

         

            /***************************************
                    刪除集合中的某個元素

            參數:        指向集合指針的指針
                        需要刪除的元素
            返回值:    是否刪除成功
            ***************************************/
            bool delete_setElement(Set **s, int element)
            {
                Node_t *head = NULL;
                Node_t *temp = NULL;
               
                assert(*s);

                head = (*s)->head;
               
            //    assert(head);
                if(head == NULL)
                {
                    return false;
                }
                /*表頭更新*/
                if(head->value == element)
                {
                    temp = head;
                    if(head->next != NULL)
                        head = head->next;
                    else
                        head = NULL;

                    (*s)->head = head;
                    (*s)->size --;
                    free(temp);
                    temp = NULL;

                    return true;
                }

                while(head->next != NULL)
                {
                    /*刪除元素*/
                    if(head->next->value == element)
                    {
                        temp = head->next;
                        head->next = head->next->next;
                        free(temp);
                        (*s)->size --;
                        temp = NULL;
                        break;
                    }
                    /*不存在當前元素*/
                    else if(head->next->value > element)
                        break;
                    else
                        head = head->next;
                }
                return true;
            }

            /****************************************
                        判斷元素是否在集合中
            參數:        集合指針
                        元素值
            返回值:        是否存在
            *****************************************/
            bool findElement(const Set *s, int Element)
            {
            //    assert(s);
                if(s == NULL)
                {
                    return false;
                }

                Node_t *head = s->head;
                while(head != NULL)
                {
                    /*找得到當前值*/
                    if(head->value == Element)
                        return true;
                    /*不存在當前值*/
                    else if(head->value > Element)
                        break;
                    head = head->next;
                }

                return false;
            }

        最重要的一個函數,我認為是集合的復制函數,這有點類似在C++中的復制構造或者賦值操作符函數。

         

            /****************************************
                    實現集合的復制操作
            參數:    一個指向被創建集合的指針
                    一個集合指針
            返回:    判斷是否成功
            ****************************************/
            bool copySet(Set **dst,const Set *src)
            {
                Node_t *head = NULL;

                assert(src);
               
                head = src->head;

                creat_nullset(dst);
               
                while(head != NULL)
                {
                    if(!create_set(dst,head->value))
                        return false;
                    head = head->next;
                }

                return true;
            }

        最后是集合的三個操作:主要是利用了前面定義的一些函數實現的,所以說前面的問題處理好了,基本的操作就是手到擒來的事。

         

            /****************************************
                    實現兩個集合的并集
            參數:
                    分別是兩個Set集合的指針
            返回值:
                    一個集合的指針
            *****************************************/
            Set * OrSets(const Set * s1, const Set *s2)
            {
                Set *news = NULL;
                const Set *searchset = NULL;
                Node_t *head = NULL;

                assert(s1 != NULL || s2 != NULL);

                if(get_setlength(s1) > get_setlength(s2))
                {
                    copySet(&news,s1);
                    searchset = s2;
                }
                else
                {
                    copySet(&news, s2);
                    searchset = s1;
                }
                head = searchset->head;
                while(head != NULL)
                {
                    if(!create_set(&news, head->value))
                        break;
                    head = head->next;
                }
                return news;
            }

            /*******************************************
                        實現兩個集合的交集
            參數:        兩個集合指針
            返回值:    新的集合
            *******************************************/
            Set * AndSets(const Set *s1, const Set *s2)
            {
                Set *newset = NULL;
                const Set *searchset = NULL;
                Node_t *head = NULL;
               
                assert(s1 != NULL && s2 != NULL);

                if(s1->head == NULL || s2->head == NULL)
                {
                        /*空集合*/
                        creat_nullset(&newset);
                        return newset;
                }

                if(get_setlength(s1) > get_setlength(s2))
                {
                    searchset = s1;
                    head = s2->head;
                }
                else
                {
                    searchset = s2;
                    head = s1->head;
                }
               
                while(head != NULL)
                {
                    if(findElement(searchset, head->value))
                    {
                        create_set(&newset, head->value);
                    }
                    head = head->next;
                }
               
                return newset;
            }

            /*********************************************
                        集合的差集操作
            參數:        兩個集合的指針
            返回值:        新的集合指針
            *********************************************/
            Set * XorSets(const Set *s1, const Set *s2)
            {
                Set *newset = NULL;
                Node_t *head = NULL;
               
                assert(s1 != NULL && s2 != NULL);

                if(s1->head == NULL)
                {
                        /*空集合*/
                        creat_nullset(&newset);
                        return newset;
                }
                if(s2->head == NULL)
                {
                    copySet(&newset,s1);
                    return newset;
                }

                /*newset和s1是相同的*/
                copySet(&newset,s1);
                head = s1->head;

                while(head != NULL)
                {
                    /*如果s2中存在當前元素,刪除*/
                    if(findElement(s2, head->value))
                    {
                        delete_setElement(&newset,head->value);
                    }
                    head = head->next;
                }
               
                return newset;
            }

        集合打印操作、集合的刪除操作

         

            /*********************************************
                        打印集合
            參數:        集合指針
            返回:        void
            **********************************************/
            void print_set(const Set *s)
            {
                Node_t * head = NULL;
                int i = 0;
                assert(s);
                head = s->head;

                printf("{ ");

                while(head != NULL)
                {
                    ++i;
                    printf("%d ",head->value);

                    if(i % 5 == 0 && i != 0)
                    {
                        i = 0;
                    //    printf("\n");
                    }
                    head = head->next;
                }
                printf("}\n");
            }

            /*********************************************
                        刪除一個集合
            參數:        指向集合指針的指針
            返回值:    void
            **********************************************/
            void delete_set(Set **s)
            {
                Node_t *head = NULL;
                Node_t *temp = NULL;

            //    assert(*s);
                if(*s == NULL)
                    return;

                head = (*s)->head;

                while(head != NULL)
                {
                    temp = head;
                    head = head->next;
                    free(temp);
                    (*s)->size --;

                    temp = NULL;
                }
                free(*s);
                *s = NULL;
            }

        最后是我的測試程序:

         

            /************************************************
                        主函數
                    完成各個函數的測試工作
                    最后需要完成內存的釋放
            ************************************************/
            int main()
            {
                Set* sets1 = NULL;
                Set* sets2 = NULL;
                Set* sets3 = NULL;
                Set* sets4 = NULL;

                int i = 0;
                int j = 0;
                for(i = 0; i < 10; ++ i)
                {
                    if(!create_set(&sets1, i+10))
                        break;
                    j = i + 10 - 5;

                    if(!create_set(&sets2, j))
                        break;
                }
                printf("Set1 : ");
                print_set(sets1);
                printf("Set2 : ");
                print_set(sets2);

                sets3 = OrSets(sets1,sets2);
                printf("Set1 + Set2: ");
                print_set(sets3);

                sets3 = OrSets(sets2,sets1);
                printf("Set2 + Set1: ");
                print_set(sets3);

                delete_set(&sets3);
                sets3 = AndSets(sets1,sets2);
                printf("Set1 * Set2: ");
                print_set(sets3);

                delete_set(&sets3);
                sets3 = AndSets(sets2,sets1);
                printf("Set2 * Set1: ");
                print_set(sets3);

                delete_set(&sets3);
                sets3 = XorSets(sets1,sets2);
                printf("Set1 - Set2: ");
                print_set(sets3);

                delete_set(&sets3);
            //    creat_nullset(&sets4);
                sets3 = XorSets(sets2,sets1);
                printf("Set2 - Set1: ");
                print_set(sets3);

                delete_set(&sets1);
                delete_set(&sets2);
                delete_set(&sets3);
                delete_set(&sets4);
                return 0;
            }

        實驗效果:

        總結:

        該實現并沒有考慮性能方面,基本上實現了集合的簡單操作。后面有時間再想想如何優化查找和刪除操作。

        關閉窗口

        相關文章

        欧美性色欧美精品视频,99热这里只有精品mp4,日韩高清亚洲日韩精品一区二区,2020国自产拍精品高潮