1

我正在尝试创建将插入列表中任何位置的代码。我还将转换它以替换给定位置的节点的值。

到目前为止,我的代码是:

#include<stdio.h>
#include<stdlib.h>

struct node* createNode(int,int);

struct node {
    int data, posi;
    struct node *next;
};

struct node *head = NULL;
struct node *tail = NULL;


struct node * createNode(int data, int pos) {
    struct node *ptr = (struct node *) malloc(sizeof (struct node));
    ptr->data = data;
    ptr->posi = pos;
    ptr->next = NULL;
    return ptr;
}

void insertAtPos(int pos, int data) {
    struct node *temp, *ptr = createNode(data,pos);
    int x = 0, i = 1, inserted = 0, duplicate = 0;

    if (head == NULL || pos == 1) {
            if (!head) {
                    head = ptr;
                    tail = ptr;
                    return;
            }
            ptr->next = head;
            head = ptr;
            return;
    }
    temp = head;
    while (temp) {
        x = temp->posi;
        if (pos == i + 1) {
            printf("pos %d - temp %d - data %d",pos,x,temp->data);
            if(pos == x){
                duplicate = 1;
                break;
            }else{
                ptr->next = temp->next;
                temp->next = ptr;

                if (ptr->next == NULL)
                        tail = ptr;
                inserted = 1;
                break;
            }
        }
        i++;
        temp = temp->next;
    }
    if (!inserted)
            printf("You've entered wrong position\n");

    if(duplicate == 1){
        printf("Duplicate position!\n");
    }
}

在这段代码中,我试图获取节点在列表中的当前值和位置,但我得到的只是前一个值。这就是为什么我必须使用 +1 来获得当前位置。

我也在努力做到这一点,以便不会在节点中插入重复的位置,并且用户可以同时插入位置 1、3 和 5。

有什么方法可以让我获取此列表中节点的当前值和位置?如果是这样,我会怎么做?

当前输出是我仍然能够添加到列表中的相同位置

4

2 回答 2

3

插入/更新到稀疏数组的一般想法是仅在到达较大位置的节点时才添加节点。当然,您需要前一个节点指针来执行此操作,因此在您找到放置数据的位置时,请继续进行扫描。

还有一些注意事项:

  • 不要malloc()在 C 程序中强制转换。
  • 我将列表清理作为一项任务留给您。
  • 如果给定的位置已经在列表中,这将更新现有节点。如果你想将一个节点到那个位置并增加它之后的元素直到找到一个间隙,那是相当多的工作。然而,这是可行的。

接着就,随即。干得好。

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

struct node* createNode(int,int);

struct node {
    int data, posi;
    struct node *next;
};

struct node *head = NULL;
struct node *tail = NULL;


struct node * createNode(int data, int pos)
{
    struct node *ptr = malloc(sizeof(*ptr));
    ptr->data = data;
    ptr->posi = pos;
    ptr->next = NULL;
    return ptr;
}

void insertAtPos(int pos, int data)
{
    struct node *ptr = head, *prev = NULL;
    while (ptr && ptr->posi < pos)
    {
        prev = ptr;
        ptr = ptr->next;
    }

    // make sure we have a node.
    if (ptr)
    {
        // Case 1: update existing element.
        if (ptr->posi == pos)
        {
            // update in place
            ptr->data = data;
        }

        // Case 2: insert new element
        else if (prev)
        {
            prev->next = createNode(data, pos);
            prev->next->next = ptr;
        }

        // Case 3: new list head.
        else
        {
            head = createNode(data, pos);
            head->next = ptr;
        }
    }
    else if (prev)
    {
        // means we hit the end of the list.
        prev->next = createNode(data, pos);
    }

    else
    {   // means empty list. new head.
        head = createNode(data, pos);
    }
}

void print()
{
    struct node *p = head;
    while (p)
    {
        printf("list[%d] = %d\n", p->posi, p->data);
        p = p->next;
    }
    printf("\n");
}

int main()
{
    int i = 0;
    srand((unsigned)time(NULL));

    // fill our list with some elements
    for (i=0;i<10;++i)
        insertAtPos(rand() % 20 + 1, rand() % 100);
    print();

    // add or update element
    insertAtPos(15, 100000);
    print();

    // update element at location 20;
    insertAtPos(15, 200000);
    print();

    // prove we can add an element at beginning of list
    insertAtPos(0, 1000);
    print();

    // prove we can add an element at end of list
    insertAtPos(100, 2000);
    print();

    return 0;
}

输出(随机)

list[3] = 86
list[5] = 10
list[9] = 63
list[12] = 86
list[14] = 93
list[19] = 86
list[20] = 49

list[3] = 86
list[5] = 10
list[9] = 63
list[12] = 86
list[14] = 93
list[15] = 100000
list[19] = 86
list[20] = 49

list[3] = 86
list[5] = 10
list[9] = 63
list[12] = 86
list[14] = 93
list[15] = 200000
list[19] = 86
list[20] = 49

list[0] = 1000
list[3] = 86
list[5] = 10
list[9] = 63
list[12] = 86
list[14] = 93
list[15] = 200000
list[19] = 86
list[20] = 49

