典型的几个链表操作-逆序和重排

http://dev.firnow.com/course/3_program/c++/cppjs/20081012/150161.html

 

已知链表的头结点head,写一个函数把这个链表逆序 ( Intel)

Node * ReverseList(Node *head) //链表逆序 { if ( head == NULL || head->next == NULL ) // 否则下面的就错了,一定要注意一些特定条件的判断,边界问题狠重要,软件开发要注意对异常分支的处理 // 三个指针的方式结构比较清晰 Node *p1 = head; Node *p2 = p1->next; Node *p3 = p2->next; p1->next = NULL; while ( p3 != NULL ) { p2->next = p1; // p2->next为p3,已经保存过了 //p1、p2、p3都向前移动一个 p1 = p2; p2 = p3; p3 = p3->next; } p2->next = p1; //最末端节点挂在链上 head = p2; return head; }

 

 

已知两个链表head1 和head2 各自有序升序排列,请把它们合并成一个链表依然有序。(保留所有结点,即便大小相同)
Node * Merge(Node *head1 , Node *head2) { if ( head1 == NULL) return head2; if ( head2 == NULL) return head1; // 良好的习惯,指针要初始化为NULL Node *head = NULL; Node *p1 = NULL; Node *p2 = NULL; // 从小到大,获得头节点 if ( head1->data =< head2->data ) { head = head1; p1 = head1->next; // 注意更新的不一样 p2 = head2; } else { head = head2; p2 = head2->next; p1 = head1; } Node *pcurrent = head; while ( p1 != NULL && p2 != NULL) { if ( p1->data <= p2->data ) { pcurrent->next = p1; // 挂接新节点 &n pcurrent = p1; //更新当前最后一个节点 p1 = p1->next; //更新下一个待比较节点 } else { pcurrent->next = p2; pcurrent = p2; p2 = p2->next; } } if ( p1 != NULL ) //挂接剩余部分 pcurrent->next = p1; if ( p2 != NULL ) pcurrent->next = p2; return head; }

 

 

 

已知两个链表head1 和head2 各自升序排列,请把它们合并成一个链表依然有序,这次要求用递归方法进行。 (Autodesk)

递归版本实际上很容易从上面一个版本改动而得来,主要是注意退出的条件和跌代的条件。

Node * MergeRecursive(Node *head1 , Node *head2) {//退出条件是某链结束 if ( head1 == NULL ) return head2; if ( head2 == NULL) return head1; Node *head = NULL; if ( head1->data < head2->data ) { head = head1; head->next = MergeRecursive(head1->next,head2); } else { head = head2; head->next = MergeRecursive(head1,head2->next); } return head; }

 

 

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/mumu10/archive/2008/09/05/2886817.aspx

下面有code的地方都经过了验证的 :)

list 的定义

typedef struct{
    int val;
    struct list *next;
} list;
1. 反转一个链表,循环算法。

list * reserve_list_by_recurrence(list *l)
{
    list * l_item = l;
    list * n_item = l->next;

    while (n_item != 0)
    {
        list * p_item = l_item;
        l_item = n_item;
        n_item = l_item->next;

        l_item->next = p_item;     
    }

    l->next = 0;
    return l_item;
}
2. 反转一个链表,递归算法。

list * reserve_list_by_recursion(list* p_l, list *l, list *n_l)
{
    l->next = p_l;

    if (n_l != 0)
    {
        reserve_list_by_recursion(l, n_l, n_l->next);
    }
    else
    {
        return l;
    }
}
3. 判断一个链表是否有循环。

思路有些意思,code比较简单,就不列code了。
方法1:快慢法,一个以步长为1遍历,一个以步长为2遍历,next为空前相遇即为循环链表。
方法2:破环结构法,遍历链表,修改链表项的某些结构,通常修改next指针,如果遍历完之前,发现有链表项已经修改,则为循环链表。
当然还有更愚蠢的方法3,就不献丑了 :)

4. 两个链表,一升一降,合并为一个升序链表。

没有什么技巧,不写code了。

5. 在双向链表中删除指定元素。

同上 :)

 

PS. 一些数组相关的也放在这里吧。

1. 一个数组,下标从0到n,元素为从0到n的整数。判断其中是否有重复元素。

定义了个字符串数组,方便返回结果:

char *check_array_repeat_str[3] = {"no repeat","repeat", "error"};
    printf ("%s", check_array_repeat_str[check_array_repeat(a, 10)]);
函数:

int check_array_repeat(int a[], int n)
{
    int i;
    int *flag_array = malloc(sizeof(int) * (n+1));
   
    memset(flag_array, 0, sizeof(int) * (n+1));

    for(i=0; i<=n; i++)
    {
        if ((a[i]>n) || (a[i]<0))
        {
            return 2; //error
        }

        if (*(flag_array+a[i]) == 1)
        {
            return 1;  //repeat
        }
        else
        {
            *(flag_array+a[i]) = 1;
        }
    }

    return 0;
}

你可能感兴趣的:(算法)