严蔚敏数据结构为主的笔记四

   /2005-05-08

闁瑰瓨鍔掔拹鐔烘嫚閸欍儱鏁╅悶娑辩厜缁辨繈宕氶崱鏇㈢叐閻犲洤澧介埢鑲╂導閸曨剚鐏愰梺鍓у亾鐢浜告潏顐㈠幋闁兼儳鍢茶ぐ锟�40%闁圭粯鍔栭崹姘辨導濮樿埖灏柨娑虫嫹
闁规亽鍔岀粻宥囨導濮樿埖灏柡澶婂暟濞夘參濡撮崒婵愬殾濞寸媴缍€閵嗗啴宕i鐐╁亾濮樺磭绠栧ù婊勫笩娴犲牏绱旈幋鐘垫惣闂侇偅鏌ㄧ欢鐐寸▔閻戞ɑ鎷辩紒鏃€鐟︾敮褰掔嵁閸噮鍚呭ù鑲╁Л閳ь剚閽扞P濞村吋鑹鹃幉鎶藉灳濠垫挾绀夐柣鈧妽閸╂盯鏌呭宕囩畺閻犲洤褰為崬顒傛偘閵娧勭暠闁告帒妫旈棅鈺呮煣閻愵剙澶嶉柟瀛樼墬閹癸綁骞庨妷銊ユ灎濞戞梹婢橀幃妤呮晬瀹€鍐惧殾濞寸媴缍€閵嗗啴鎳㈠畡鏉跨悼40%闁圭粯鍔栭崹姘跺Υ閸屾繍鍤﹀ù鐙呯秬閵嗗啰鎷归婵囧闁哄牜鍓涢悵顖涚鐠佸磭绉垮ù婧犲啯鎯傞柨娑樿嫰濞煎孩绂嶉銏犵秬9闁硅埖菧閳ь剙鍊搁惃銏ゅ礆閸℃洟鐓╅梺鍓у亾鐢挳濡存担瑙勫闯闁硅翰鍎卞ù姗€鎮ч崶鈺冩惣闁挎稑鑻ぐ鍌炲礆閺夋鍔呴柡宓氥値鍟堥柛褎绋忛埀顑胯兌濞呫劍鎯旈敃浣稿灡闁告皜浣插亾娴i晲绨抽柛妤佸搸閳ь兛绀佹禍鏇熺┍鎺抽埀顑垮倕Q缂佸本妞藉Λ鍧楀Υ娴h櫣鍙€濞戞柨绨洪埀顑挎祰閻挳鎮洪敐鍥╂惣闁告艾瀚妵鍥嵁閸愭彃閰遍柕鍡嫹
 

ListNode  *pa , *pb ,  *qa  , *qb ;
pa=A;
pb=B ;
qa=A->next;
qb=B->next;
while ( qa && qb)
{
if ( qb->data < qa->data )
{
// 当B中的元素小于A中当前元素时,插入到它的前面
pb=qb;
qb=qb->next ;// 指向B中下一元素
pa->next=pb;
pb->next=qa;
pa=pb;

}
             else if ( qb->data  >=  pa->data && qb->data <= qa->data)
{
//   当B中元素大于等于A中当前元素
//   且小于等于A中后一元素时,
//    将此元素插入到A的当前元素之后
pa=qa;
qa=qa->next;   // 保存A的后一元素位置
pb=qb;    
qb=qb->next;   // 保存B的后一元素位置
pa->next=pb;   //插入元素
pb->next=qa;
}

else
{
//  如果B中元素总是更大,指针移向下一个A元素
pa=qa;
qa=qa->next;
}
}

if ( qb )// 如果A表已到终端而B表还有结点未插入
{
// 将B表接到A表后面
pa->next=qb;
}

LinkList  C=ReverseList ( A );// 调用前面2.8题所设计的逆置函数

return     C;  //返回新的单链表C, 已是递减排列
}


该算法的时间复杂度分析如下:
算法中只有一个while 循环,在这个循环中,按照最坏的情况是B元素既有插到A的最前的,也有插到最后的,也就是说需要把A中元素和B中元素全部检查比较过,这时的所费时间就是m+n.  而新链表的长度也是m+n+1 (有头结点),这样逆置函数的执行所费时间为m+n+1.所以可得整个算法的时间复杂度为:
m+n+m+n+1=2(m+n)+1= O(m+n)

---------------------------------------------------------------------------------------------------------

为验证本题,晓津设计了一个程序,清单如下:

//ListStruct.h  将链表结构存为头文件
typedef char DataType; //假设结点的数据类型是字符型
typedef struct node { //结点类型定义
DataType data;
struct node *next;//结点的指针域
}ListNode;

typedef ListNode * LinkList;

// 以下是源文件 //  在VC++中运行通过。

#include
#include
#include "ListStruct.h"
#include

LinkList CreatList (void)
{ //用尾插法建立带头结点的单链表

char ch;
LinkList head = (LinkList)malloc(sizeof( ListNode)); //生成头结点
ListNode *s , *r;
r=head;//尾指针亦指向头结点
while ((ch=getchar())!='/n')
{
s=(ListNode *) malloc (sizeof(ListNode));
s->data=ch;
r->next=s;
r=s;
}
r->next=NULL;
return  head;
}


