交换双向链表中的项目

时间:2014-06-30 15:36:51

标签: c linked-list

我正在攻读算法考试,我有一个练习,如果条件成立,我需要交换两个双向链表项。 (语言:C) 更具体地说,我有一个这样的清单:

H <-> |prev|Frequency1|VALUE1|next| <-> |prev|Frequency2|VALUE2|next| <-> ... <-> NULL

每次搜索相对值时,频率字段都会增加。必须根据频率对列表进行排序(按递减顺序排列,因此最顶部的搜索项目最多)

问题是,我在交换指针方面不是很好,我多次尝试过,但我不知道。我想我面临的问题是我不知道如何使用临时项来跟踪我正在做的事情而不会丢失数据。

我认为我必须考虑的情况是:

  • 列表的第一项
  • 列表的最后一项
  • 项目位于列表中间。

我的尝试,当然是错误的:

int Search(int x, list* head) {

    int contapos = 0;
    list* i;
    list* aus;

    for (i=head; i!=NULL; i = i->next, contapos++)
    {

        if (i->key == x)
        {
            i->freq++; // Increase frequency

            aus = i->prev;

            while ((i->freq > aus->freq))
            { // Keep ordered the frequencies

                if (i->next != NULL)
                {
                    i->next->prev = aus;
                }

                if (aus->prev != NULL)
                {
                    aus->prev->next = i;
                }

                aus->next = i->next;
                i->prev = aus->prev;
                aus->prev = i;
                i->next = aus;

            }

            /* Return counter */
            return contapos;

        }

    }

    return -1; // In case the item i am searching is not there
}

提前感谢您的一切!

修改 根据要求,我现在正在添加程序的主要(以及完整的代码)

typedef struct _list {
int key;
int freq;
struct _list *next;
struct _list *prev;
} list;

list* head;
list* tail;

void swap(list *lhs, list *rhs) {
list *temp;

temp = lhs->prev;
lhs->prev = rhs->prev;
rhs->prev = temp;

temp = lhs->next;
lhs->next = rhs->next;
rhs->next = temp;
}


void InsertAtTail(int value) {
list *newNode;
newNode = (list*)malloc(sizeof(list));
newNode->key = value;

if(head == NULL)
{
    head = newNode;
}
else
{
    tail->next = newNode;
    newNode->prev = tail;
}

tail = newNode;
tail->next = NULL;
}

int SearchAndIncrement(int x, list** head) {
int contapos = 0;
list* i;

// Let's find the element with the matching key
for (i = *head; i != NULL; i = i->next, contapos++)
    if (i->key == x)
        break;

// If we did not find the node, return -1 to denote failure.
if (i == NULL)
    return -1;

// Increase frequency
i->freq++;

// Move this node forward while the frequency is not in the correct position.
while (i->next && i->prev && (i->freq > i->prev->freq))
    swap(i, i->prev);

// The head might have been moved.
while ((*head)->prev != NULL)
    (*head) = (*head)->prev;

// Return the original position
return contapos;
}


int main () {

int N;
scanf("%d", &N);

head = NULL;
tail = NULL;

int i, value;
for (i=0; i<N; i++) {
    scanf("%d", &value);
    InsertAtTail(value);
}

/* Initializing frequencies */
list* aus;
for (aus=head; aus; aus = aus ->next) {
    aus->freq = 0;
}

int x, pos;
do {
    scanf("%d", &x);
    pos = SearchAndIncrement(x, &head);
    printf("%d ", pos);
    printf("[");
    aus = head;
    while (aus!=NULL) {
        printf("%d ", aus->key);
        aus = aus->next;
    }
    printf("]\n");

} while (pos != -1);

return 0;


}

1 个答案:

答案 0 :(得分:4)

让我们简化问题。复杂的指针部分是我们尝试在列表中向前移动节点的时候。所以让我们为此创建一些函数。

void RemoveNode(list *node) {
    if (node->prev)
        node->prev->next = node->next;
    if (node->next)
        node->next->prev = node->prev;
}

void InsertNodeBetween(list *lhs, list *node, list *rhs) {
    if (lhs) assert(lhs->next == rhs);
    if (rhs) assert(rhs->prev == lhs);

    if (lhs) lhs->next = node;
    if (rhs) rhs->prev = node;

    node->prev = lhs;
    node->next = rhs;
}

一旦我们完成了这项工作,我们就可以更轻松地谈论您想要做的操作。

int SearchAndIncrement(int x, list** head) {
    int contapos = 0;
    list* i;

    // Let's find the element with the matching key
    for (i = *head; i != NULL; i = i->next, contapos++)
        if (i->key == x)
            break;

    // If we did not find the node, return -1 to denote failure.
    if (i == NULL)
        return -1;

    // Increase frequency
    i->freq++;

    // Move this node forward while the frequency is not in the correct position.
    while (i->next && (i->freq > i->next->freq)) {
        list *prev = i->next;
        list *next = i->next->next;
        RemoveNode(i);
        InsertNodeBetween(prev, i, next);
    }

    // The head might have been moved.
    while ((*head)->prev != NULL)
        (*head) = (*head)->prev;

    // Return the original position
    return contapos;
}

一些评论:

这里要注意的重要一点是,我们有能力创建多个功能。我们可以使用这些功能来解决我们需要在任何时候保持在较小的问题量。