用位置号打印C链表中的重复条目

Print duplicate entries in C linked list with location number

我正在尝试打印链表中出现的所有重复项,但无法打印最后一个。

我还尝试将最后一个重复字符串 ptr1->name 存储在一个临时变量中并在 while 循环结束后打印它,但它不适用于不同的一对值,只有最后一个,我也不能找到一种方法来打印最后一个重复字符串的位置。

如果没有更好的方法来打印最后重复的字符串,我如何才能只忽略第一次出现的字符串?

示例:

列表:

1 7001 桑贾纳
2 7014 艾西瓦娅
3 7025 兰吉特
4 7017 导师
5 7101 迪克夏
6 7023 印度
7 7017 导师
8 7001 桑贾纳
9 7017 导师
10 7016 基兰
11 7020 拉吉尼
12 7020 拉吉尼

所需输出:

1 7001 桑贾纳
4 7017 导师
7 7017 古鲁达 -- Dup
8 7001 Sanjana -- 重复
9 7017 古鲁达 -- Dup
11 7020 拉吉尼
12 7020 拉吉尼 -- Dup

Edit:

Found Solution with help of @peal-mazumder

解法:

void duplicate(void){
    int count = 0;
    int loc1 = 0;  // 1st Pointer location
    int loc2 = 0;  // 2nd Pointer location
    struct node * ptr1, * ptr2;
    bool vis[5000] = {false}; 

    ptr1 = root;

    while (ptr1!=NULL){
    loc1++;

    // if node is already marked for duplicate it will skip compare and move to next node.

        if (vis[loc1]) {
            ptr1 = ptr1->link;
            continue;
        }
        ptr2 = ptr1->link;
        loc2 = loc1;
        while(ptr2!=NULL){
        loc2++;

            if ((ptr1->num == ptr2->num) && !(strcmpi(ptr1->name, ptr2->name))){
                count++;
                if (count == 1) printf("Duplicate Search Results: \n");

                // delete below if statement if original not to be printed.

                if (!vis[loc1]) printf(" %d--> %02d %s\n",loc1, ptr1->num, ptr1->name); // print original

                printf(" %d--> %02d %s --> Dup\n", loc2, ptr2->num, ptr2->name); // print duplicate
                vis[loc2] = true; // marked for duplicate.
                vis[loc1] = true; // not required if original not to be printed.
            }

            ptr2 = ptr2->link;
        }
        ptr1 = ptr1->link;
    }

    if (!count) {
        printf("No duplicates found in the list!\n");
    }else{
        printf("Total (%d) duplicates.\n", count);
    }
}

输出:

 1--> 7001 Sanjana
 8--> 7001 Sanjana --> Dup
 4--> 7017 Gurudas
 7--> 7017 Gurudas --> Dup
 9--> 7017 Gurudas --> Dup
 11--> 7020 Rajni
 12--> 7020 Rajni --> Dup
Total (4) duplicates.
8 --> 7001 Sanjana
9 --> 7017 Gurudas
12 --> 7020 Rajni
Total (3) duplicates.

如果您正在尝试打印类似的内容,请检查下面的代码,否则请在您的描述中为给定的示例案例添加所需的输出。

struct node {
    int num;
    char name[20];
    struct node* link;
} * root;


// function

void duplicate(void){
    int count = 0;
    int loc = 0; // Location in the list.
    struct node * ptr1, * ptr2;
    bool vis[200000] = {false};
    ptr1 = root; // root is global pointer variable.
    while (ptr1->link!=NULL) {
        loc++;
        if(vis[ptr1->num]) { // if i already processed for same num value then we don't need to check duplicate for this again.
            ptr1 = ptr1->link;
            continue;
        }
        vis[ptr1->num] = true;
        ptr2 = ptr1->link;
        int Ptr2Location = loc + 1, lastDupLocation = 0;
        struct node *temp; // to store last duplicate node
        while(ptr2 != NULL) {
            if ((ptr1->num == ptr2->num) && !(strcmpi(ptr1->name, ptr2->name))){
                temp = ptr2;
                lastDupLocation = Ptr2Location;
            }
            Ptr2Location++;
            ptr2 = ptr2->link;
        }
        if(lastDupLocation)
            printf(" %d --> %02d %s\n", lastDupLocation, temp->num, temp->name), count++;
        ptr1 = ptr1->link;
    }

    if (!count) {
        printf("No duplicates found in the list!\n");
    }else {
        printf("\nTotal (%d) duplicates.\n", count);
    }
}
void insert(int num, char str[20], int len)
{
    if(root == NULL) { //If the list is empty
        root = new node();
        root->num = num;
        strcpy(root->name, str);
        root->link = NULL;
    }
    else{
        node* current_node = root; //make a copy of root node
        while(current_node->link!=NULL) //Find the last node
        {
            current_node=current_node->link; //go to next address
        }
        node *newnode = new node(); //create a new node
        newnode->num = num;
        strcpy(newnode->name, str);
        newnode->link = NULL;

        current_node->link=newnode; //link the last node with new node
}

}

