使用链表排序给定的字符数组
在这个问题中,我们需要使用链表对给定的字符数组进行排序。我们可以使用冒泡排序、选择排序、归并排序等技术对数组进行排序。
在这里,我们将首先将数组转换为链表,然后使用选择排序和冒泡排序技术对数组进行排序。
问题陈述 - 我们给定一个长度为 N 的数组 arr[]。该数组包含小写字母字符。我们需要使用链表对数组进行排序。
示例
输入
arr[] = {'e', 's', 'a', 'x', 'c', 'e','f', 'p', 'b', 'n', 'a'};
输出
a -> a -> b -> c -> e -> e -> f -> n -> p -> s -> x -> NULL
解释 - 我们已经按升序对数组进行了排序。
输入
arr[] = {'g', 'g', 'h', 'i', 'j', 'k', 'k', 'l', 'm', 'n', 'o'};
输出
g -> g -> h -> i -> j -> k -> k -> l -> m -> n -> o -> NULL
解释 - 数组 arr[] 和输出与数组相同,因为数组已经排序。
方法 1
在这种方法中,我们将使用冒泡排序算法对链表进行排序。首先,我们将数组转换为链表,然后使用冒泡排序技术。在冒泡排序技术中,我们进行总共 N 次迭代来交换所有大于下一个元素的列表元素。
算法
步骤 1 - sortLinkedList() 函数用于对链表进行排序,它以起始节点和列表长度作为参数。
步骤 2 - 定义 'curr' 节点和 'swapped' 布尔变量以跟踪单次迭代中是否发生了任何交换。
步骤 3 - 使用循环遍历链表。将 'start' 节点分配给 'curr' 并将 'swapped' 初始化为 false。
步骤 4 - 现在,使用另一个嵌套循环进行迭代,直到 len − p −1。定义 'temp1' 和 'temp2' 变量并将它们分别初始化为 'curr' 节点及其下一个节点。
步骤 5 - 如果 temp1 −> ch 大于 temp2 −> ch,则交换它们并更新 'curr' 节点和 'swapped' 变量的值。
步骤 6 - 将 'curr' 移动到下一个节点。
步骤 7 - 如果 'swapped == false' 并且在使用嵌套循环进行迭代时未更新,则中断外循环,因为列表已排序。
示例
在这个例子中,我们使用了结构来创建链表。此外,我们定义了 addNode() 函数将节点插入到当前列表中。我们获取数组的每个元素并使用 addNode() 函数将字符添加到列表中。
addNode() 函数遍历列表,直到获取最后一个节点,并在最后添加新节点。
#include <iostream> using namespace std; // creating the struct listNode struct listNode { int ch; listNode *next; } listNode; // Swapping the nodes of the linked list struct listNode *swap(struct listNode *pointer1, struct listNode *pointer2) { struct listNode *tmp = pointer2->next; pointer2->next = pointer1; pointer1->next = tmp; return pointer2; } // Sorting the linked list void sortLinkedList(struct listNode **start, int len) { // storing the current node struct listNode **curr; int p, q; bool swapped = false; for (p = 0; p <= len; p++) { // store the current node address in curr curr = start; swapped = false; // traverse the list for (q = 0; q < len - p - 1; q++) { struct listNode *temp1 = *curr; struct listNode *temp2 = temp1->next; // If temp1 > temp2 swap them if (temp1->ch > temp2->ch) { // Update the link after swapping *curr = swap(temp1, temp2); swapped = true; } // Move the current pointer to the next node curr = &(*curr)->next; } // If any pair of elements is not swapped, break the loop. if (swapped == false) break; } } // adding nodes to the linked list void addNode(struct listNode **start, int ch) { // creating a new node struct listNode *temp = new struct listNode(); // add ch to the node temp->ch = ch; temp->next = NULL; // If the list is empty, add a node to the list if (*start == NULL) { *start = temp; } else { // If the list has some nodes, append the node at the end of the list struct listNode *pointer1 = *start; while (pointer1->next != NULL) { pointer1 = pointer1->next; } pointer1->next = temp; } } // print nodes void printLinkedList(struct listNode *head) { cout << "The sorted list is " << endl; while (head != NULL) { cout << char(head->ch) << " -> "; head = head->next; } cout << "NULL" << endl; } int main() { int arr[] = {'e', 's', 'a', 'x', 'c', 'e', 'f', 'p', 'b', 'n', 'a'}; int len, p; // create an empty linked list struct listNode *start = NULL; len = sizeof(arr) / sizeof(arr[0]); // inserting characters of the array to a linked list for (p = 0; p < len; p++) addNode(&start, arr[p]); // Sort the list sortLinkedList(&start, len); printLinkedList(start); return 0; }
输出
The sorted list is a -> a -> b -> c -> e -> e -> f -> n -> p -> s -> x -> NULL
时间复杂度 - O(N^2),因为我们使用了两个嵌套循环。
空间复杂度 - O(1),因为我们没有在 sortLinkedList() 函数中使用动态空间。但是,当我们将数组转换为列表时,我们使用了 O(N) 空间,但这不属于排序的一部分。
方法 2
在这种方法中,我们将使用选择排序算法对链表进行排序。在选择排序算法中,我们从 len − p 的后缀中找到包含最小值的节点。之后,我们将最小节点与第 p 个索引处的节点交换。
算法
步骤 1 - 定义并初始化 'current' 节点为 'start' 节点。
步骤 2 - 使用 while 循环进行迭代,直到 'current' 节点不为空。
步骤 3 - 将 'minNode' 初始化为 'current' 节点,并将 'traverse' 初始化为下一个 current,因为我们需要找到最小节点。
步骤 4 - 使用嵌套 while 循环查找最小节点并将其与 'current' 节点交换。
步骤 5 - 将 current 节点移动到下一个。
示例
#include <iostream> using namespace std; struct listNode { int ch; listNode* next; }; void swapNodes(struct listNode* node1, struct listNode* node2) { int temp = node1->ch; node1->ch = node2->ch; node2->ch = temp; } void sortLinkedList(struct listNode* start) { struct listNode* current = start; while (current != nullptr) { struct listNode* minNode = current; struct listNode* traverse = current->next; while (traverse != nullptr) { if (traverse->ch < minNode->ch) { minNode = traverse; } traverse = traverse->next; } swapNodes(current, minNode); current = current->next; } } void addNode(struct listNode** start, int ch) { struct listNode* newNode = new struct listNode(); newNode->ch = ch; newNode->next = nullptr; if (*start == nullptr) { *start = newNode; } else { struct listNode* current = *start; while (current->next != nullptr) { current = current->next; } current->next = newNode; } } void printLinkedList(struct listNode* head) { cout << "The sorted list is " << endl; while (head != nullptr) { cout << char(head->ch) << " -> "; head = head->next; } cout << "NULL" << endl; } int main() { int arr[] = {'e', 's', 'a', 'x', 'c', 'e', 'f', 'p', 'b', 'n', 'a'}; int len = sizeof(arr) / sizeof(arr[0]); struct listNode* start = nullptr; for (int p = 0; p < len; p++) { addNode(&start, arr[p]); } sortLinkedList(start); printLinkedList(start); return 0; }
输出
The sorted list is a -> a -> b -> c -> e -> e -> f -> n -> p -> s -> x -> NULL
时间复杂度 - O(N^2),因为我们使用了两个嵌套 while 循环。
空间复杂度 - O(1),因为我们没有使用动态空间。