数据结构与算法分析2.1 双向链表及其操作

双向链表的增删改查,此双向链表没有使用空的头链表,直接第一个链表就可以存值。

//cat chapter2_doublelink.h
#ifndef _DOUBLE_LINK_
#define _DOUBLE_LINK_
typedef struct GList {
    int  data;
    struct GList *prev;
    struct GList *next;
} GList;

GList * g_list_new(void);
int g_list_free(GList * p1);
GList * g_list_preinsert(GList * p1, GList* p2);
GList * g_list_appand(GList *p1, GList * p2);
int g_list_print_all(const GList *p1);
GList * g_list_get_post_link(const GList *p1, int pos);
int g_list_post_insert(GList **head, int pos, GList *p2);
GList * g_list_del_link(GList * p1, GList *p2);
void * g_list_destroy(GList * p1);

#endif

root@ubuntu:data-struct# cat double_link.c 
#include "chapter2_doublelink.h"
#include 
#include 
#include 

GList * g_list_new(void)
{
    GList * p1 = NULL;
    p1 = malloc(sizeof(GList));
    if (p1) {
          p1->prev = p1;
          p1->next = p1;
          p1->data = 0;
    }
    return p1;
}

int g_list_free(GList * p1)
{
        if (p1) {
                free(p1);
                return 0;
        }
        else {
                return -1;
        }
}

GList * g_list_preinsert(GList * p1, GList* p2)
{
        if ( p1 ) {
            p2->next = p1;
            p2->prev = p1->prev;
            p1->prev->next = p2;
            p1->prev = p2; 
        } 
        return p2; 
}

GList * g_list_appand(GList *p1, GList * p2)
{
 
    if (p1) {
        p2->next = p1;
        p2->prev = p1->prev;
        p1->prev->next = p2;
        p1->prev = p2;
        return p1;
    }
    else {
        return p2;
    } 
}

GList * g_list_del_link(GList * p1, GList *p2)
{
    int i = 0;
    GList *p3 = p1;
    while (p3) {
        if (i != 0 && p3 == p1) {
            break;
        }
        i++;
        if (p3->data == p2->data) {
            if (p3->next == p3) {
                g_list_free(p3);
                return NULL;
            }
            else {
                p3->prev->next = p3->next;
                p3->next->prev = p3->prev;
                if (i == 1) {
                    p1 = p3->next;
                } 
                g_list_free(p3);
                return p1;
            }
        }
        else {
            p3 = p3->next;
        }
    }
    return p1;
}


void * g_list_destroy(GList * p1)
{
    if (p1) {
        GList *p2 = p1;
        GList *p3 = p2->next;
        while (p2) {
            g_list_free(p2);
            if (p3 == p1) {
                break;
            }
            p2 = p3;
            p3 = p3->next;
        } 
    }
    return NULL;
}


int g_list_print_all(const GList *p1)
{
    const GList *p2 = p1;
    int i = 0;
    printf("\n****** start of list ******\n");
    while (p2) {
        if ( i != 0 && p2 == p1) {
            break;
        }
        i++;
        printf("link[%d]:%d\t", i, p2->data);
        p2 = p2->next;
   }
   printf("\n===== end of list =====\n");
   return i;
}

int g_link_get_len(const GList *p1)
{
    const GList *p2 = p1;
    int i = 0;
    while (p2) {
        if ( i != 0 && p2 == p1) {
            break;
        }
        i++;
        p2 = p2->next;
    }
    return i;
}

GList * g_list_get_post_link(const GList *p1, int pos)
{
    int i = 0;
    const GList* p2 = p1;
    for (; p2; p2 = p2->next ) {
        if (i != 0 && p2 == p1) {
            break;
        }
        ++i;
        if (i == pos) {
            return (GList*)p2;
        }
    } 
    return NULL;
}