void OutList( LinkList L)
{
 ListNode *p;
 p=L;
 while (p->next)
 {
 cout <<  p->next->data << "  " ;
 p=p->next;
 }
 cout << endl;
}
LinkList  ReverseList( LinkList  head  )
{
// 将head 所指的单链表逆置
ListNode *p  ,*q ;//设置两个临时指针变量
if( head->next && head->next->next)//当链表不是空表或单结点时
{
p=head->next;
q=p->next;
p -> next=NULL;//将开始结点变成终端结点

while (q)
{//每次循环将后一个结点变成开始结点
p=q;
q=q->next ;
p->next = head-> next  ;
head->next = p;
}
return head;
}
return head;//直接返回head
}

 

LinkList    MergeSort (  LinkList  A  , LinkList B )
{
// 归并两个递增有序表为一个递减有序表

ListNode  *pa , *pb ,  *qa  , *qb ;
pa=A;
pb=B ;
qa=A->next;
qb=B->next;
while ( qa && qb)
{
if ( qb->data < qa->data )
{
// 当B中的元素小于A中当前元素时,插入到它的前面
pb=qb;
qb=qb->next ;// 指向B中下一元素
pa->next=pb;
pb->next=qa;
pa=pb;

}


             else if ( qb->data  >=  pa->data && qb->data <= qa->data)
{
//   当B中元素大于等于A中当前元素
//   且小于等于A中后一元素时,
//    将此元素插入到A的当前元素之后
pa=qa;
qa=qa->next;   // 保存A的后一元素位置
pb=qb;    
qb=qb->next;   // 保存B的后一元素位置
pa->next=pb;   //插入元素
pb->next=qa;
}

else
{
//  如果B中元素总是更大,指针移向下一个A元素
pa=qa;
qa=qa->next;
}
}

if ( qb )// 如果A表已到终端而B表还有结点未插入
{
// 将B表接到A表后面
pa->next=qb;
}

LinkList  C=ReverseList ( A );// 调用前面2.8题所设计的逆置函数

return     C;  //返回新的单链表C, 已是递减排列
}


void main()
{
LinkList A, B, C;
A=CreatList();
OutList (A);
B=CreatList();
OutList (B);
C=MergeSort (A ,B);
OutList (C);
}


---------------------------------------------------


--------------------------------------------------------------------------------

(答案及点评) 2.14 已知单链表L是一个递增有序表,试写一高效算法,删除表中值大于min 且小于max的结点(若表中有这样的结点),同时释放被删结点的窨,这里min 和 max是两个给定的参数。请分析你的算法的时间复杂度。

2.14 解:
要解这样的问题,我们首先想到的是拿链表中的元素一个个地与max和min比较,然后删除这个结点,其实因为已知其是有序链表,所以我们只要找到大于min的结点的直接前趋结点,再找到小于max的结点,然后一并把中间的全部摘掉就可以了。

算法如下:
void DeleteList ( LinkList L, DataType min , DataType max )
{
ListNode *p , *q , *h;
p=L->next;
while( p  && p->data <=min )
{//找比min大的前一个元素位置
q=p;
p=p->next;

}
p=q;//保存这个元素位置

闁绘劗鎳撻崵顔剧博鐎n亜绁柟鍏肩矌閸岋拷2濞戞挸娲ㄩ~鎺楁嚀閸愵亞鍩¢柣銏ゆ涧閻℃瑩鎮ч崼锝囥偒闁哄倹鐟辩槐锟�
濠㈠爢鍥у姤闁告帒妫涢銏ゆ鐎n喖鍘撮柡鍕靛灣椤戝洦绋夐埀顒€鈻庨檱閳ь剙鍟伴悥娲晬鐏炵瓔鍤犲ù婊冮椤┭勬媴閺囩喓鍙€闁归潧褰炵粭鎾寸▔濮樻剚鍤﹂柟绋挎搐閻i箖寮▎鎰稄闁挎稑鏈崹銊ф媼閸涘﹥绠掔€垫澘鐗嗛ˇ鍧楁偪閹达附锛栭柕鍡曞ree濠㈠綊鈧稒銆冮柛鎺戞椤掔喐绋婇悩鐢电Ч闁兼澘鍟伴悥鍝勄庢潏顐熷亾閺囨氨鐟╁☉鎾翠亢椤曡櫕娼忛崨顓у殼20妤犵偠鎻槐婵嬪箑閼姐倗娉㈠ù婊冩缁夊鈧湱鍋熼弫銈夋儍閸曨剙鐦归悗瑙勭閺嗏偓闁哄鍔栭悡锛勬嫚閵忊剝鐓欐繛澶嬫礀瀵攱寰勫鍕槑闁哄倽顫夌涵鍫曟晬鐏炵偓绠掗梻鍥e亾閻熸洑鑳跺▓鎴︽儑鐎n厾绠栭柡澶涙嫹

相关话题/

  • 领限时大额优惠券,享本站正版考研考试资料!
    大额优惠券
    优惠券领取后72小时内有效,10万种最新考研考试考证类电子打印资料任你选。涵盖全国500余所院校考研专业课、200多种职业资格考试、1100多种经典教材,产品类型包含电子书、题库、全套资料以及视频,无论您是考研复习、考证刷题,还是考前冲刺等,不同类型的产品可满足您学习上的不同需求。 ...
    本站小编 Free壹佰分学习网 2022-09-19