因排序代码过多,同样分成两个博文来发表。
- #include <iostream>
- using namespace std;
- /*
- 希尔排序的分组是gap(增量)的倍数
- 堆排序的分组是 树(子树)的分组
- */
- #define MAXSIZE 20
- #define MAXD 8
- typedef int ElemType;
- typedef struct node
- {
- ElemType data;
- struct node *next;
- }Node;
- void CreateList(Node *&nodes, int iarr[], int len) //此函数是创建一个单链表
- {
- int loop1 = 0;
- Node *temp = NULL, *temp2 = NULL;
- if(nodes != NULL) free(nodes);
- nodes = (Node *)malloc(sizeof(Node));
- nodes->next = NULL;
- temp2 = nodes;
- for(loop1 = 0; loop1 < len ; ++loop1)
- {
- temp = NULL;
- temp = (Node *)malloc(sizeof(Node));
- temp->data = iarr[loop1];
- temp->next = temp2->next;
- temp2->next = temp;
- temp2 = temp;
- }
- }
- void InsertSort2(Node *&nodes) //对单链表进行排序
- {
- Node *temp = NULL, *node = NULL, *prenode = NULL, *pre = NULL;
- if(nodes == NULL || nodes->next == NULL )
- { cout<<"wrong parameter"<<endl;return ; }
- else
- { pre = nodes;
- temp = nodes->next;
- prenode = temp->next;
- node = temp->next;
- temp->next = NULL; //把第三个域的值给置空, 被一个单链表分为两个单链表
- while(prenode != NULL)
- {
- node = prenode;
- pre = nodes;
- temp = nodes->next;
- while(temp != NULL && (node->data > temp->data)) //判断的条件的顺序不能颠倒,这一点要谨慎
- {
- pre = temp;
- temp = temp->next;
- }
- prenode = prenode->next;
- node->next = pre->next;
- pre->next = node;
- }
- }
- }
- void Disp(Node *nodes)
- {
- Node *temp = NULL;
- if(nodes != NULL)
- {
- temp = nodes->next;
- while(temp != NULL)
- {
- cout<<temp->data<<' ';
- temp = temp->next;
- }
- }
- cout<<endl;
- }
- void Disp(int iarr[], int len)
- {
- int loop1 = 0;
- while(loop1 < len)
- {
- cout<<iarr[loop1]<<' ';
- ++loop1;
- }
- cout<<endl;
- }
- void Disp(char iarr[][4], int len)
- {
- int loop1 = 0;
- while(loop1 < len)
- {
- cout<<iarr[loop1]<<' ';
- ++loop1;
- }
- cout<<endl;
- }
- void InsertSort(int iarr[], int len) //此函数是直接插入排序,从数组中得出一个值,把它按照顺序插入到前面的数组中
- {
- int loop1 = 0, loop2 = 0, loop3 = 0, temp = 0;
- for(loop1 = 1; loop1 < len ; ++loop1) //循环从1以后的元素
- {
- temp = iarr[loop1];
- for(loop2 = 0; loop2 < loop1 && temp > iarr[loop2]; ++loop2); //找到要插入的位置
- loop3 = loop1;
- while(loop3 >= loop2) //移动元素
- {
- iarr[loop3] = iarr[loop3 - 1];
- --loop3;
- }
- iarr[loop2] = temp;
- }
- }
- void ShellSort(int iarr[], int len) //此函数又称为缩小增量, 把记录按下标的一定在增量gap,其中下标值是gap倍数的元素为一组,对这一组元素进行插入排序
- { //每次循环,都把gap缩小到原来的二分之一, 直到其值为0. 主要思想是其分组的方式是把 增量的倍数为一组
- int loop1 = 0, loop2 = 0, temp = 0, gap = 0;
- gap = len / 2;
- while(gap > 0)
- {
- for(loop1 = gap; loop1 < len ; ++loop1)
- {
- temp = iarr[loop1];
- loop2 = loop1 - gap;
- while(loop2 >= 0 && iarr[loop2] > temp) //此循环就相当于一个插入排序
- {
- iarr[loop2 + gap] = iarr[loop2];
- loop2 = loop2 - gap;
- }
- iarr[loop2 + gap] = temp;
- }
- gap = gap / 2;
- }
- }
- void SelectSort(int iarr[], int len) //此函数是选择,在无序的区间里面选择一个最小的,然后把其置于有序区间的最后
- {
- int loop1 = 0,loop2 = 0, min = 0, pos = 0; //min 保存的是最小的值, pos保存的是最小值的下标位置
- for(loop1 = 0; loop1 < len ; ++loop1)
- { pos = loop1;
- min = iarr[loop1];
- for(loop2 = loop1 + 1; loop2 < len ; ++loop2)
- if(min > iarr[loop2])
- { min = iarr[loop2]; pos = loop2;}
- iarr[pos] = iarr[loop1]; //此处赋值不可整错
- iarr[loop1] = min;
- }
- }
- void sift(int iarr[], int low, int high) //由于堆排序是要把堆化为大根堆或者小根堆, 此函数就是这个功能
- {
- int loop1 = low, loop2 = low *2 ,value = iarr[low];
- while(loop2 <= high)
- {
- if(loop2 < high && iarr[loop2] < iarr[loop2 + 1])
- ++loop2;
- if(value < iarr[loop2]) //这里比较的是最初的iarr[low]的值,如果满足条件的话,就把loop2继续向下深入,因为是数组存储,所以其子节点的下标为 loop2 * 2
- {
- iarr[loop1] = iarr[loop2];
- loop1 = loop2; //loop1 的作用相当于链表中 前驱
- loop2 = loop2 * 2;
- }else break;
- }
- iarr[loop1] = value;
- }
- void HeapSort(int iarr[], int len) //堆排序的思想是,按堆的定义把数组调整为堆(创建初始堆,此后就是大根堆了),然后交换第一个元素与最后一个元素,这样最后一个元素就是最大的值,然后对倒数第二个元素之前的元素进行堆排序,一直重复上个过程即可。
- { //其中数组的开始是从1 开始的,第0个节点没用
- int mid = len / 2, loop1 = 0, temp = 0;
- for(; mid > 0; --mid) //mid的指向是最后一个 枝节点, 对所有枝节点进行调整为堆。
- sift(iarr,mid,len);
- for(loop1 = len ; loop1 > 1; --loop1)
- {
- temp = iarr[1];
- iarr[1] = iarr[loop1];
- iarr[loop1] = temp;
- sift(iarr,1,loop1 - 1); //此处只执行一次是因为,除了根节点外都是满足大(小)根堆的要求,所以只对根节点进行操作
- }
- }
- void sift2(int iarr[], int low, int high)
- {
- int ivar1 = low, ivar2 = low * 2, tempval = iarr[low];
- while(ivar2 <= high)
- {
- if(ivar2 < high && iarr[ivar2] > iarr[ivar2 + 1]) //此时应该把最小的值放在根节点处
- ++ivar2;
- if(tempval > iarr[ivar2])
- {
- iarr[ivar1] = iarr[ivar2];
- ivar1 = ivar2;
- ivar2 = 2 * ivar2;
- }else break;
- }
- iarr[ivar1] = tempval;
- }
- void HeapSort2(int iarr[], int len) //此是按照从大到小的顺序排序,即树是一个小根树
- {
- int loop1 = 0, mid = len / 2, loop2 = 0, temp = 0;
- for(; mid > 0; --mid)
- sift2(iarr,mid,len);
- for(loop2 = len ; loop2 > 1; --loop2)
- {
- temp = iarr[1];
- iarr[1] = iarr[loop2];
- iarr[loop2] = temp;
- sift2(iarr,1,loop2 - 1);
- }
- }
- bool isSmallHeap(int iarr[], int len) //判断是否是一个小根堆,如果是的话,那么一个节点的左右子节点的值,都要比其双亲节点的值要大
- { //要判断数组的长度是为奇数还是偶数, 如果是偶数的话,那么最后一个枝节点就少一个右节点
- int loop1 = 0, mid = len / 2;
- bool isNOdd = false;
- if(len % 2 == 0) isNOdd = true;
- for(loop1 = 1; loop1 <= mid ; ++loop1)
- {
- if(isNOdd && loop1 == mid)
- {
- if(iarr[loop1] < iarr[2 * loop1])
- continue;
- else return false;
- }
- else
- {
- if(iarr[loop1] < iarr[2 * loop1] && iarr[loop1] < iarr[2 * loop1 + 1])
- continue;
- else return false;
- }
- }
- return true;
- }
- void BubbleSort(int iarr[], int len) //冒泡排序,把相邻的前后两个元素成为有序
- {
- int loop1 = 0, loop2 = 0, temp = 0;
- bool isExchange = false; //此变量表示是否交换了数据, 如果没有交换,那么说明其顺序是有序的不需要进行后面的排序操作,直接返回即可
- for(loop1 = 0; loop1 < len; ++loop1)
- { isExchange = false;
- for(loop2 = len -1 ; loop2 > loop1 ; --loop2) //此循环代表一次排序
- {
- if(iarr[loop2] < iarr[loop2 - 1])
- {
- temp = iarr[loop2];
- iarr[loop2] = iarr[loop2 -1];
- iarr[loop2 - 1] = temp;
- isExchange = true;
- }
- }
- if(!isExchange) return ;
- }
- }
- void DBubble(int iarr[], int len) //双向冒泡排序, 实际上是一个排序区间从两边向中间缩小的过程, 而单个冒泡排序则是从一边向中间缩小的过程
- {
- int loop1 = 0, mid = len / 2, loop2 = 0,temp = 0;
- bool isExchange = false;
- for(loop1 = 0; loop1 < mid; )
- { isExchange = false;
- for(loop2 = len -1 - loop1; loop2 > loop1; --loop2) //从后向前循环
- {
- if(iarr[loop2] < iarr[loop2 - 1])
- {
- temp = iarr[loop2];
- iarr[loop2] = iarr[loop2 - 1];
- iarr[loop2 - 1] = temp;
- isExchange = true;
- }
- }
- ++loop1; //此处++表明上一步骤后loop1已经存放了最终值, 所以不需要继续对其进行排序
- if(isExchange && loop1 < mid) //表示当有交换值并且loop1还没有达到临界的时候
- {
- for(loop2 = loop1; loop2 < len - loop1; ++loop2) //此循环是从未达到最终值的左边开始向右,但是条件是 loop2 < len - loop1,表明后面排过序的元素不再比较
- {
- if(iarr[loop2] > iarr[loop2 + 1])
- {
- temp = iarr[loop2];
- iarr[loop2] = iarr[loop2 + 1];
- iarr[loop2 + 1] = temp;
- }
- }
- }else return ;
- }
- }
- void DBubble2(int iarr[], int len) //此循环同样是一个双向的冒泡排序,不同的是它的循环条件是exchange==1,这样直到一趟排序中没有交换的时候完成全部的排序
- {
- int loop1 = 0, ivar = 0, temp = 0;
- int exchange = 1;
- while(exchange == 1)
- {
- exchange = 0;
- for(loop1 = len -1 -ivar; loop1 > ivar; --loop1)
- {
- if(iarr[loop1] < iarr[loop1 - 1])
- {
- temp = iarr[loop1];
- iarr[loop1] = iarr[loop1 - 1];
- iarr[loop1 - 1] = temp;
- exchange = 1;
- }
- }
- ++ivar;
- if(exchange == 1)
- for(loop1 = ivar; loop1 < len - ivar; ++loop1)
- {
- if(iarr[loop1] > iarr[loop1 + 1])
- {
- temp = iarr[loop1];
- iarr[loop1] = iarr[loop1 + 1];
- iarr[loop1 + 1] = temp;
- }
- }
- }
- }
- void QuickSort(int iarr[], int begin, int end) //快速排序的思想是 先取出一个元素,然后从最后一个元素开始向左进行,直到找到一个比取得元素小的元素,把此元素放在取出元素的位置,
- { //然后从开始出向右进行,找到一个比取出元素大的元素,把其放在右边取出的位置上, 如此循环直到向左的下标与向右的下标相遇, 此时这个下标就是刚开始取得元素的最终位置
- int temp = iarr[begin], loop1 = begin, loop2 = end - 1; //快速排序与冒泡排序一样,每一次循环都要把一个元素放在最终的位置上。
- // cout<<"loop1 : "<<loop1<<" loop2 : "<<loop2<<" begin : "<<begin<<" end :"<<end<<endl;
- if(begin >= end) return;
- while(loop1 < loop2)
- {
- while(loop1 < loop2 && iarr[loop2] > temp)
- --loop2;
- if(loop1 < loop2) //此处还需要有一个判断,因为上一步的--loop2会使loop2 < loop1
- { iarr[loop1] = iarr[loop2];
- ++loop1; //此处进行++操作,因为原来的值不需要操作
- }
- while(loop1 < loop2 && iarr[loop1] < temp)
- ++loop1;
- if(loop1 < loop2)
- {
- iarr[loop2] = iarr[loop1];
- --loop2;
- }
- }
- cout<<"loop1 : "<<loop1<<" loop2 : "<<loop2<<endl;
- iarr[loop1] = temp;
- QuickSort(iarr,begin, loop1 );
- QuickSort(iarr,loop1 + 1, end );
- }
- void QuickSort2(int iarr[], int begin, int end) //此函数是快速排序的非递归算法,利用一个队列保存每个区间
- {
- struct
- {
- int begin, end;
- }st[MAXSIZE],temp;
- int front = -1, rear = -1, ivar1 = 0, ivar2 = 0, tempval = 0;
- ++rear;
- st[rear].begin = begin;
- st[rear].end = end;
- while(front < rear)
- {
- ++front;
- temp = st[front];
- ivar1 = temp.begin;
- ivar2 = temp.end - 1;
- if(ivar1 == ivar2) continue; //当相遇的时候,也就是元素只有一个时,不执行操作
- tempval = iarr[ivar1]; //此句不能放在while循环内,因为ivar1的值在循环内是变化的
- while(ivar1 < ivar2)
- {
- // cout <<"ivar1 "<<ivar1<<" ivar2: "<<ivar2<<endl;
- while(ivar2 > ivar1 && iarr[ivar2] > tempval)
- --ivar2;
- if(ivar2 > ivar1)
- {
- iarr[ivar1] = iarr[ivar2];
- ++ivar1;
- }
- // cout <<" iva r1 "<<ivar1<<" ivar2: "<<ivar2<<endl;
- while(ivar2 > ivar1 && iarr[ivar1] < tempval)
- ++ivar1;
- if(ivar2 > ivar1)
- {
- iarr[ivar2] = iarr[ivar1];
- --ivar2;
- }
- // cout <<" ivar1 "<<ivar1<<" ivar2: "<<ivar2<<endl;
- }
- cout<<"ivar1 : "<<ivar1<<" ivar2 : "<<ivar2<<endl; //此处ivar2怎么会出现为 -1?? 因为这一句 ivar2 = temp.end - 1; 递归的不存在这个问题因为递归比较的是begin和end的值, 不是loop1 和 loop2的值
- iarr[ivar1] = tempval; //此句不能放在判断语句内,因为这一句总是要执行的
- if(ivar1 == ivar2) //要注意此处的判断条件,当ivar1 == ivar2的时候才表明找到了一个元素的最终位置,最后一定有(ivar1 == ivar2),此判断要
- {
- ++rear;
- st[rear].begin = temp.begin;
- st[rear].end = ivar1;
- ++rear;
- st[rear].begin = ivar1 + 1;
- st[rear].end = temp.end;
- }
- }
- }
- /*
- void Partition(int iarr[], int begin, int end)
- {// cout<<"begin : "<<begin<<" end :"<<end<<endl;
- int temp = 0, ivar1 = begin, ivar2 = end , mid = (ivar1 + ivar2) / 2 , tempval = 0;
- if(ivar1 >= ivar2) return;
- temp = iarr[mid];
- while(ivar1 < ivar2)
- {
- while(ivar2 > ivar1 && iarr[ivar2] >= temp)
- --ivar2;
- while(ivar2 > ivar1 && iarr[ivar1] <= temp)
- ++ivar1;
- if(ivar1 < ivar2)
- {
- tempval = iarr[ivar1];
- iarr[ivar1] = iarr[ivar2];
- iarr[ivar2] = tempval;
- }
- }Disp(iarr,12);
- iarr[mid] = iarr[ivar1];
- iarr[ivar1] = temp;
- // system("pause");
- Partition(iarr,begin,ivar1 -1);
- Partition(iarr,ivar1 + 1, end);
- }
- void QuickSortX(int iarr[], int begin, int end)
- {
- int pos = 0;
- Partition(iarr,begin, end);
- if(begin < pos -1)
- QuickSortX(iarr,begin,pos);
- if(pos + 1 < end - 1)
- QuickSortX(iarr,pos + 1,end);
- }
- */
- void Merge(int iarr[], int begin, int mid, int end) //归并,把一个数组的前后两个部分(有序)合并为一个有序的数组
- {
- int iarr2[MAXSIZE], loop1 = 0, tempmid = 0, count = 0;
- for(loop1 = 0, tempmid = mid + 1; loop1 <= mid && tempmid <= end; )
- {
- if(iarr[loop1] > iarr[tempmid])
- {
- iarr2[count] = iarr[tempmid];
- ++tempmid;
- ++count;
- }else if(iarr[loop1] < iarr[tempmid])
- {
- iarr2[count] = iarr[loop1];
- ++loop1;
- ++count;
- }else
- {
- iarr2[count] = iarr[loop1];
- ++loop1;
- ++count;
- iarr2[count] = iarr[tempmid];
- ++tempmid;
- ++count;
- }
- }
- if(loop1 > mid)
- {
- while(tempmid <= end)
- {
- iarr2[count] = iarr[tempmid];
- ++count;
- ++tempmid;
- }
- }
- if(tempmid > end)
- {
- while(loop1 <= mid)
- {
- iarr2[count] = iarr[loop1];
- ++count;
- ++loop1;
- }
- }
- for(loop1 = 0; loop1 <= end; ++loop1)
- iarr[loop1] = iarr2[loop1];
- }
- void MergePass(int iarr[], int end, int length) //对一个数组进行一length长度的合并时候,应该判断数组的长度是否为区间的偶数倍或者奇数倍
- {
- int pos = 0;
- for(pos = 0; pos + 2 * length -1 <= end; pos = pos + 2 * length)
- Merge(iarr,pos,pos + length - 1, pos + 2 * length - 1);
- if(pos + length - 1 < end)
- Merge(iarr,pos, pos + length -1 , end);
- }
- void MergeSort(int iarr[], int len) //归并排序,其思想是把数组先按照长度为1进行两路排序,然后长度递增
- {
- int length = 1;
- for(length = 1; length < len ; length *= 2)
- MergePass(iarr,len,length);
- }
- typedef struct rnode
- {
- char data[MAXD];
- struct rnode *next;
- }RecType;
- void RadixSort(char carr[][4], int len, int weishu) ///基数排序
- {
- int loop1 = 0, num = 0,count = 0, loop2 = 0;
- RecType head[MAXSIZE], *tail[MAXSIZE] = {NULL}, *temp = NULL;
- for(count = weishu -1;count >= 0; --count)
- {
- for(loop1 = 0; loop1 < MAXSIZE; ++loop1)
- {
- tail[loop1] = NULL;
- head[loop1].next = NULL;
- }
- for(loop1 = 0; loop1 < len; ++loop1) //按照位数位置上的数字添加到链表数组中,分配
- {
- num = int(carr[loop1][count] - '0');
- temp = (RecType *)malloc(sizeof(RecType));
- strcpy(temp->data, carr[loop1]);
- temp->next = NULL;
- if(tail[num] == NULL)
- {
- tail[num] = temp;
- head[num].next = tail[num];
- }else
- {
- temp->next = tail[num]->next;
- tail[num]->next = temp;
- tail[num] = temp;
- }
- }
- loop2 = 0;
- for(loop1 = 0; loop1 < len; ++loop1) //从链表中收集
- {
- if(tail[loop1] == NULL)
- {cout<<"loop1 "<<loop1<<endl; }
- else
- {
- temp = head[loop1].next;
- while(temp != NULL)
- {
- strcpy(carr[loop2++],temp->data);
- temp = temp->next;
- }
- }
- }
- for(loop1 = 0; loop1 <len; ++loop1)
- cout<<carr[loop1]<<' ';
- cout<<endl;
- }
- }
转载于:https://blog.51cto.com/saibro/1183655