繁体   English   中英

在双向链接列表中交换项目

[英]Swap items in a doubly 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;


}

让我们简化问题。 复杂的指针部分是当我们尝试在列表中向前移动节点时。 因此,让我们为此创建一些功能。

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;
}

一些评论:

这里要注意的重要一点是,我们具有创建多个功能的能力。 而且,我们可以使用这些功能来使我们需要随时解决的问题量变小。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM