简体   繁体   English

我将如何修改这个单链表排序算法,使其按升序正确排序?

[英]How would I modify this singly linked list sorting algorithm so that it sorts by ascending order properly?

I am currently trying to sort a singly linked list in descending order.我目前正在尝试按降序对单链表进行排序。 Realizing there is no straightforward way to do that with only a next pointer, I opted for the approach of sorting the list in ascending order first, then reversing the list, so that the items are sorted in descending order.意识到仅使用 next 指针没有直接的方法来做到这一点,我选择了先按升序对列表进行排序,然后将列表反转,以便项目按降序排序的方法。

Edit 1: I'm trying to ensure that the items are stored in descending order based on how frequently they are accessed in the linked list.编辑1:我试图确保项目根据它们在链接列表中的访问频率以降序存储。 The printing is just to help me check the order of the linked list.打印只是为了帮助我检查链表的顺序。

Edit 2: Minimum Working Example as Requested:编辑 2:要求的最小工作示例:

main.c main.c

#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

typedef struct node_struct {
    char *name;
    int accessCount;
    struct node_struct *next;
}Knowledge_Node;

int knowledge_put();
int knowledge_get();
void printList();
void sortList();
void reverseList();

Knowledge_Node *head = NULL;

int main(int argc, char*argv[]){
  // Putting James into the linked list
  knowledge_put("James");

  //Get the James node twice
  knowledge_get("James");
  knowledge_get("James");

  //Add Carrie to the linked list
  knowledge_put("Carrie");

  //Get the Carrie node thrice
  knowledge_get("Carrie");
  knowledge_get("Carrie");
  knowledge_get("Carrie");

  // Add adams to linked list
  knowledge_put("Adams");
  knowledge_get("Adams");

  printList();
}

Add Node Function添加节点 Function

int knowledge_put(char * name) {
  Knowledge_Node *node = (Knowledge_Node *)malloc(sizeof(Knowledge_Node));
  if (node == NULL) {
      return -3;
  }
  node->name = (char *)malloc(sizeof(char) * 255);
  if (node->name == NULL){
      return -3;
  }
  strncpy(node->name, name, strlen(name) + 1);
  node->accessCount = 0;

  node->next = head;
  head = node;

  sortList();
}

Retrieve Node Function检索节点 Function

int knowledge_get(char * name){
    Knowledge_Node *search = head;

    while (search != NULL){
        if (strcmp(search->name, name) == 0){
            search->accessCount = search->accessCount + 1;
            sortList();
            return 0;
        }
        search = search->next;
    }
    return -1;
}

Sort List Function:排序列表 Function:

void sortList(){
    Knowledge_Node *temp = head;
    Knowledge_Node *backPtr = head;
    Knowledge_Node *prevNode = NULL;

    while (temp != NULL){
        Knowledge_Node *nextNode = temp->next;
        //currentNode is assigned to temp, which is the pointer used to iterate through the list
        Knowledge_Node *currentNode = temp;
        //Doing a simple check to see if nextNode has something
        if (nextNode != NULL) {

            if(nextNode != NULL){
                if (currentNode->accessCount > nextNode->accessCount) {
                    //If previousNode is NULL it means currentNode is the head of //the linked list
                    //There's different logic to handle each case
                    if (prevNode != NULL){
                        prevNode->next = nextNode;
                        nextNode->next = currentNode;
                        currentNode->next = NULL;
                    } else if (prevNode == NULL){
                        currentNode->next = nextNode->next;
                        nextNode->next = currentNode;
                        head = nextNode;
                    }
                }
            }
        }
        //Assigning of previousNode. We'll need this for the linking/un-linking //process
        prevNode = currentNode;
        temp = temp->next;
    }
    reverseList();
} 

Reverse List Function:反向列表 Function:

void reverseList(){
    //Initialise three pointers, which we'll use to reverse the links of the 
    //linked list
    Knowledge_Node *prevNode = NULL;
    Knowledge_Node *currentNode = head;
    Knowledge_Node *nextNode = NULL;

    //This is where the linked list reversal is done
    while (currentNode != NULL){
        nextNode = currentNode->next;
        currentNode->next = prevNode;
        prevNode = currentNode;
        currentNode = nextNode;
    }

    //Previous Node points to the last node in the original list, so let's 
    //make it the new head
    head = prevNode;
}

Print List Function:打印清单 Function:

void printList() {
    Knowledge_Node *temp = head;
    while (temp != NULL){
        printf("%s %d\n", temp->name, temp->accessCount);
        temp = temp->next;
    }
}

Expected Output:预期 Output:

Carrie 3
James 2
Adams 1

Actual Output:实际 Output:

Adams 1
Carrie 3
James 2

