单链表及在其上的操作实现

来源:互联网 发布:it治理与it管理的区别 编辑:程序博客网 时间:2024/06/05 09:40

单链表作为一种常见的数据结构,在程序设计中很重要。我也是在最近参加的一些面试,感觉好多公司在技术面试时都会问一些单链表的问题,在此进行一下总结。

本文的完整代码在:https://github.com/JayYangSS/Data-Structure-and-Algorithm/tree/master/Linklist


首先建立单链表的基本数据单元:

typedef struct Node{int data;Node *next;}Node;

声明单链表的类,将单链表的相关操作均封装到该类中,后续的单链表操作方法还会继续更新,下面得1声明在LinkList.h文件中:

class LinkList{public:LinkList(void);~LinkList(void);Node* SetupLinkList(void);// //diaplay the data of link listvoid diaplay(Node* head);// 输入数值,建立有序的链表Node* SetupOrderedLinkList(bool down);// 将元素插入到pp所指节点后void Insert(Node* pp,Node *newNode);// 将两个单链表按顺序合并为一个单链表Node* Merge(Node* first, Node* second);// 将链表复制到另一条链表上void copyto(Node* src, Node* dst);// 合并两条有序链表的方法二Node* Merge2(Node* first, Node* second);// 寻找单链表的中间节点Node* FindMid(Node* head);// 使用归并排序法实现链表排序Node* SortLinkList(Node* head);};

相应的实现如下:

// 将链表复制到另一条链表上void LinkList::copyto(Node* src, Node* dst){Node *p,*q,*tmp;q=new Node;dst->next=q;p=src->next;do{q->data=p->data;p=p->next;if(p!=NULL){tmp=new Node;q->next=tmp;q=q->next;q->next=NULL;}}while(p!=NULL);}
<pre name="code" class="cpp">Node* LinkList::SetupLinkList(void){Node *head,*p,*q;cout<<"input the data(input '-1' to end):"<<endl;head=new Node;head->next=NULL;q=head->next;while (1){int a;cout<<"input data:";cin>>a;if (a==-1)break;else{p=new Node;if (head->next==NULL){head->next=p;p->data=a;p->next=NULL;q=p;}else{p->data=a;q->next=p;q=p;q->next=NULL;}}}return head;}

<pre name="code" class="cpp">// //diaplay the data of link listvoid LinkList::diaplay(Node* head){Node *p;if (head == NULL)cout << "The head of the LinkList is NULL!" << endl;else if (head->next==NULL){cout<<"Linklist is empty!"<<endl;}    else{p=head->next;while(p!=NULL){cout<<p->data<<endl;p=p->next;}}}
// 将元素插入到pp所指节点后void LinkList::Insert(Node* pp,Node *newNode){if (pp->next==NULL){pp->next=newNode;newNode->next=NULL;}else{Node *tmp=pp->next;pp->next=newNode;newNode->next=tmp;}}

建立有序单链表的程序如下:

Node* LinkList::SetupOrderedLinkList(bool down)//down=true时为降序排列,down=false时为升序排列{Node *head,*p,*q;cout<<"input the data(input '-1' to end):"<<endl;head=new Node;head->next=NULL;q=head->next;while (1){int a;cout<<"input data:";cin>>a;if (a==-1)break;else{p=new Node;p->data=a;//创建第一个元素if (head->next==NULL){head->next=p;p->next=NULL;q=p;}else{Node *search,*pre;search=head->next;pre=head;while(pre->next!=NULL){if (down==false)//升序排列{//比较待插入链表的数据与当前链表中的元素大小//若待插入元素大于当前节点,比较下一节点//若待插入元素小于当前节点,插入到该节点之前if (a>=search->data){if (search->next==NULL)Insert(search,p);pre=pre->next;search=search->next;}else{Insert(pre,p);break;}}else//降序排列{if (a<=search->data){if (search->next==NULL)Insert(search,p);pre=pre->next;search=search->next;}else{Insert(pre,p);break;}}}}}}return head;}





将两条有序单链表合并为一条有序的单链表,第一种实现方法的思路是首先将其中的一条单链表复制到一条新的链表head上,再从另一条单链表开始遍历,每取出第二条链表上的一个元素,就将其与head链表上的每一个元素进行比较,按顺序插入即可(该思路写的程序有点乱,复杂度大),代码如下:

// 将两个单链表按顺序合并为一个单链表Node* LinkList::Merge(Node* first, Node* second){if(first->next==NULL)return second;else if (second->next==NULL)return first;else{Node *d,*head;//存储合并好的新的链表Node *p1,*p2,*pre;head=new Node;copyto(first,head);//新的链表头//p1=head->next;//pre=head;p2=second->next;while(p2!=NULL)//while(((p2->next!=NULL)&&p2!=NULL)|((p2!=NULL)&&(p2->next==NULL))){p1=head->next;pre=head;while(pre!=NULL){if ((p2->data>=p1->data)&&(p1->next!=NULL)){p1=p1->next;pre=pre->next;if ((p1->next==NULL)&&(p2->data>=p1->data)){Insert(p1,p2);p1=p1->next;pre=pre->next;p2=p2->next;break;}}else{d=new Node;d->data=p2->data;Insert(pre,d);if (p2->next==NULL){p2=p2->next;break;}p2=p2->next;pre=pre->next;break;}}}return head;}}

第二种合并的方法比第一种简单,思路是:每次取出两条链表的第一个节点中的元素,将其中较小的元素放入一条新的链表中,同时将该条链表的指针后移(相当于将该元素从这条链表中清除出去),再将两条链表中的指针所指元素进行大小比较,重复上述操作。若其中的一条链表中的元素已经全部放入新链表中,而另一条链表还没有放置完毕,则将剩余部分直接放入新链表尾部,得到的新链表即为合并好的有序链表,程序如下:

Node* LinkList::Merge2(Node* first, Node* second){Node *head,*tail;head=new Node;tail=head;first=first->next;second=second->next;if(first==NULL)return second;if(second==NULL)return first;while(first&&second){if (first->data>second->data){Node* tmp=new Node;tmp->data=second->data;tail->next=tmp;tail=tail->next;tail->next=NULL;//delete tmp;second=second->next;}else{Node* tmp=new Node;tmp->data=first->data;tail->next=tmp;tail=tail->next;tail->next=NULL;//delete tmp;first=first->next;}}if(first==NULL){while(second){Node *tmp=new Node;tmp->data=second->data;tail->next=tmp;tail=tail->next;tail->next=NULL;second=second->next;}}else{while(first){Node *tmp=new Node;tmp->data=first->data;tail->next=tmp;tail=tail->next;tail->next=NULL;first=first->next;}}return head;}

为了实现将无序单链表进行排序,使用归并排序法,其主要思想如下:

1.首先找到单链表的中点,将其分为两个链表

2.对前后半部分链表进行同样的操作,再分别分为两半部分链表,如此一直重复下去,直到每个链表只含有一个元素,此时每个链表均为有序单链表

3.对每一个有序单链表使用之前实现的合并有序单链表方法进行合并,直到最后所有链表合并为一条,该链表即为重新排序好的单链表

实现方法使用到递归:

// 使用归并排序法实现链表排序Node* LinkList::SortLinkList(Node* head){if (!head)return NULL;if (!head->next)return head;Node *mid,*next=NULL,*head2;mid=FindMid(head);if (mid->next != NULL){next = mid->next;//为后半部分添加链表头head2 = new Node;head2->next = next;mid->next = NULL;return Merge2(SortLinkList(head), SortLinkList(head2)); //使用递归调用}elsereturn head;}


其中寻找单链表中点的思路:使用游标指针,slow移动一步,fast移动两步,当fast移动到末尾,则slow正好移动到中点

Node* LinkList::FindMid(Node* head){if(!head)return NULL;if(!head->next)return head;Node *slow,*fast;    slow=head;fast=head;while(fast&&fast->next){slow=slow->next;fast=fast->next->next;//游标slow移动一步,fast移动两步,当fast移动到末尾,则slow正好移动到中点}return slow;}


0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 我的世界皮肤有黑影怎么办 我的世界字体变大了怎么办 生锈的铁钉扎了怎么办 每天晚上窗纱上老有蝙蝠倒挂怎么办 我的世界没有痒怎么办 七日杀被ban了怎么办 吕框箱子上保护摸撕不掉怎么办 我的世界开光影卡怎么办 我的世界买不了怎么办 我的世界延迟高怎么办 我的世界过于昂贵怎么办 白色麻布染上别的颜色怎么办 印度老山檀香开裂了怎么办 专升本没过线怎么办 西安公租房小孩上学怎么办 全民k歌直播没人怎么办 在全民直播没人看怎么办 皮肤又黄又粗怎么办 被强制消费后应怎么办? 当保安不发工资怎么办? 辅警改革流管员怎么办 退伍证上照片毁了怎么办 辅警年龄大了怎么办 交警2小时不出警怎么办 中暑发烧39度了怎么办 中暑头疼怎么办最快最有效 十五个月的宝宝拉肚子怎么办 中暑了头疼想吐怎么办 2周岁中暑了呕吐怎么办 容易中暑的人该怎么办 喷泡3m反光脏了怎么办 新摩托车被交警查到怎么办 写字楼保安夜班巡逻害怕怎么办 全民k歌歌曲删了怎么办 莲藕洞里的黑膜怎么办 鞋子后面的拉链磨脚怎么办 磨砂鞋尖踢掉皮怎么办 塔吊吊装过程中遇到障碍物怎么办 高速路上突然遇到障碍物怎么办 被不明物蛰了怎么办 喝酒后开车撞路政护栏怎么办