c++中的数组和归并排序
Arrays and mergeSort in c++?
void Merge(int *array, int lo, int mid, int hi) {
int tArray[20];
int loBeg = lo;
int count = lo;
int hiBeg = mid + 1;
while (loBeg <= mid && hiBeg <= hi) {
if (array[loBeg] < array[hiBeg]) {
tArray[count] = array[loBeg];
loBeg++;
count++;
} else {
tArray[count] = array[hiBeg];
hiBeg++;
count++;
}
}
while (loBeg <= mid) {
tArray[count++] = array[loBeg++];
}
while (hiBeg <= hi) {
tArray[count++] = array[hiBeg++];
}
for (int i = 0; i < count; i++) {
array[i] = tArray[i];
}
}
void mergeSort(int *array, int lo, int hi) {
if (lo < hi) {
int mid = (lo + hi) / 2;
mergeSort(array, lo, mid);
mergeSort(array, mid + 1, hi);
Merge(array, lo, mid, hi);
}
}
int main(int argc, const char * argv[]) {
int array[] = {90, 99, 63, 82, 93, 76, 81, 76};
//int temp[8];
mergeSort(array, 0, 7);
for (int i = 0; i < 8; i++) {
std::cout << array[i] << std::endl;
}
return 0;
}
我的问题是关于数组的性质在这个合并排序代码。这段代码只适用于在Merge, O中设置tArray[20];
的初始值为20。为什么我不能将初始值设置为hi + 1
,在这种情况下是8
(与数组相同)?但是,如果我取消注释出temp[8]
数组,并通过mergeSort
和Merge
传递它,并将其用作Merge
中的tArray
(初始大小为8
),则它可以工作。
我认为我缺乏理解也是我原来的merge()
(见下文)函数也不起作用的原因:
//this was my original merge code which does not work.
void merge(int *array, int lo, int mid, int hi) {
int tempArray[hi + 1];
int loBeg = lo;
int hiBeg = mid + 1;
for (int i = 0; i <= hi; i++) {
if (hiBeg > hi || (array[loBeg] < array[hiBeg] && loBeg <= mid)) {
tempArray[i] = array[loBeg++];
} else {
tempArray[i] = array[hiBeg++];
}
}
for (int i = 0; i <= hi; i++) {
array[i] = tempArray[i];
}
}
所以基本上我想知道为什么在第一个Merge()
函数中,我必须将tArray
初始大小设置为20
而不是与数组相同的大小,除非我从main
传递一个临时数组(初始化为与数组相同的大小),然后进一步,为什么我原来的merge()
函数不起作用,但我认为这与我缺乏对第一个Merge()函数的理解有关。
当你创建一个像int array[20];
这样的数组时,你是在你的程序的堆栈内存中分配它。这个内存是在程序开始之前分配的。
int array[hi + 1];
时,您要求它分配在程序启动之前未知的内容量,这会导致错误。在这种情况下,你需要做的是使用动态内存。这些内存在运行时分配并释放。这意味着您可以执行int* array = new int[hi + 1];
并且不会导致错误。
整个合并函数将是:
void merge(int *array, int lo, int mid, int hi) {
int* tempArray = new int[hi + 1];
int loBeg = lo;
int hiBeg = mid + 1;
for (int i = 0; i <= hi; i++) {
if (hiBeg > hi || (array[loBeg] < array[hiBeg] && loBeg <= mid)) {
tempArray[i] = array[loBeg++];
} else {
tempArray[i] = array[hiBeg++];
}
}
for (int i = 0; i <= hi; i++) {
array[i] = tempArray[i];
}
delete[] tempArray;
}
我不建议你自己管理动态内存。您应该使用STL:vector<int> tempArray(hi + 1);
而不是int* tempArray = new int[hi + 1];
。这样,您就不必在末尾加上delete[] tempArray;
了。
您的代码中存在多个问题,以下是其中的几个:
void Merge(int *array, int lo, int mid, int hi) {
// The size should be hi - lo + 1, not hi + 1
int tArray[hi + 1];
int loBeg = lo;
// count should start at 0, not lo
int count = lo;
int hiBeg = mid + 1;
while (loBeg <= mid && hiBeg <= hi) {
if (array[loBeg] < array[hiBeg]) {
tArray[count] = array[loBeg];
loBeg++;
count++;
} else {
tArray[count] = array[hiBeg];
hiBeg++;
count++;
}
}
while (loBeg <= mid) {
tArray[count++] = array[loBeg++];
}
while (hiBeg <= hi) {
tArray[count++] = array[hiBeg++];
}
for (int i = 0; i < count; i++) {
// it should be array[lo + i], not array[i]
array[i] = tArray[i];
}
}
以下是对这3个错误的解释:
你不希望每次都有一个大小为
hi + 1
的数组,当你沿着"合并树"走下去时,你必须合并较小大小的数组,所以你需要使用hi - lo + 1
。实际上,在这种情况下使用hi + 1
应该不是问题,但是您分配了比实际需要更多的内存。您不应该从
lo
开始,而应该从0
开始,否则您的tArray[count]
将超出边界。从lo
开始,因为你分配了一个非常大的数组(大小为20
或hi + 1
),但它不适用于大小为hi - lo + 1
的数组,所以你应该小心。也许最大的错误-你总是替换原始数组的第一个
count
单元…不!您希望替换lo
和hi
之间的单元格,而不是0
和count
之间的单元格。
您需要记住,当您调用Merge (array, lo, mid, hi)
时,您要将array[lo:mid]
和array[mid+1:hi]
合并到array[lo:hi]
中。
这里有一些详细的解释:
让我们从下面的数组[90, 99, 63, 82, 93, 76, 81, 76]
开始,在每次调用mergeSort
时,您将数组分成两等份:
第一次你得到[90, 99, 63, 82]
(lo = 0
,hi = 3
)和[93, 76, 81, 76]
(lo = 4
和hi = 7
),然后你继续除法,直到你得到大小为1
的8
数组。为了简单起见,我将写(array, lo, hi)
,例如([90], 0, 0)
。
你应该得到一个点,你有([90], 0, 0)
,([99], 1, 1)
,等等…你将合并这些2乘2,所以你(例如)将合并([93], 4, 4)
和([76], 5, 5)
。当您合并这两个数组时,您将获得Merge
的调用,如下所示:
Merge (array, 4, 4, 5) // mid is (4 + 5) / 2 = 4
那么,Merge
函数中发生了什么?
您应该注意到,由于您正在合并两个大小为1的数组(
[93]
和[76]
),因此您需要一个大小为2的临时数组。如果您使用tArray[hi + 1]
,则分配一个大小为hi + 1 = 6
的数组,这比您实际需要的数组大得多(这里可能没有太大的区别,但想象一下如果您有一个大小为十亿的原始数组!)。因此,分配一个大小为hi - lo + 1 = 5 - 4 + 1 = 2
的数组就足够了。你实际上是你的初始数组的
4
到5
的范围,所以你想在那部分工作,你不想擦除部分0
到1
,你已经排序!但是如果在循环中执行array[i] = tArray[i]
会发生什么呢?好吧,i
从0
开始,到count
(在这种情况下应该是2
),所以你要替换array[0]
和array[1]
,而不是array[4]
和array[5]
。这可以通过修改array[lo + i]
而不是array[i]
来修复。
归并排序被认为适用于列表,因为当你合并两个列表时,你可以自由地将每个元素附加到你想要的元素上。
的例子:
Merge(List{3,4},List{5,6});
导致以下操作
List Merge(List a, List b){ //2 instructions even when Lists are long 1000000 elements
List newlist;
newlist.head = a.head;
newlist.tail = b.tail;
a.tail.next = b.head;
b.head.prev = a.tail;
return newList;
}
当你有数组的时候你需要分配一个新的数组大小:
int * Merge( int array* a, int array* b, unsigned int sizea, unsigned int sizeb){
//int tArray[20]; // :/ wrong
int * newarray = new int[sizea+sizeb];
for(unsigned int i=0; i<sizea; i++)
newarray[i]=a[i];
for(unsigned int i=0; i<sizeb; i++)
newarray[i+sizea]=a[i];
delete []a;
delete []b;
return newarray;
}
这顺便使算法更加昂贵。即使你预先分配了一个足够大的数组,算法的成本也会更高,因为你必须在每次合并时复制所有的元素。
- 在c++中尝试对对象数组进行排序时,出现std:bad_alloc错误
- 显示错误输出的简单数组排序程序
- 为什么我的排序算法会更改数组值
- 为什么我需要C++中不同的排序格式来对这个USACO代码上的数组和优先级队列进行排序
- 在 c++ 中对类中的 c 字符串动态数组进行排序的最佳方法是什么?
- 合并排序不排序自创建数组类 c++
- 带有枚举方向/类型的气泡排序结构数组
- 为什么指针在对二维数组进行排序时无法正常工作?
- 排序并行数组
- 如何在数组 c++ 中对字符串进行排序
- 为什么在此排序算法实现中,向量明显比数组慢?
- 如何对不在数组中的变量进行排序?
- C++数组与向量排序(在我的情况下,向量比数组慢~2.5倍(无优化))
- 按字母顺序对结构内数组变量中的名称进行排序
- 使用排序函数 c++ 对字符数组进行排序
- 使用 std::sort 对二维 c 数组进行排序
- c++中的数组和归并排序
- 归并函数中动态数组的归并排序
- 数组中的反转次数.使用归并排序
- 归并排序递归不清楚数组的排序是如何实现的,请帮助理解代码