int g_list_post_insert(GList **head, int pos, GList *p2)
{
    int ret = -1;
    GList *p1 = *head;
    GList *p3 = NULL;
    if (pos == 1) {
        p3 = g_list_preinsert(p1, p2);
        *head = p3; 
        ret = 0;
    }
    else {
        p3 =  g_list_get_post_link(p1, pos-1);
        if (p3) {
                p2->prev = p3;
               p2->next = p3->next;
               p3->next->prev = p2;
               p3->next = p2;
                ret = 0;
        }
    }
    return ret;
}


int test()
{
    int data;
    GList * head = NULL, *p1;
    printf("Input your link int data(no-number will finish):\n");
    while (1 == scanf("%d", &data)) {
        p1 = g_list_new();
        if (p1) {
            head = g_list_appand(head, p1); 
            p1->data = data;
        }
        else {
            exit(-1);
        } 
        printf("Input your link int data(no-number will finish):\n");
        while ( getchar() != '\n') ;
    }

    g_list_print_all(head);
    while ( getchar() != '\n') ;
    printf("insert to prehead, input the insert data:\n");
    if (scanf("%d", &data) == 1) {
        p1 = g_list_new();
        p1->data = data;
        head = g_list_preinsert(head, p1);
        g_list_print_all(head);
    }

    printf("insert to 3 pos, input the insert data:\n");
    while ( getchar() != '\n') ;
    if (scanf("%d", &data) == 1) {
        p1 = g_list_new();
        p1->data = data;
        if (g_list_post_insert(&head, 3, p1) >= 0) {
            printf("insert to pos 3 error!!\n");
        }
        g_list_print_all(head);
    } 
    return 0;
}

==================================链表的使用=====================

/*

使用链表实现无限大整数的加减。

一个链表来装无限大整数a1,另一个链表来装a2,目前先支持两个数都是正整数。

加法可以工作,减法得到负数的时候有bug,为了不卡进度,先不调了,有需要再搞。

*/

int g_list_print_number(const GList *p1)
{
    const GList *p2 = p1;
    int i = 0;
    printf("\n****** start of list ******\n");
    while (p2) {
        if ( i != 0 && p2 == p1) {
            break;
        }
        i++;
        if (p2->data<0) {
            printf("-");
        }
        //printf("link[%d]:%d ",i, p2->data);
        printf("%d ",p2->data);
        p2 = p2->next;
    }
    printf("\n===== end of list =====\n"); 
    return i;
}

//len(p1) >= len(p2), small_len = MIN(len p1, len p2)
GList * g_link_opr(GList * p1, GList * p2, char oper, int small_len)
{
    GList * res = NULL, *p11 = p1, *p22 = p2, *tmp = NULL;
    int borrow = 0, data1 = 0, data2 = 0, i = 0;
    if (!p1 || !p2) return NULL;
    p11 = p11->prev;
    res = p11;//the end.
    p22 = p22->prev;
    while (i < small_len) {
        data1 = p11->data;
        data2 = p22->data;
        switch (oper) {
        case '+':
            if (borrow) {
                data1++;
                borrow = 0;
            }
            p11->data = (data1 + data2)%100000000;
            if ((data1 + data2)/100000000) {
                borrow = 1;
            }
            break;
        case '-':
            if (borrow) {
                data1--;
                borrow = 0;
            }
            p11->data = (data1 - data2);
            if (p11->data < 0) {
                p11->data = -1 * tmp->data;
                borrow = 1;
            }
            break;
        default:
            printf("oper:%c does not support yet!\n", oper);
        }

        p11 = p11->prev;
        p22 = p22->prev;
        i++;
    }

    while (borrow) {
        if (p11 != res) {
            data1 = p11->data;
            if (oper == '+') {
                data1++ ;
                p11->data = data1 % 100000000;
                borrow = 0;
                if ( data1/100000000 ) {
                    borrow = 1;
                }
            }
            else {// '-'
                data1--;
                if (data1 < 0) {
                    borrow = 1;
                    data1 = -1 * data1;
                }
                else {
                    borrow = 0;
                }
                p11->data = data1 % 100000000;
            }
            p11 = p11->prev;
      }
      else {
        tmp = g_list_new();
        p1 = g_list_preinsert(p1, tmp); 
        if (oper == '+') {
            tmp->data = 1;
        }
        else { //'-'
            tmp->data = -1;
        }
     } 
  }

 return p1;
}