list[0] = 1000
list[3] = 86
list[5] = 10
list[9] = 63
list[12] = 86
list[14] = 93
list[15] = 200000
list[19] = 86
list[20] = 49
list[100] = 2000

编辑关于如何完成插入的请求。

将新项目滑入给定索引可能需要在其之后更新现有索引。前提是以下内容应该构建一个具有升序posi值的列表:

int main()
{
    int i = 0;
    srand((unsigned)time(NULL));

    // fill our list with some elements
    for (i=0;i<10;++i)
        insertAtPos(0, rand() % 100);
    print();

    return 0;
}

注意我们插入的索引。它始终为零。之前的版本insertAtPos()会简单地重复替换现有值,我们会以单个节点 ( posi = 0) 的列表结束。为了滑动一个值并相应地调整列表,我们应该有一个完美的 0..9 值序列posi。这可以按如下方式完成:

void insertAtPos(int pos, int data)
{
    // same as before. find the right slot
    struct node *ptr = head, *prev = NULL;
    while (ptr && ptr->posi < pos)
    {
        prev = ptr;
        ptr = ptr->next;
    }

    if (prev)
    {
        // slip new node in.
        prev->next = createNode(data, pos);
        prev->next->next = ptr;
    }
    else
    {   // no prev means this goes to the head of the list.
        head = createNode(data, pos);
        head->next = ptr;
    }

    // it is possible the new node has the same
    //  index as its successor. to account for this
    //  we must walk successor nodes, incrementing
    //  their posi values until a gap is found (or
    //  end of list).
    while (ptr && (ptr->posi == pos++))
    {
        ptr->posi++;
        ptr = ptr->next;
    }
}

运行上述main()..

list[0] = 90
list[1] = 34
list[2] = 45
list[3] = 27
list[4] = 45
list[5] = 88
list[6] = 75
list[7] = 50
list[8] = 68
list[9] = 41

当然,您的值会因rand(). 与两个插入循环略有不同main(),一个总是在 slot-0 插入,另一个总是在 slot-4 插入。

int main()
{
    int i = 0;
    srand((unsigned)time(NULL));

    // fill our list with some elements
    for (i=0;i<5;++i)
        insertAtPos(0, rand() % 100);
    print();
    for (i=0;i<5;++i)
        insertAtPos(4, rand() % 100);
    print();

    return 0;    
}

应该导致相同的索引,但明显不同的值(同样,它毕竟是 `rand())。

list[0] = 74
list[1] = 35
list[2] = 72
list[3] = 22
list[4] = 0

list[0] = 74
list[1] = 35
list[2] = 72
list[3] = 22
list[4] = 40
list[5] = 38
list[6] = 31
list[7] = 57
list[8] = 42
list[9] = 0

请注意该0值是如何一直推到列表末尾的。它在 4-index 中,因此每次插入都会“下推”,就像我们一个接一个插入的每个数字一样。

最后,为了证明这仅在检测到间隙之前正确调整索引,请考虑以下内容:

int main()
{
    int i = 0;
    srand((unsigned)time(NULL));

    // fill our list with some elements
    for (i=0;i<10;i+=2)
        insertAtPos(i, rand() % 100);
    print();
    for (i=0;i<2;++i)
        insertAtPos(3, rand() % 100);
    print();

    return 0;
}

这应该最初在索引 0,2,4,6,8 中插入值,然后在插槽“3”处插入两个值。第一次插入应该给我们索引 0,2,3,4,6,8。第二次插入应该给我们索引 0,2,3,4,5,6,8。

list[0] = 22
list[2] = 3
list[4] = 91
list[6] = 15
list[8] = 68

list[0] = 22
list[2] = 3
list[3] = 94
list[4] = 48
list[5] = 91
list[6] = 15
list[8] = 68

正如预期的那样。

于 2013-09-29T06:37:37.823 回答
1

这是我的函数,它可以让你在列表中的任何位置插入,给定一个位置编号。它根据必须遍历的项目数+ 1隐式地为每个项目提供一个数字。因此,头部的节点编号为 1。

void insertAfterPos(struct node** head_ref, struct node* link, int new_data, int pos)
{

// allocate new node 
struct node* new_node = malloc(sizeof(struct node));
struct node* cur = *head_ref; //initialise current node as head
cur->next = link;
int nodenum = 1;
// put in the data
new_node->data = new_data;
while (cur !=NULL || nodenum <= pos) {
    if (nodenum == pos) {
    //Make next of new node next of current node 
    new_node->next = cur->next;

    //Make the next of current node new_node
    cur->next = new_node;
    }
    nodenum++;
    cur = cur->next; //move forward
    }
}

该函数是在框架内编写的,所有插入函数对列表的访问将通过头引用,或指向指向头的指针的指针,因此节点 **head_ref 参数。此函数中的第二个参数 link 应该是 head->next,因为当前节点无法从头引用访问头节点中包含的下一个指针。它的使用示例

insertAtPos(&head,head->next,10,2)

将在第二个节点之后的节点中插入值 10。

有趣的是,如果你输入的位置大于列表的大小,它只会把它放在最后。

于 2015-07-17T15:20:55.873 回答