那么需要怎么解决?
,显然我们需要增加一个空头节点,这样头节点的交换就没有问题了。
现在给出一般的指针冒泡排序算法(C语言):
//冒泡排序
structbook*BubbleSort(structbook*head_book){
intfinish=0;
intsize_book=sizeof(structbook);
structbook*NullH_book=(structbook*)malloc(size_book);//增加一个空头节点
NullH_book->book_next=head_book;
structbook*tail=NULL;
//structbook*j1_ptr_book=head_book->book_next;
while(NullH_book->book_next!
=tail&&!
finish)
{
finish=1;//交换标志
structbook*pre_book=NullH_book;
structbook*cur_book=pre_book->book_next;
while(cur_book!
=tail&&cur_book->book_next!
=tail){
if(GetKey(cur_book)book_next))
{
pre_book->book_next=cur_book->book_next;
cur_book->book_next=cur_book->book_next->book_next;
pre_book->book_next->book_next=cur_book;
finish=0;//已交换
}
pre_book=pre_book->book_next;
cur_book=pre_book->book_next;
}tail=cur_book;
}
returnNullH_book->book_next;
}
貌似问题解决了,但是这里只给出了冒泡排序,我们知道冒泡排序算法的时间上界为O(n2),即使,我增加了交换标志,可以改进一些,但是我们仍然像可不可以有更好的方法提高排序效率。
你也知道当然存在更好的算法,比如之前的快速排序,此外还有:
直接插入排序,简单选择排序,堆排序,二路归并排序等等。
我们是不是能够也对单链表排序呢?
但是有一个问题,还是指针问题,冒泡是对相邻的节点交换,指针的交换就很麻烦了,还要多设置一个前一个节点的指针。
那么,快速排序呢,是不相邻的节点的赋值(交换),这样的复杂过程,需要设置几个指针,需要怎样移动,要考虑哪些情况。
堆排序情况是怎样的?
归并排序又要怎样写?
也许是有办法的,但想想也很麻烦,单链表操作实在很不好使用这些排序。
是不是真的无法排序呢?
办法还是有的。
能不能利用已经写过的这些函数进行排序?
教材有这些方法的关键代码,课设时也实现过了,但是是对输入的整数,装入一个数组进行排序的,链表节点型的数据怎么排序?
其实,回到最开始的错误想法来看,可以解决这个问题。
如果我存放的是指针数组,每个指针指向链表的一个节点。
可以通过指针找到节点,比较key,再对指针数组进行排序,这样就实现了对节点的排序。
当然只进行这一步,肯定还是错误的,我们还是没对链表进行改变。
所以,最后一步就是,在排好序的基础上,走一轮,将指针的指向的节点看成是独立的节点,修改它的属性中的指向下一节点的指针值为当前数组指针的后一个数组指针。
这样就重新得到了一个单链表。
唉,用进废退,是不变的法则啊,本以为数据结构学的还可以,现在好久不用了就将数据结构的特点给遗忘了。
现在用JAVA,C#,不写C++了指针都用不熟了,经常报错,用C里面的部分方法也出现错误。
花了这么久终于算是解决了。
附:
通用排序模板
#include
#include
usingnamespacestd;
constintMaxSize=100;
template
classelement
{
template
friendclasssortlist;
private:
Typekey;//数据元素关键字
public:
element():
key(0){}//构造函数
TypeGetKey(){returnkey;}//取关键字
voidsetKey(constTypek){key=k;}//修改关键字
element&operator=(element&x){key=x.key;return*this;}//赋值,重载运算符=
};
template
classsortlist{
//templatefriendvoidQuickSort(sortlist&table,intlow,inthigh);也可以
friendvoidInsertionSort(sortlist&table);//直接插入排序
friendvoidBubbleSort(sortlist&table);//冒泡排序
friendvoidSelectSort(sortlist&table);//简单选择排序
friendvoidQuickSort(sortlist&table,intlow,inthigh);//快速排序
template
friendclassMaxHeap;//堆
friendvoidHeapSort(sortlist&table);//堆排序
friendvoidmerge(sortlist&sourceTable,sortlist&mergedTable,
constintleft,constintmid,constintright);//归并
friendvoidMergePass(sortlist&sourceTable,sortlist&mergedTable,
constintlen);//一趟归并
friendvoidMergeSort(sortlist&table);//两路归并
public:
element*Arr;//存储数据元素的向量
intCurrentSize;//数据表中的元素个数
sortlist():
CurrentSize(0){Arr=newelement[MaxSize];}//构造函数
sortlist(constsortlist&sl)//拷贝构造函数
{
Arr=newelement[MaxSize];CurrentSize=sl.CurrentSize;
for(inti=0;iArr[i]=sl.Arr[i];
}
~sortlist(){delete[]Arr;}//析构函数
voidSwap(element&x,element&y)//交换x和y
{elementtemp=x;x=y;y=temp;}
voidInsert(constTypek){Arr[CurrentSize].setKey(k);CurrentSize++;}//插入k
voidShow()//显示数据元素
{
for(inti=0;icout<}
};
//直接插入排序---使用监视哨改进需要将第一个空出来,此处不便于其他排序算法的使用,所以不使用
template
voidInsertionSort(sortlist&table)
{
elementtemp;
cout<<"直接插入排序结果:
\n";
cout<<"初始序列:
";table.Show();cout<intj;
for(inti=1;i
{
temp=table.Arr[i];j=i;
while(j>=0&&temp.GetKey()
{
table.Arr[j]=table.Arr[j-1];
j--;
}
table.Arr[j]=temp;
cout<<"第"<
";
table.Show();cout<}
}
//冒泡排序
template
voidBubbleSort(sortlist&table)
{
inti=1;intfinish=0;
cout<<"冒泡排序结果:
\n";
cout<<"初始序列:
";table.Show();cout<while(i
finish)
{
finish=1;//交换标志
for(intj=0;j
if(table.Arr[j].GetKey()>table.Arr[j+1].GetKey())
{
table.Swap(table.Arr[j],table.Arr[j+1]);
finish=0;//已交换
}
cout<<"第"<
";
table.Show();cout<i++;
}
}
//简单选择排序
template
voidSelectSort(sortlist&table)
{
intk;
cout<<"简单选择排序结果:
\n";
cout<<"初始序列:
";table.Show();cout<for(inti=0;i
{
k=i;
for(intj=i+1;j
if(table.Arr[j].GetKey()
k=j;//当前最小关键字的位置
if(k!
=i)
table.Swap(table.Arr[i],table.Arr[k]);
cout<<"第"<
";
table.Show();cout<}
}
//快速排序
template
classQSort
{
public:
voidQuickSort(sortlist&table,intlow,inthigh);
};
template
voidQSort:
:
QuickSort(sortlist&table,intlow,inthigh)
{
staticintcount=1;
if(count==1)
{
cout<<"快速排序结果:
\n";
cout<<"初始序列:
";table.Show();cout<}
inti=low,j=high;
elementtemp=table.Arr[low];//取区间第一个位置为基准位置
if(i{
while(iwhile(iif(iwhile(i=table.Arr[i].GetKey())i++;
if(i}
table.Arr[i]=temp;//基准元素归为
cout<<"第"<";table.Show();cout<QuickSort(table,low,i-1);//左区间递归快速排序
QuickSort(table,i+1,high);//右区间递归快速排序
}
}
//堆排序
template
classMaxHeap{
public:
MaxHeap(intmaxSize);//构造函数,建立空堆
MaxHeap(Type*a,intn);//构造函数,以数组a[]的值建立堆
~MaxHeap(){delete[]heapArr;
}//析构函数
intInsert(Type&d);//在堆中插入元素d
TypeDeleteTop();//删除堆顶元素
TypeGetTop()const//取得堆顶元素
{returnheapArr[0];}
intIsEmpty()//判断堆是否为空
{returnheapCurrentSize==0;}
intIsFull()const//判断堆是否为满
{returnheapCurrentSize==heapMaxSize;}
voidSetEmpty(){heapCurrentSize=0;}//置堆为空
voidHeapSort();//堆排序
voidShow(intk)
{
for(inti=0;icout<}
private:
intheapMaxSize;//堆中数据元素的最大数目
Type*heapArr;//存放堆中数据元素的数组
intheapCurrentSize;//堆中当前元素数目
voidFilterDown(intp);//向下调整使以结点p为根的子树成为堆
voidFilterUp(intp);//向上调整使以结点p为根的子树成为堆
};
template
intMaxHeap:
:
Insert(Type&d)
{
if(IsFull())
{cout<<"堆已满"<heapArr[heapCurrentSize]=&d;//在堆尾插入数据元素d
FilterUp(heapCurrentSize);//向上调整为堆
heapCurrentSize++;
return1;
}
template
MaxHeap:
:
MaxHeap(intmaxSize){
//根据maxSize,建立空堆
if(maxSize<=0)
{
cerr<<"堆的大小不能小于1"<exit
(1);
}
heapMaxSize=maxSize;
heapArr=newType[heapMaxSize];//建立堆空间
heapCurrentSize=0;
}
template
MaxHeap:
:
MaxHeap(Type*a,intn){//根据数组a[]中的数据,建立堆,n为数组的大小
if(n<=0)
{cerr<<"堆的大小不能小于1"<exit
(1);
}
heapMaxSize=n;//确定堆的最大空间
heapArr=newType[heapMaxSize];//创建堆空间
//heapArr=a;//?
直接赋值?
for(inti=0;iheapArr[i]=a[i];
heapCurrentSize=n;//当前堆大小
/*inti=(heapCurrentSize-2)/2;//找最后一个分支结点的序号
while(i>=0)
{
FilterDown(i);//从开始到heapCurrentSize-1为止进行调整
i--;
}*/
}
template
voidMaxHeap:
:
FilterDown(constintstart)
{
//向下调整从start开始到heapCurrentSize-1为止的子序列成为最大堆
inti=start,j;
Typetemp=heapArr[i];
if(heapCurrentSize<=2)
{
if(i==0&&heapCurrentSize==2&&heapArr[0].GetKey(){heapArr[0]=heapArr[1];heapArr[1]=temp;}
}
else{
j=2*i+1;//j为i的左孩子
while(jif(jj++;//从左右孩子中选较大者
if(temp.GetKey()>=heapArr[j].G