问题描述
试图使用链表实现冒泡排序,但不起作用。谁能在我的代码中识别出问题。我认为在类singlylinkedist
中有一个名为bubblesort
的函数,其中的for循环不起作用,用于对链表进行完全排序。它只会对列表进行一次排序,而不会对链表的大小进行排序。
#include<iostream>
using namespace std;
class Node{
public:
int data;
Node *next;
Node()
{
data = 0;
next = NULL;
}
Node(int d)
{
data = d;
}
};
class singlylinkedlist{
public:
Node *head,*tail;
singlylinkedlist()
{
head = NULL;
tail = NULL;
}
void appendNode(Node *temp)
{
if (head == NULL)
{
head = temp;
tail = temp;
cout << "Node Appended" << endl;
}
else
{
tail->next = temp;
tail = tail->next;
cout << "Node Appended" << endl;
}
}
void prependNode(Node *temp)
{
temp->next = head;
head = temp;
cout<< "Node Prepended" << endl;
}
int getdata(int pos)
{
Node *curr = new Node;
curr = head;
for(int i=1;i<pos;i++)
{
curr = curr->next;
}
return curr->data;
}
void printList()
{
if (head == NULL)
{
cout << "No Nodes in Singly Linked List";
}
else
{
cout << endl << "Singly Linked List Values : ";
Node *temp = head;
while (temp != NULL)
{
cout << "--> "<<temp -> data;
temp = temp -> next;
}
cout<<"\n";
}
}
int ListSize()
{
int count=0;
if (head == NULL)
{
cout << "No Nodes in Singly Linked List";
}
else
{
Node *temp = head;
while (temp != NULL)
{
temp = temp -> next;
count = count+1;
}
}
return count;
}
void bubblesort(Node *temp)
{
temp= head;
Node *ptr;
Node *prev = NULL;
for(int j=0;j<ListSize();j++)
{
while(temp!=NULL && temp->next!=NULL){
if(temp->data > temp->next->data){
if(prev == NULL){
ptr = temp->next;
temp->next = ptr->next;
ptr->next = temp;
head = prev = ptr;
}
else{
ptr = temp->next;
prev->next = ptr;
temp->next = ptr->next;
ptr->next = temp;
prev = ptr;
}
}
else{
ptr = temp->next;
prev = temp;
temp = ptr;
}
}
}
}
};
int main()
{
singlylinkedlist s;
int option;
int data1;
int pos;
do{
cout << "\nWhat operation do you want to perform? Select Option number. Enter 0 to exit." << endl;
cout << "1. appendNode()" << endl;
cout << "2. prependNode()" << endl;
cout << "3. getdata()" << endl;
cout << "6. printList()" << endl;
cout << "7. bubblesort()" << endl;
cin>>option;
Node *temp = new Node;
switch (option) {
case 0:
break;
case 1:
cout << "Append Node Operation \nEnter data of the Node to be Appended" << endl;
cin >> data1;
temp->data = data1;
temp->next = NULL;
s.appendNode(temp);
break;
case 2:
cout<<"Prepend Node Operation \nEnter data of the Node to be Prepended" << endl;
cin>>data1;
temp->data = data1;
temp->next = NULL;
s.prependNode(temp);
break;
case 3:
cout<<"enter position to get data"<<endl;
cin>>pos;
cout<<"DATA AT GIVEN INDEX IS " << s.getdata(pos);
break;
case 6:
s.printList();
break;
case 7:
s.bubblesort(temp);
s.printList();
break;
}
}while (option != 0);
}
解决方法
撇开其余残破的代码,排序的主要问题是无法在最外层循环的每次迭代中重置prev
和temp
。列表的每次扫描都需要将其重置(prev
应该重新启动为null,temp
应该重新启动为head
。这样做是:
void bubblesort()
{
for(int j=0;j<ListSize();j++)
{
Node *prev = nullptr;
Node *temp = head;
while(temp != nullptr && temp->next != nullptr)
{
if(temp->data > temp->next->data)
{
if(prev == nullptr)
{
Node *ptr = temp->next;
temp->next = ptr->next;
ptr->next = temp;
head = prev = ptr;
}
else
{
Node *ptr = temp->next;
prev->next = ptr;
temp->next = ptr->next;
ptr->next = temp;
prev = ptr;
}
}
else
{
Node *ptr = temp->next;
prev = temp;
temp = ptr;
}
}
}
}
替代
一些注意事项。这只是半气泡排序。 Bubblesort的重点是,每次扫描时,“最大”节点都会冒泡到末端。例如。它不再需要再次访问,因为 nothing 会“更大”(这就是它首先冒泡到最后的方式)。但是,使用您的算法,您会反复扫描整个列表,而不是比先前的迭代少一个少的节点。
执行此操作的一种简单方法是在列表末尾将其从列表中卸下,然后将其移至整个新链的最前面。然后该算法变为。
- 扫描列表,将活动列表的最大节点起泡到最后
- 从该列表中删除节点,并将其添加到新链之前。
- 继续(1)和(2),直到旧列表中没有更多节点为止。
- 新链现在是新列表。设置
head
,您就完成了。
以可视方式进行此操作,假设我们列表中有五个元素,最初是一个空的“结果”列表。
list: 7 4 5 2 6
result: null
在(1)和(2)的第一遍之后,我们得到:
list: 4 5 2 6
result: 7
第二遍:
list: 4 2 5
result: 6 7
第三遍:
list: 2 4
result: 5 6 7
第四遍:
list: 2
result: 4 5 6 7
最后:
list: null
result 2 4 5 6 7
这时,我们可以简单地将list
设置为result
,现在我们的列表已排序。
以下是使用指针到指针方法实现此目的的实现。请注意,我们无需在任何地方获取或关心列表大小(即,无需调用ListSize()
)。
void bubblesort()
{
Node *result = nullptr;
while (head != nullptr)
{
// starts at the beginning of the list
Node **pp = &head;
while ((*pp)->next != nullptr)
{
Node **pp2 = &(*pp)->next;
if ((*pp2)->data < (*pp)->data)
{
// swap pointers,then swap back their next members.
std::swap(*pp,*pp2);
std::swap((*pp)->next,(*pp2)->next);
}
// advance to next node in the list.
pp = &(*pp)->next;
}
// prepend to new list,unlink from old one.
(*pp)->next = result;
result = *pp;
*pp = nullptr;
}
// new list is built
head = result;
}
测试
在{1..99}中生成二十个值的随机序列,打印,然后排序,然后再次打印。对于香料,首先会生成所有奇数值;所有偶数值都被附加。列表建立后,我们将气泡松开,然后打印最终结果。
#include <iostream>
#include <utility>
#include <random>
class Node{
public:
int data;
Node *next;
Node(int d=0)
: data(d),next(nullptr)
{
}
};
class singlylinkedlist{
public:
Node *head,*tail;
singlylinkedlist()
: head(nullptr),tail(nullptr)
{
}
~singlylinkedlist()
{
while (head)
{
Node *tmp = head;
head = head->next;
delete tmp;
}
}
// squelch these; copying not supported.
singlylinkedlist(const singlylinkedlist&) = delete;
singlylinkedlist& operator =(const singlylinkedlist&) = delete;
void appendNode(int data)
{
Node *p = new Node(data);
if (head == nullptr)
head = p;
else
tail->next = p;
tail = p;
}
void prependNode(int data)
{
Node *p = new Node(data);
p->next = head;
if (head == nullptr)
tail = p;
head = p;
}
int getdata(int pos)
{
Node *curr = head;
while (curr != nullptr && pos-- > 0)
curr = curr->next;
return curr ? curr->data : 0; // TODO: throw an exception if out of range?
}
void printList() const
{
for (const Node *p = head; p != nullptr; p = p->next)
std::cout << p->data << ' ';
std::cout << '\n';
}
int size() const
{
int count=0;
for (const Node *p = head; p != nullptr; p = p->next)
++count;
return count;
}
void bubblesort()
{
Node *result = NULL;
while (head != nullptr)
{
// starts at the beginning of the list
Node **pp = &head;
while ((*pp)->next != nullptr)
{
Node **pp2 = &(*pp)->next;
if ((*pp2)->data < (*pp)->data)
{
// swap pointers,then swap back their next members.
std::swap(*pp,*pp2);
std::swap((*pp)->next,(*pp2)->next);
}
// advance to next node in the list.
pp = &(*pp)->next;
}
// link to new list,unlink from old one.
(*pp)->next = result;
result = *pp;
*pp = nullptr;
}
// new list is built
head = result;
}
};
int main()
{
// fixed seed for repetitive testing. replace 42 with
// std::random_device{}() for random sequence
std::mt19937 rng{ 42 };
std::uniform_int_distribution<> dist(1,99);
singlylinkedlist s;
for (int i=0; i<20; ++i)
{
int data = dist(rng);
if (data % 2)
s.prependNode(data);
else
s.appendNode(data);
}
s.printList();
s.bubblesort();
s.printList();
}
输出
53 3 75 75 87 83 21 61 15 93 52 72 88 24 22 2 88 30 38 2
2 2 3 15 21 22 24 30 38 52 53 61 72 75 75 83 87 88 88 93