我正在尝试创建将在列表中的任何位置插入的代码。我还将转换它以替换给定位置中节点的值。
到目前为止,我的代码是:
#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.
我有什么方法可以获得此列表中节点的当前值和位置?如果是这样,我该怎么做?
当前输出是我仍然可以添加到列表中的相同位置
答案 0 :(得分:3)
插入/更新到稀疏数组的一般想法是仅在到达较大位置的节点时添加节点。当然,您需要之前的节点指针来执行此操作,因此在找到放置数据的位置时,请保持一次跳转以进行扫描。
还有一些说明:
malloc()
in C programs. 有了这个。你走了。
#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
)的列表结束。为了滑动一个值并相应地调整列表,我们应该为posi
提供一个完美的0..9值序列。这可以按如下方式完成:
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()
有两个插入循环,一个始终插入插槽0,另一个插入插槽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个索引中,因此每次插入都会“推”下来,我们逐个插入的每个数字也是如此。
最后,为了正确地证明这一点,只需调整索引直到检测到的间隙,请考虑:
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
正如所料。
答案 1 :(得分: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-&gt; next,因为当前节点无法从头引用访问头节点中包含的下一个指针。 一个使用它的例子
insertAtPos(&head,head->next,10,2)
将在第二个节点之后的节点中插入值10。
有趣的是,如果你输入一个大于列表大小的位置,它就会把它放在最后。