简体   繁体   English

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

[英]Swap items in a doubly linked list

I am studying for my Algorithms exam and I have an exercise where I need to swap two items of a doubly linked list if a condition is true. 我正在为算法考试学习,并且有一个练习,如果条件为真,我需要交换双向链表中的两项。 (Language: C) More specifically, I have a list of this kind: (语言:C)更具体地说,我有一个这样的列表:

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

The frequency field increases every time I search for the relative value. 每当我搜索相对值时,频率场都会增加。 The list must be ordered according to the frequency (in decreasing order, so at the very top there is the most searched item) 必须根据频率对列表进行排序(以降序排列,因此最顶部是搜索最多的项目)

The problem is, I am not very good in exchanging pointers, I tried many times to do it but I have no clue. 问题是,我在交换指针方面不是很好,我尝试了很多次但没有任何线索。 I guess that the problem I am facing is that I don't know how to use a temp item to keep track of what I am doing without loosing data. 我想我面临的问题是我不知道如何使用临时项来跟踪我在做什么而又不会丢失数据。

I think that the case I have to consider are: 我认为我要考虑的情况是:

  • First item of the list 清单的第一项
  • Last item of the list 列表的最后一项
  • Item is in the middle of the list. 项目在列表的中间。

My attempt, certainly wrong is: 我的尝试,当然是错误的:

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
}

Thank you in advance for everything! 预先感谢您所做的一切!

Edit: as requested, I am adding the main (and the whole code just to be sure) of the program at the moment 编辑:根据要求,我现在正在添加程序的主要代码(以及整个代码)

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;


}

Let's simplify the problem. 让我们简化问题。 The complicated pointer portion is when we are trying to move a node forward in the list. 复杂的指针部分是当我们尝试在列表中向前移动节点时。 So let's create some functions just for that. 因此,让我们为此创建一些功能。

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

Once we've done that, then we can more easily talk about the operation that you want to do. 完成此操作后,我们可以更轻松地讨论您要执行的操作。

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

Some commentary: 一些评论:

The important thing to note here is that we have the ability to create multiple functions . 这里要注意的重要一点是,我们具有创建多个功能的能力。 And we can use those functions to make the amount of the problem that we need to keep in our head at any one time smaller. 而且,我们可以使用这些功能来使我们需要随时解决的问题量变小。

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

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