int main()
{
    int num, n, i;
    cin>>n;
    char name[20];
    for (i = 0; i<n; i++)
    {
        scanf("%d %s", &num, name);
        insert(num, name, strlen(name));
    }
    duplicate();
    return 0;
}

You can sort this according to their location by storing these values in a data structure or a structure.

1 --> 7001 Sanjana
8 --> 7001 Sanjana
4 --> 7017 Gurudas
7 --> 7017 Gurudas
9 --> 7017 Gurudas
11 --> 7020 Rajni
12 --> 7020 Rajni

Code

void duplicate(void){
    int count = 0;
    int loc = 0; // Location in the list.
    struct node * ptr1, * ptr2;
    bool vis[200000] = {false};
    ptr1 = root; // root is global pointer variable.
    while (ptr1->link!=NULL) {
        loc++;
        if(vis[ptr1->num]) { // if i already processed for same num value then we don't need to check duplicate for this again.
            ptr1 = ptr1->link;
            continue;
        }
        ptr2 = ptr1->link;
        int Ptr2Location = loc + 1;
        while(ptr2 != NULL) {
            if ((ptr1->num == ptr2->num) && !(strcmpi(ptr1->name, ptr2->name))){
                if(!vis[ptr1->num])
                    printf(" %d --> %02d %s\n", loc, ptr1->num, ptr1->name), count++;
                printf(" %d --> %02d %s\n", Ptr2Location, ptr2->num, ptr2->name);
                vis[ptr1->num] = true;
            }
            Ptr2Location++;
            ptr2 = ptr2->link;
        }
        ptr1 = ptr1->link;
    }
}

不太实用的答案

duplicate 是一个 O(n^2) 函数;也就是说,一个循环遍历 ptr1,并且对于每个值,嵌套循环遍历 ptr2。这在 linked-list.

中很常见

一种更有效的方法是散列法,即将密钥转换成称为散列[code]的数字。此特定数据的hash table stores the records by their hash. Seeing this data, I would assume that name depends on num, so num can be your key. If there is guarantee that num falls in, say, 7000 -- 7099, one could have a collision-free perfect hash funcionH(x) = x.num - 7000O(n)速度。

例如,H(1 7001 Sanjana) = 1 -> 将记录存储在 table[1]。到达 H(8 7001 Sanjana) = 1table[1] 已被占用,因此立即知道它是重复的。

但为什么还要为数据烦恼呢?如果一个人不介意 false-positives 的(小)机会和概率 Bloom filter,则可以有 O(n) run-time 和 O(1) space 要求.

#include <stdio.h>
#include <errno.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>

/* Define a maximum name length and have the C pre-processor encode this in a
 string automatically. */
#define NAME_LENGTH 31
#define QUOTE(n) XQUOTE(n)
#define XQUOTE(n) #n

/** < */
static uint32_t hash(uint32_t x) {
    x = ((x >> 16) ^ x) * 0x45d9f3b;
    x = ((x >> 16) ^ x) * 0x45d9f3b;
    x = (x >> 16) ^ x;
    return x;
}

/** Thomas Wang's 32 bit Mix Function. */
static uint32_t inthash(uint32_t key) {
    key += ~(key << 15);
    key ^=  (key >> 10);
    key +=  (key << 3);
    key ^=  (key >> 6);
    key += ~(key << 11);
    key ^=  (key >> 16);
    return key;
}

/** <https://nullprogram.com/blog/2018/07/31/> */
static uint32_t lowbias32(uint32_t x) {
    x ^= x >> 16;
    x *= 0x7feb352dU;
    x ^= x >> 15;
    x *= 0x846ca68bU;
    x ^= x >> 16;
    return x;
}

int main(void) {
    uint64_t bloom = 0;
    size_t scans = 0, count = 0;
    unsigned no, id;
    char name[NAME_LENGTH + 1], lf;
loop:
    switch(scanf("%u %u %" QUOTE(NAME_LENGTH) "s%c", &no, &id, name, &lf)) {
    case EOF: if(feof(stdin)) break; else goto catch;
    case 0: case 1: case 2: case 3: errno = EILSEQ; goto catch;
    case 4:
        if(lf != '\n') { errno = EILSEQ; goto catch; }
        else {
            const uint32_t x = (uint32_t)id;
            const uint64_t xvect = (1 << (hash(x) & 63))
                | (1 << (inthash(x) & 63)) | (1 << (lowbias32(x)));
            if((bloom & xvect) == xvect) // print (possible) duplicate
                printf(" %u %u %s --> (possible) Dup\n", no, id, name), count++;
            else // marked for duplicate
                bloom |= xvect;
        }
        scans++;
        goto loop;
    }
    if (!count) {
        printf("No duplicates found in the %zu list!\n", scans);
    }else{
        printf("Total %zu/%zu (possible) duplicates.\n", count, scans);
    }
    return EXIT_SUCCESS;
catch:
    fprintf(stderr, "While scanning record %zu: %s.\n", scans, strerror(errno));
    return EXIT_FAILURE;
}

7 7017 Gurudas --> (possible) Dup 8 7001 Sanjana --> (possible) Dup 9 7017 Gurudas --> (possible) Dup 12 7020 Rajni --> (possible) Dup Total 4/12 (possible) duplicates.