当前位置:文档之家› 链表的选择排序

链表的选择排序

排序采用选择法:把30 接到80后面45接到90后面90替原来45的位置***************************预备知识:NODE *v,*u,*p,*h;U,v,h,p都是指针,它们只是地址性的可以指向结构而链表中的表有next指针**************************************** 链表排序h45 65 54 80 90 30要实现45和90 的交换:30要接到80后面45要接到90后面90要接到h后面90 45 65 54 80 30要实现45和80 的交换:30 接到54后面45接到80后面80要接到90后面。

即插入到90后面所以一般情况需要用:两个指针vold v 指出45两个指针mold max 指出最大这样可以方便的实现v 或max,移走或被替换时,其它的可以接上。

但如果要被替换的是第一个,如45被90替换。

h,vold,v max45 65 54 80 90 30Max指向90,30 放到80后面,h,vold,v max45 65 54 80 30 9045 放到90后面,h,v,vold都跟着45移动,max h,vold,v90 45 65 54 80 30h=max还要一个游动指针,u,用于不断和v比较为了继续进行,下一轮开始前应该为:h ,vold v,max u90 45 65 54 80 30vold要指向90, v指向45, u指向54所以对于第一次交换后还要移动voldif(vold==v) 时,vold=h;总之一个比较可行的程序为:while (v->next != NULL) //省去空的v,//选择法{ for(max=v,uold= u = v->next; u->next != NULL;uold=u, u = u->next) { if (u->score > max->score ) { mold=uold; max = u; } //找到最大的} //u已移动,但队列未动// u->next == NULL即u是最后一个表,跳出循环,// 还要判别u指向的表是最大吗?if(u->score>max->score) {mold =uold; max=u;} //最后一个if (max!= v) {mv->next= max->next;max->next =v;if(vold==v) { h=max; }else { vold->next=max; }}。

可见用以上方法指针比较多,而且指针移动比较麻烦。

因为一开始,不能够用vold=vold->next;方式。

并且上述程序还未完全调通***************************************为此,一种常用的方法,引入一个空表接到h的后面先比较45 和65 :if( v->next->score < u->next->score ) ,……….比出最大后,90要插入到u的位置时,要做下面的步骤:1. 30 接到80后面 . max独立出来2. max->next =u;3. v->next=max;v=v-.>next, u=v->next将来输出时return h->next;, 就可以把空表让过具体分析:引进一个vNODE *v=(NODE*)malloc(sixeof(NODE));V uh p p1 p2 p3 p4 p5 p6v->next =h; h=v; 把v 插入h 和p1(45)之间先比较p1==u(45)和p2 (65)为了适合循环: v->next->score , u->next->score 表示要比较的数据:u->score==45,p2.score == 65P=v; u=v->next ; (v->next==u )u->score==45 , v->next->score ==45p2==u->next==65p2.score= u->next->score==65for(p=v,u=v->next; u->next!=NILL; u=u->next) if( p->next->score < u->next->score) p=u;找出最大的表u->next->score==(90), 然后交换(90) (45)) 把30 接到80后面: 90 的指针要保存45接到90后面90替代45位置一、90要独立出来,同时30 接到80后面,需要两个指针:1. p=u?, u=p->next : p指向80 u指向9090要独立出来,所以要用指针u指向它,以免丢掉,u要移走,所以先用p指向802. p->next =u->next : 30 接到80后面二、: 45接到90后面,u->next=v->next;三、90替代45位置v->next =u :V=v->next, u=v-.next 准备下一轮NODE *bubblesort(NODE *h){NODE *v,*u,*p;v = (NODE *)malloc(sizeof(NODE));v->next =h; h=v;while (v->next != NULL) //选择法{ for(p = v, u = v->next; u->next != NULL; u = u->next) if (u->next->score > p->next->score ) p = u; //找到最大的//u已移动,但队列未动if (p != v) { u = p->next; p->next = u->next; //oku->next =v->next; v->next =u; } v=v->next;} return h->next; //h;}*******************************14.Sort()排序由于学生信息采用的是单链表存储结构,所以选用直接插入算法较为简单。

直接插入算法的基本方法是:每步将一个待排序的记录按其排序码值的大小插到前面已经排好序的表中,直到全部插入为止。

基于这样的方法首先将链表的头结点看作是已排好序的结点,然后取下一个结点作为待排序的结点,插入到已排好序的表中。

由于单链表的特性,所以具体的思路如下:(1)先将原表头结点作为新排好序表的头结点h,原表下一个结点作为原表头结点h1。

设原表如图1l—所示,表中只列出总分数据。

图.11设新表头结点即h是新链表,h1是旧链表(2)原表头结点为待排序结点,将其总分与新表结点的总分进行比较,如果待排序结点总分大,则插在新表的头,否则插入在其后,原表头结点后移一位,如图.12所示。

(3)重复第二步,即将原表头结点的总分和新表结点的总分进行比较,如果待排序结点总分小,则移动新表指针,直到找到合适的位置将其插入,直到原表为空,所有结点排序完毕,如图.13所示。

这个排序算法实际上是先从原表删除头结点,然后在新表中查找到合适的位置,进行插入。

待排序结点的插入位置总是插在表头、表尾和表中间三种情况之一,由于单链表的特性,实际插入结点时,并不需要移动和交换结点信息,而是只改变指针关系,所以排序时间主要用在比较上。

排好序后将其名次数据写入数据域order中。

STUDENT *sort(STUDENT *h){ int i=0; /*保存名次*/STUDENT *p,*q,*t,*hl; /*定义临时指针*/hl=h->next; /*将原表头指针所指的下一个结点作为头指针*/h1->next=NULL; /*第一个结点为新表的头结点*/ ???while(hl!=NULL) /*当原表不为空时,进行排序*/{ t=hl; /*取原表的头结点*/hl=hl->next; /*原表头结点指针后移*/p=h; /*设定移动指针P,从头指针开始,即,h1中的每一个,从h的头比较起*/q=h; /*设定移动指针q作为P的前一个==pold,初值为头指针*/原表取第一个和新表从头进行比较while(t->sum < p->sum && p!=NULL) /*进行总分比较*/ { q=p; /*待排序点值小,则新表指针后移*/p=p->next; } /*直到t->sum >p->sum时,t插到p的前面if(p==q) /*说明待排序点值最大,应排在首位*/{ t->next=p; /*待排序点的后继为p*/h=t; } /*新头结点为待排序点*/else /*待排序点应插入在中间某个位置q和P之间,如果P为空则是尾部*/{ t->next=p; /*t的后继是P*/q->next=t; } /*q的后继是t*/}p=h; /*排序完成p指针回到链表头,准备填写名次*/ //因为是降序i=1即第一名,i=2, 第二名while(p!=NULL) /* P不为空时,进行下列操作*/{ i++; /*结点序号*/p->order=i; /*将名次赋值*/p=p->next; /*指针后移*/}printf("sort sucess!!!\n"); /*排序成功*/return h; /*返回头指针*/}。

相关主题