Общая идея вставки/обновления в разреженном массиве только добавлять узлы, когда вы прибудете в узел на больше. Конечно, для этого вам нужен указатель узла предыдущего, поэтому держите его в сканирующем режиме для сканирования, пока вы находите, где разместить свои данные.
И некоторые примечания:
- Don't cast
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;
}
Выход (Random)
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
EDIT Запрос как засунуть в вставки делается.
Чтобы пропустить новый элемент в данный индекс, потенциально необходимо обновить существующие индексы после. Предпосылкой является то, что следующий должен создать список с восходящей 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()
с двумя петлями вставки, которые всегда вставляются в слот-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. Какой выход вы получаете *? 2. Какой результат вы ожидаете *? 3. Как выглядит определение «struct node» (включая описание членов). 4. Если вы предпочитаете обновлять существующие узлы, то почему * создать * новый узел прямо из ворот? Не имело бы смысла только делать это, когда вы знаете, что вы * не * нашли узел для обновления? – WhozCraig
@WhozCraig извините, оставит остальную часть кода, для 4, что еще для того, чтобы добавить только узел, когда он не найден, хотя это было из предыдущего кода, который я сейчас редактирую, чтобы соответствовать моему новому сценарию. – magicianiam
ОК. это должно быть что-то вроде разреженного массива? Похоже, он просто хотел уточнить. – WhozCraig