The ascending sort seems to work fine on its own, without the reverse sort.升序排序本身似乎工作正常,没有反向排序。

Hopefully someone can guide me based on this as to how I can change the sortList algorithm to make it sort in ascending, then descending order properly希望有人可以根据此指导我如何更改 sortList 算法以使其按升序排序,然后正确降序排序

Removed rest of content to keep things brief删除了 rest 的内容以保持简短

I figured out what is wrong with your sorting algorithm.我弄清楚你的排序算法有什么问题。 Since your linked list is a singly linked list you can't use a more efficient sorting algorithm like insert sort.由于您的链表是单链表,因此您不能使用更有效的排序算法,如插入排序。 So I used bubble sort in this matter.所以我在这件事上使用了冒泡排序。 In your algorithm you have only used a one loop.在您的算法中,您只使用了一个循环。 You must use nested two loops.您必须使用嵌套的两个循环。 See details about bubble sort .请参阅冒泡排序的详细信息。

Also instead of keeping the head pointer for the list as the newly added node, you can define a structure called List and have the head pointer in that.此外,您可以定义一个名为List的结构并在其中包含头指针,而不是将列表的头指针保留为新添加的节点。 It's more clear.更清楚了。

#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

typedef struct node_struct {
    char *name;
    int accessCount;
    struct node_struct *next;

}Knowledge_Node;


typedef struct list{

    Knowledge_Node* head;
    int count;

}List;

int knowledge_put();
int knowledge_get();
void printList();
void sortList();
void reverseList();

List* list1=NULL;

int main(int argc, char*argv[]){

   list1= (List*)malloc(sizeof(List)*1);
   list1->head=NULL;
   list1->count=0;
  // Putting James into the linked list
  knowledge_put("James");

  //Get the James node twice
  knowledge_get("James");
  knowledge_get("James");

  //Add Carrie to the linked list
  knowledge_put("Carrie");

  //Get the Carrie node thrice
  knowledge_get("Carrie");
  knowledge_get("Carrie");
  knowledge_get("Carrie");

  // Add adams to linked list
  knowledge_put("Adams");
  knowledge_get("Adams");

  sortList();
  reverseList();
  printList();
}

int knowledge_put(char * name) {
  Knowledge_Node *node = (Knowledge_Node *)malloc(sizeof(Knowledge_Node));
  if (node == NULL) {
      return -3;
  }
  node->name = (char *)malloc(sizeof(char) * 255);
  if (node->name == NULL){
      return -3;
  }
  strncpy(node->name, name, strlen(name) + 1);
  node->accessCount = 0;


  node->next = list1->head;
  list1->head = node;
  list1->count++;


  return -3;
}

int knowledge_get(char * name){
    Knowledge_Node *search = list1->head;

    while (search != NULL){
        if (strcmp(search->name, name) == 0){
            search->accessCount = search->accessCount + 1;

            return 0;
        }
        search = search->next;
    }
    return -1;
}

void sortList(){

    Knowledge_Node* sort=list1->head;
    Knowledge_Node* nextl=list1->head->next;
    Knowledge_Node* temp=(Knowledge_Node *)malloc(sizeof(Knowledge_Node));
    temp->name = (char *)malloc(sizeof(char) * 255);
    //const Knowledge_Node* c_sort=list1->head;

    for(int i=0;i<list1->count-1;i++){

        while(nextl!=NULL&&sort!=NULL){

            if(sort->accessCount > nextl->accessCount){

                temp->accessCount=sort->accessCount;
                strncpy(temp->name,sort->name,strlen(sort->name)+1);
                sort->accessCount=nextl->accessCount;
                strncpy(sort->name,nextl->name,strlen(nextl->name)+1);
                nextl->accessCount=temp->accessCount;
                strncpy(nextl->name,temp->name,strlen(temp->name)+1);

            }
            sort=sort->next;
            nextl=nextl->next;

        }
        sort=list1->head;
        nextl=list1->head->next;

    }


}

void reverseList(){
    //Initialise three pointers, which we'll use to reverse the links of the
    //linked list
    Knowledge_Node *prevNode = NULL;
    Knowledge_Node *currentNode = list1->head;
    Knowledge_Node *nextNode = NULL;

    //This is where the linked list reversal is done
    while (currentNode != NULL){
        nextNode = currentNode->next;
        currentNode->next = prevNode;
        prevNode = currentNode;
        currentNode = nextNode;
    }

    //Previous Node points to the last node in the original list, so let's
    //make it the new head
    list1->head = prevNode;
}

void printList() {
    Knowledge_Node *temp = list1->head;
    while (temp != NULL){
        printf("%s %d\n", temp->name, temp->accessCount);
        temp = temp->next;
    }
}

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

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