int main()
{
    int data = 0, str_len = 0;
    char opr = '+';
    char tmp_str[1024] = {0}, *ptr = NULL, *get = NULL;
    GList * head1 = NULL,* head2 = NULL, *p1;
    printf("Input first number:");
    fgets(tmp_str, sizeof(tmp_str), stdin);
    str_len = strlen(tmp_str);
    ptr = tmp_str + str_len - 1;
    while (ptr >= tmp_str) {
        *ptr = 'q';
        ptr -= 8;
        if (ptr < tmp_str) get = tmp_str;
        else get = ptr;

        sscanf(get, "%8d", &data);
        if(data < 0) {
            printf("number < 0 does not support yet\n");
            exit(-1);
        }
        p1 = g_list_new();
        if (p1) {
            head1 = g_list_preinsert(head1, p1);
            p1->data = data;
       }
       else {
               exit(-1);
       }
   } 

    g_list_print_number(head1);
    //printf("tem:%s", tmp_str);
    while ( getchar() != '\n') ;
    printf("Input your operator(+/-):");
    scanf("%c", &opr);

    while ( getchar() != '\n') ;
    printf("\nInput second number:");
    fgets(tmp_str, sizeof(tmp_str), stdin);
    str_len = strlen(tmp_str);
    ptr = tmp_str + str_len -1;
    while (ptr >= tmp_str) {
        *ptr = 'q';
        ptr -= 8;
        if (ptr < tmp_str) get = tmp_str;
        else get = ptr;

        sscanf(get, "%8d", &data);
        if(data < 0) {
            printf("number < 0 does not support yet\n");
            exit(-1);
         }
         p1 = g_list_new();
        if (p1) {
            head2 = g_list_preinsert(head2, p1);
            p1->data = data;
        }
        else {
            exit(-1);
        }
    }
    g_list_print_number(head2);

    int len1 = g_link_get_len(head1);
    int len2 = g_link_get_len(head2);
    if (opr == '-') {
        if (len1 < len2) {
            head1 = g_link_opr(head2, head1, opr, len1);
            p1 = g_list_new();
            head1 = g_list_preinsert(head1, p1);
            head1->data = -1; 
        }
        else head1 = g_link_opr(head1, head2, opr, len2);
    }
    else {
        if (len1 < len2) {
            head1 = g_link_opr(head2, head1, opr, len1);
        }
        else head1 = g_link_opr(head1, head2, opr, len2);
    }

    g_list_print_number(head1); 
}

root@ubuntu:data-struct# 

=======================一些测试结果===================

加法

root@ubuntu:data-struct# ./a.out 

Input first number:99999999999999999999999
****** start of list ******
9999999 99999999 99999999 
===== end of list =====
Input your operator(+/-):+
Input second number:44444444444444444444444444444444444444444444444
****** start of list ******
44444444 44444444 44444444 44444444 44444444 44444444 4444444 
===== end of list =====
****** start of list ******
44444444 44444444 44444444 44444444 54444444 44444444 4444443 

===== end of list =====

不产生负数的减法:

root@ubuntu:data-struct# ./a.out 
Input first number:4444444444444444444444444444
****** start of list ******
4444 44444444 44444444 44444444 
===== end of list =====
Input your operator(+/-):-
Input second number:3333333333
****** start of list ******
33 33333333 
===== end of list =====
****** start of list ******
4444 44444444 44444411 11111111 

你可能感兴趣的:(数据结构与算法分析)