Method 1 :
void LinkedList::BubbleSortVer1( ){
if( !head ) return;
bool change = true;
while( change ){ //round
Node *prev = NULL;
Node *current = head;
change = false;
while( current->next != NULL ){
if( current->value > current->next->value ){
current = swap(current, current->next);
change = true;
if( prev != NULL )
// swap is unrelated to head, update prev' s next link
prev->next = current;
else
// swap is related to head, change head pointer
head = current;
}
prev = current;
current = current->next;
}
}
}
Node* LinkedList::swap( Node* p, Node* q){
Node *temp = q->next;
q->next = p;
p->next = temp;
return q;
}
|
Main idea:
- 藉由兩兩swap把最大的丟到最後面
- 利用一個change flag 來判斷sorting完成否 (可以省略計算目前是第幾round)
- 獨立的Swap function: 另外提出來做Node的Swap, 回傳Swap後, 前面的node, 如此可以讓iteration繼續下去
- 利用兩個pointer, 一個是當前指標current, 一個是current的前一個node的指標prev
- 比較當前node與下一個node的值, 來決定要不要swap
- 注意head的位置會跑掉, 必須在swap判斷時, 判斷prev的位置; 如果prev的位置是在NULL, 表示目前current是head, 必須更新head, 否則更新prev的next連結位置
- 前進prev和current
Method 2:
void LinkedList::BubbleSortVer2( ){
if( !head ) return;
bool change = true;
Node *prevHead = new Node(0, head);
while( change ){
change = false;
Node *prev = prevHead;
Node *current = prev->next;
while( current->next != NULL ){
if( current->value > current->next->value ){
prev->next = current = swap(current, current->next);
change = true;
}
prev = current;
current = current->next;
}
}
head = prevHead->next;
delete prevHead;
}
Node* LinkedList::swap( Node* p, Node* q){
Node *temp = q->next;
q->next = p;
p->next = temp;
return q;
}
|
Main idea:
- 與作法1大致相同, 只差在此方法另外開一個新的dummy node去只向head, 此時, 可以在每次swap後, 都更新前一個node的next, 不用擔心前一個是NULL
- 與作法1相比, 差了一個if的判斷式, 判別前一個node是不是非空, 來決定要不要更新前一個node的next, 或者是更新head
C++ code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
| #include <iostream>
using namespace std;
class Node{
public:
Node() : value(0), next(NULL) {}
Node( int theValue, Node *theNext ) : value(theValue), next(theNext){}
int value;
Node *next;
};
class LinkedList{
public:
LinkedList( );
~LinkedList( );
void push_front( int value );
void push_back( int value );
void delete_front( );
void show_element( );
void BubbleSortVer1( );
void BubbleSortVer2( );
private:
Node* head;
Node* swap( Node*, Node* );
};
LinkedList::LinkedList( ) : head(NULL){
}
LinkedList::~LinkedList( ){
if( head )
delete_front( );
}
void LinkedList::push_front( int value ){
Node *newNode = new Node(value, head);
head = newNode;
}
void LinkedList::push_back( int value ){
if( !head )
push_front( value );
else{
Node *current = head;
while( current->next != NULL )
current = current->next;
Node *newNode = new Node(value, NULL);
current->next = newNode;
}
}
void LinkedList::delete_front( ){
if( !head )
return;
Node *deleteNode = head;
head = head->next;
delete deleteNode;
}
void LinkedList::show_element( ){
Node *current = head;
while( current ){
cout << current->value << " ";
current = current->next;
}
cout << endl;
}
void LinkedList::BubbleSortVer1( ){
if( !head ) return;
bool change = true;
while( change ){ //round
Node *prev = NULL;
Node *current = head;
change = false;
while( current->next != NULL ){
if( current->value > current->next->value ){
current = swap(current, current->next);
change = true;
if( prev != NULL )
// swap is unrelated to head, update prev' s next link
prev->next = current;
else
// swap is related to head, change head pointer
head = current;
}
prev = current;
current = current->next;
}
show_element( );
}
}
void LinkedList::BubbleSortVer2( ){
if( !head ) return;
bool change = true;
Node *prevHead = new Node(0, head);
while( change ){
change = false;
Node *prev = prevHead;
Node *current = prev->next;
while( current->next != NULL ){
if( current->value > current->next->value ){
prev->next = current = swap(current, current->next);
change = true;
}
prev = current;
current = current->next;
}
}
head = prevHead->next;
delete prevHead;
}
Node* LinkedList::swap( Node* p, Node* q){
Node *temp = q->next;
q->next = p;
p->next = temp;
return q;
}
int main( ){
LinkedList list;
list.push_back( 4 );
list.push_back( 7 );
list.push_back( 5 );
list.push_back( 1 );
list.push_back( 3 );
list.push_back( 2 );
list.push_front( 6 );
list.push_front( 0 );
list.show_element( );
list.delete_front( );
list.show_element( );
cout << "sorting list1: \n";
list.BubbleSortVer2( );
cout << "After sort: ";
list.show_element( );
LinkedList list2;
list2.push_back( 1 );
list2.push_back( 2 );
list2.push_back( 3 );
list2.push_back( 4 );
list2.push_back( 5 );
list2.push_back( 7 );
list2.push_back( 6 );
cout << "\nsorting list2: \n";
list2.BubbleSortVer2( );
cout << "After sort: ";
list2.show_element( );
return 0;
}
|
結論:
- bubble sort將大的往後swap到底端
- swap node另外實做一個函數, 回傳swap後前面的node, 非常重要且省事!
- round數不需要計算node總個數, 利用change flag來觀察是否已經完成sorting
- Maintain 兩個指標, previous及current, 其中previous是要用來更新swap後的鏈結方式, current是用來判斷pari間的大小關係
Reference:
沒有留言:
張貼留言