删除单链表中的重复节点(删除重复项)

题目:删除单链表中的重复节点(删除重复项;即只要链表中某个元素的出现次数大于1,那么就将链表中所有的该元素都删除)(即重复的结点不保留)
例如,链表1->3->2->5->6->1->5->7->3->8->2 ,处理后为 6->7->8。
思路分析:
只需在删除单链表中的重复节点(删除多余项)的非递归方法上略作修改即可实现。但是要注意,带头节点的单链表和不带头节点的单链表的细微区别。
具体实现如下:

#include 

typedef struct node
{
    int data;
    struct node *next;
} NODE;


// 尾插法创建单链表(带头节点)
NODE *createEnd(int arr[], int len)
{
    NODE *head = (NODE *)malloc(sizeof(NODE)); // 生成头节点
    head->next = NULL;
    NODE *end = head;  // 尾指针初始化

    for (int i = 0; i < len; i++) {

        NODE *p = (NODE *)malloc(sizeof(NODE)); // 为每个数组元素建立一个节点
        p->data = arr[i];
        end->next = p;  // 将节点p插入到终端节点之后
        end = p;
    }

    end->next = NULL;  // 单链表建立完毕,将终端节点的指针域置空

    return head;
}


// 单链表打印
void print(NODE *head)
{
    if (head == NULL) return;

    NODE *p = head->next;
    while (p != NULL) {
        printf("%d  ", p->data);
        p = p->next;
    }
}


// 删除重复项(带头节点的单链表)
NODE *delSame(NODE *head)
{
    NODE *p,*q,*r,*temp;
    NODE *s = head;
    p = s->next;
    int flag = 0; // flag用于标记在下一步遍历中,p后面的节点中 是否存在 与当前的p节点 相同的节点,若有,则flag为1while(p != NULL)    // p用于遍历链表,每次遍历过程中,用p节点和p后面的节点依次比较;
    {
        q = p;
        while(q->next != NULL) // q遍历p后面的结点,并与p数值比较
        {
            if(q->next->data == p->data)
            {
                flag = 1; // flag为1,则在当前遍历结束后,删除当前的p节点;
                r = q->next; // r保存需要删掉的结点
                q->next = r->next;   // 需要删掉的结点的前后结点相接
                free(r);
            }
            else
                q = q->next;
        }


        if (flag == 0)
        {
            s = p;
            p = p->next;
        }
        else
        {
            flag = 0; // 删除当前的p节点时,flag重新置为0;
            temp = p;
            p = p->next;
            s->next = p;
            free(temp);
        }

    }

    return head;
}

int main(int argc, const char * argv[]) {

    int arr[] = {1, 3, 2, 5, 6, 1, 5, 7, 3, 8, 2};
    int len = sizeof(arr)/sizeof(int);

    NODE *head = createEnd(arr, len);

    // 去重前
    print(head);
    printf("\n");

    // 带头节点的单链表
//     delSame(head);

// -------------------------------------------------------------- 
    // 如果使用的是不带头节点的单链表,那么应先自己创建一个头节点pHead,让pHead->next指向无头单链表的首元节点。
    // 通过上面 NODE *head = createEnd(arr, len);创建的是一个带头节点的单链表;为了测试,测试,测试,我们假设这是一个无头单链表,此链表的首元节点就是head->next,此时为了给该单链表去重,应自己先创建一个头节点。
    NODE *pHead = (NODE *)malloc(sizeof(NODE));
    pHead->next = head->next;
    delSame(pHead);
// --------------------------------------------------------------

    // 去重后
    print(pHead);
    printf("\n");

    return 0;
}

输出如下:
这里写图片描述

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