单链表及在其上的操作实现
来源:互联网 发布: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;}
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
- 单链表及在其上的操作实现
- 数据结构上机:数组和三元组表示及建立在其上的相关运算
- sqlite在其uclinux上的移植
- Linux中在主机上实现对备机上目录及文件的操作的C代码实现
- 动态添加ImageView控件并在其上实现动画
- 单链表 C语言实现其操作
- 在access数据库中,据记录ID得到其上一条记录及下一条记录的SQL
- [分享]点阵字库分析及在J2ME上的实现
- RAS 在 x86 上的应用及 Linux 实现
- Spinlock在ARM及X86平台上的实现
- d指针在Qt上的应用及实现
- Spinlock在ARM及X86平台上的实现
- 安卓自定义dialog,改变其在主页面的位置和实现dialog上的按钮点击事件
- JNCryptor在Android上的性能其差无比,而在iOS上RNCryptor则其强无比 何解?
- 选择鼠标指针浮动在其上的元素,并设置其样式:hover
- 单链表、带头结点的单链表、循环单链表 以及其操作实现
- 数据结构中栈的实现以及其基本操作
- 由于“Table(User)”没有主键,因此无法在其上执行 Create、Update 或 Delete 操作。
- 链式表达
- Linux学习笔记(用户管理)
- [LeetCode 67]Add Binary
- lightoj1282
- 心得(1)
- 单链表及在其上的操作实现
- 已知二叉树的中序遍历和后序遍历,求先序遍历
- PHP获得文件列表
- c与c++区别
- Plus One
- 调用WCF服务
- LeetCode Excel Sheet Column Title
- java web笔记之Filter防盗链
- PHP获得文件列表