c++实现单向单链表及常见面试题

1.单链表

链表中的数据是以结点来表示的,每个结点的构成:元素+ 指针,元素就是存储数据的存储单元,指针就是连接每个结点的地址数据。

2、链表的结点结构

│data │next |

data域--存放结点值的数据域

next域--存放结点的直接后继的地址(位置)的指针域

注:链表通过每个结点的链域将线性表的n个结点按其逻辑顺序链接在一起的。

"LSist.h"

#pragma once

#include <iostream>

using namespace std;

typedef int DataType;

struct Node

{

Node(const DataType& d) //初始化Node

:_data(d)

,_next(0)

{ }

DataType _data;//数据域

struct Node* _next;//指针域

};

class SList

{

//因在类外重载"<<",所以应声明为友元

friend ostream& operator<<(ostream& os,const SList& s);

public:

SList()  //构造函数

:_head(0)

,_tail(0)

{}

~SList()  //析构函数

{

Node* cur = _head;

if(_head == NULL)

return;

while(cur->_next != NULL)

{

Node* del = cur;

cur = cur->_next;

delete del;

}

delete cur;

cur = NULL;

_head = NULL;

_tail = NULL;

}

SList(SList& s)  //拷贝构造函数

:_head(0)

,_tail(0)

{

Node* cur = s._head;

while(cur)

{

PushBack(cur->_data);

cur = cur->_next;

}

}

//SList& operator=(SList s)

//{

// swap(_head,s._head);

// swap(_tail,s._tail);

// return *this;

//}

SList& operator=(SList& s) //赋值函数

{

if( this != &s )

{

SList tmp(s);

swap(_head,tmp._head);

swap(_tail,tmp._tail);

}

return *this;

}

public:

void PushBack(const DataType& d);//后插

void PopBack();//后删

void PushFront(const DataType& d);//前插

void PopFront();//前删

Node* Find(const DataType& d);//查找某一个元素

void Insert(Node* pos,const DataType& d);//在某个位置后 插入元素

void Reverse(SList& s);//逆置

void Sort(SList& s);//排序

void Remove(const DataType& d);//删除某一元素

void RemoveAll(const DataType& d);//删除所有d元素

//面试题

void EraseNotTail(Node* pos);//删除非头结点

void InsertFrontNode(Node* pos, const DataType& d);

Node* FindMidNode(SList& s);

void DelKNode(DataType k);//删除第k个结点

void CheckCross(SList& l1,SList& l2);//两链表是否相交

Node* CheckCycle(SList& l1);//判断链表中是否有圈

int GetCircleLength(Node* meet);//圈的长度

Node* GetCycleEntryNode(Node* meetNode);//圈的入口

SList Merge(SList& l1, SList& l2);//将链表合并

private:

Node* _head; //头指针

Node* _tail; //尾指针

};

//函数的实现

//函数在类外实现,所以应加上域名

"LSist.cpp"

#include "SList.h"

ostream& operator<<(ostream& os,const SList& s)

{

Node* cur = s._head;

while(cur)

{

os<<cur->_data<<"->";

cur = cur->_next;

}

os<<"over"<<endl;

return os;

}

void SList::PushBack(const DataType& d)

{

Node* newNode = new Node(d);

if(_head == NULL)

{

_head = newNode;

_tail = _head;

}

else

{

_tail->_next = newNode;

_tail = newNode;

}

}

void SList::PopBack()

{

Node* cur = _head;

if(_head == NULL)

{

return;

}

else if(_head == _tail)

{

delete _head;

_head = NULL;

_tail = NULL;

return;

}

else

{

while(cur->_next != _tail)

{

cur = cur->_next;

}

delete _tail;

_tail = cur;

_tail->_next = NULL;

}

}

void SList::PushFront(const DataType& d)

{

Node* newNode = new Node(d);

if(_head == NULL)

{

_head = newNode;

_tail = _head;

}

else

{

newNode->_next = _head;

_head = newNode;

}

}

void SList::PopFront()

{

if(_head == NULL)

{

return;

}

else if(_head == _tail)

{

delete _head;

_head = NULL;

_tail = NULL;

}

else

{

Node* del = _head;

_head = _head->_next;

delete del;

}

}

Node* SList::Find(const DataType& d)

{

Node* cur = _head;

while(cur)

{

if(cur->_data == d)

{

return cur;

}

cur = cur->_next;

}

return NULL;

}

void SList::Insert(Node* pos,const DataType& d)

{

Node* newNode = new Node(d);

if(pos == _tail)

{

_tail->_next = newNode;

_tail = newNode;

}

else

{

newNode->_next = pos->_next;

pos->_next = newNode;

}

}

void SList::Reverse(SList& s)

{

Node* newNode = NULL;

Node* cur = s._head;

Node* prev = NULL;

if(s._head == NULL)

return;

else if(s._head == s._tail)

return;

else

{

while(cur)

{

prev = cur;

cur = cur->_next;

prev->_next = newNode;

newNode = prev;

}

s._head = newNode;

}

}

void SList::Sort(SList& s)

{

if(s._head == NULL)

{

return;

}

else if(s._head == s._tail)

{

return;

}

else

{

Node* cur = NULL;

Node* prev = NULL;

DataType tmp = 0;

while(s._head != prev)

{

cur = s._head;

while(cur&&(cur->_next != prev))

{

if(cur->_data > cur->_next->_data)

{

tmp = cur->_data;

cur->_data = cur->_next->_data;

cur->_next->_data = tmp;

}

cur = cur->_next;

}

prev = cur;

}

}

}

void SList::Remove(const DataType& d)

{

Node* cur = _head;

Node* prev = _head;

Node* del = NULL;

if(_head == NULL)

return;

while(cur)

{

if(cur->_data == d)

{

del = cur;

if(cur == _head)

{

_head = _head->_next;

cur = _head;

delete del;

return;

}

else

{

prev->_next = cur->_next;

cur = prev->_next;

delete del;

return;

}

}

prev = cur;

cur = cur->_next;

}

}

void SList::RemoveAll(const DataType& d)

{

Node* cur = _head;

Node* prev = _head;

Node* del = NULL;

if(_head == NULL)

return;

while(cur)

{

if(cur->_data == d)

{

del = cur;

if(cur == _head)

{

_head = _head->_next;

cur = _head;

}

else

{

prev->_next = cur->_next;

cur = prev->_next;

}

delete del;

}

else

{

prev = cur;

cur = cur->_next;

}

}

}

void SList::EraseNotTail(Node* pos)

{

DataType tmp = 0;

Node* del = NULL;

tmp = pos->_data;

pos->_data = pos->_next->_data;

pos->_next->_data =tmp;

del = pos->_next;

pos->_next = del->_next;

delete del;

del = NULL;

}

Node* SList::FindMidNode(SList &s)

{

Node* fast = s._head;

Node* slow = s._head;

if(fast == NULL)

return NULL;

while(fast->_next)

{

if(fast->_next->_next != NULL)

{

fast = fast->_next->_next;

slow = slow->_next;

}

else

{

return slow;

}

}

return slow;

}

void SList::InsertFrontNode(Node* pos, const DataType& d)

{

Node* newNode = new Node(d);

Node* cur = _head;

Node* front = cur;

if(pos == _head)

{

newNode->_next = _head;

_head = newNode;

}

else

{

cur = cur->_next;

while(cur)

{

if(cur == pos)

{

newNode->_next = front->_next;

front->_next = newNode;

}

cur = cur->_next;

front = front->_next;

}

}

}

void SList::DelKNode(DataType k)

{

Node* fast = _head;

Node* slow = _head;

Node* del = NULL;

Node* cur = NULL;

if(_head == NULL)

return;

while(--k)

{

fast = fast->_next;

}

while(fast->_next)

{

fast = fast->_next;

cur = slow;

slow = slow->_next;

}

del = slow;

cur->_next = del->_next;

delete del;

del = NULL;

}

void SList::CheckCross(SList &l1, SList &l2)

{

SList l3;

Node* cur1 = l1._head;

Node* cur2 = l2._head;

l1._tail = l3._head;

l2._tail = l3._head;

while(cur1)

{

cur1 = cur1->_next;

}

while(cur2)

{

cur2 = cur2->_next;

}

if(cur1 == cur2)

{

cout<<"链表相交"<<endl;

}

else

{

cout<<"链表不相交"<<endl;

}

}

Node* SList::CheckCycle(SList& l1)

{

Node* fast = l1._head;

Node* slow = l1._head;

while(fast&&fast->_next)

{

fast = fast->_next->_next;

slow = slow->_next;

if(fast == slow)

{

return slow;//相遇的点

}

}

return NULL;

}

int SList::GetCircleLength(Node* meet)

{

Node* start = meet;

int count = 0;

do

{

start = start->_next;

count++;

}while(start != meet);

return count;

}

Node* SList::GetCycleEntryNode(Node* meetNode)

{

Node* entry = _head;

while(entry != meetNode)

{

entry = entry->_next;

meetNode = meetNode->_next;

}

return entry;

}

SList SList::Merge(SList& l1, SList& l2)

{

SList newNode;

Node* cur1;

Node* cur2;

if((l1._head == l2._head)&&(l1._tail == l2._tail))

return l1;

if((l1._head == NULL)&&(l2._head != NULL))

return l2;

if((l1._head != NULL)&&(l2._head == NULL))

return l1;

if(l1._head->_data < l2._head->_data)

{

newNode._head= l1._head;

l1._head = l1._head->_next;

}

else

{

newNode._head = l2._head;

l2._head = l2._head->_next;

}

cur1 = l1._head;

cur2 = l2._head;

Node* prev = newNode._head;

while(cur1&&cur2)

{

if(cur1->_data < cur2->_data)

{

prev->_next = cur1;

cur1 = cur1->_next;

prev = prev->_next;

}

else

{

prev->_next = cur2;

prev = prev->_next;

cur2 = cur2->_next;

}

}

if(cur1)

{

prev->_next = cur1;

}

if(cur2)

{

prev->_next = cur2;

}

return newNode;

}

//函数测试

"test.cpp"

#include "SList.h"

void Test1()

{

SList l1;

/*l1.PushBack(1);

l1.PushBack(2);

l1.PushBack(3);

l1.PushBack(4);

l1.PopBack();*/

l1.PushFront(1);

l1.PushFront(2);

l1.PushFront(3);

l1.PushFront(4);

l1.PopFront();

cout<<l1;

SList l2(l1);

cout<<l2;

SList l3;

l3 = l2;

cout<<l3;

}

void Test2()

{

SList l1;

l1.PushBack(1);

l1.PushBack(2);

l1.PushBack(3);

l1.PushBack(4);

l1.PushBack(5);

l1.PushBack(6);

cout<<l1;

/*if(ret != NULL)

{

cout<<ret->_data<<endl;

}

else

{

cout<<"链表中无此元素"<<endl;

}*/

//l1.Insert(ret,5);

//cout<<l1;

}

void Test3()

{

SList l1;

l1.PushFront(3);

l1.PushFront(2);

l1.PushFront(3);

l1.PushFront(4);

l1.PushFront(3);

l1.PushFront(5);

cout<<l1;

/*l1.Reverse(l1);

cout<<l1;*/

/*l1.Sort(l1);

cout<<l1;*/

l1.Remove(4);

//l1.RemoveAll(3);

cout<<l1;

}

void Test4()

{

SList l1;

l1.PushFront(1);

l1.PushFront(2);

l1.PushFront(3);

l1.PushFront(4);

l1.PushFront(5);

l1.PushFront(6);

l1.PushFront(7);

l1.PushFront(8);

cout<<l1;

/*Node *ret = l1.Find(4);

l1.InsertFrontNode(ret,10);*/

//l1.EraseNotTail(ret);

l1.DelKNode(3);

cout<<l1;

/*Node* ret = l1.FindMidNode(l1);

cout<<ret->_data<<endl;*/

}

void Test5()

{

SList l1;

SList l2;

SList l3;

l1.PushBack(1);

l1.PushBack(2);

l1.PushBack(3);

l1.PushBack(4);

l2.PushFront(5);

l2.PushFront(6);

l2.PushFront(7);

l3.PushBack(8);

l3.PushBack(9);

l3.CheckCross(l1,l2);

}

void Test6()

{

SList l1;

l1.PushBack(1);

l1.PushBack(3);

l1.PushBack(4);

l1.PushBack(6);

cout<<l1;

Node* end = l1.Find(6);

end->_next = l1.Find(3);

Node* meetNode = l1.CheckCycle(l1);

cout<<meetNode->_data<<endl;

//DataType ret = l1.GetCircleLength(meetNode);

//Node* ret = l1.GetCycleEntryNode(meetNode);

//cout<<ret->_data<<endl;

}

void Test7()

{

SList l1;

SList l2;

SList l3;

l1.PushBack(1);

l1.PushBack(3);

l1.PushBack(4);

l1.PushBack(6);

cout<<l1;

l2.PushBack(2);

l2.PushBack(5);

cout<<l2;

l3 = l3.Merge(l1,l2);

cout<<l3;

}

int main()

{

Test6();

return 0;

}

时间: 2024-10-29 19:08:35

c++实现单向单链表及常见面试题的相关文章

单链表常见面试题

单链表的常见面试题有如下: 1. 求单链表中有效节点的个数 代码如下: 1 //方法:获取到单链表的节点的个数(如果是带头节点的链表,需求不统计头节点) 2 /** 3 * @param head 链表的头节点 4 * @return 返回的就是有效节点的个数 5 */ 6 public static int getLength(HeroNode head){ 7 if(head.next == null) { //空链表 8 return 0; 9 } 10 //定义辅助变量,这里没有统计头节

一些html5和css3的一些常见面试题

最近总结了一些有关于html5和css3的一些常见面试题,希望对正在找工作的你有所帮助. 还有欢迎大家补充~~~ 一.HTML5 CSS3 CSS3有哪些新特性? 1. CSS3实现圆角(border-radius),阴影(box-shadow), 2. 对文字加特效(text-shadow.),线性渐变(gradient),旋转(transform) 3.transform:rotate(9deg) scale(0.85,0.90) translate(0px,-30px) skew(-9de

JDBC常见面试题集锦

什么是JDBC,在什么时候会用到它? JDBC的全称是Java DataBase Connection,也就是Java数据库连接,我们可以用它来操作关系型数据库.JDBC接口及相关类在java.sql包和javax.sql包里.我们可以用它来连接数据库,执行SQL查询,存储过程,并处理返回的结果. JDBC接口让Java程序和JDBC驱动实现了松耦合,使得切换不同的数据库变得更加简单. 有哪些不同类型的JDBC驱动? 有四类JDBC驱动.和数据库进行交互的Java程序分成两个部分,一部分是JDB

【转载】JAVA常见面试题及解答(精华)

JAVA常见面试题及解答(精华) 1)transient和volatile是java关键字吗?(瞬联) 如果用transient声明一个实例变量,当对象存储时,它的值不需要维持.例如: class T { transient int a;  //不需要维持 int b;  //需要维持 } 这里,如果T类的一个对象写入一个持久的存储区域,a的内容不被保存,但b的将被保存. volatile修饰符告诉编译器被volatile修饰的变量可以被程序的其他部分改变.在多线程程序中,有时两个或更多的线程共

数据库常见面试题总结

说明:本文仅供学习交流,转载请标明出处,欢迎转载! 数据库常见面试题总结 1.      SQL的表连接方式有哪些? SQL中连接按结果集分为:内连接,外连接,交叉连接 内连接:inner join on,两表都满足的组合.内连接分为等值连接,不等连接,自然连接. 等值连接:两表中相同的列都会出现在结果集中.  自然连接:两表中具体相同列表的列会合并为同一列出现在结果集中. 外连接:分为左(外)连接,右(外)连接,全连接 左(外)连接:A left (outer) join B,以A表为基础,A

java常见面试题——java笔试题总结

注:本文转载自http://www.cnblogs.com/huajiezh/p/5790928.html,版权归其所有! Java常见面试题总结 一.Java基础 1.String类为什么是final的. 2.HashMap的源码,实现原理,底层结构. 3.说说你知道的几个Java集合类:list.set.queue.map实现类咯... 4.描述一下ArrayList和LinkedList各自实现和区别 5.Java中的队列都有哪些,有什么区别. 6.反射中,Class.forName和cl

HTML常见面试题及疑难点解答

HTML&CSS常见面试题及疑难解答 HTML篇 对web标准以及W3C的理解与认识? WEB标准不是某一个标准,而是一系列标准的集合.网页主要由三部分组成:结构(Structure).表现(Presentation)和行为(Behavior). 对应的标准也分三方面:结构化标准语言主要包括XHTML和XML,表现标准语言主要包括CSS,行为标准主要包括对象模型(如W3C DOM).ECMAScript. 或者说: web标准简单来说可以分为结构.表现和行为.其中结构主要是有HTML标签组成.或

PHP常见面试题汇总(二)

PHP常见面试题汇总(二) //第51题:统计一维数组中所有值出现的次数?返回一个数组,其元素的键名是原数组的值;键值是该值在原数组中出现的次数 $array=array(4,5,1,2,3,1,2,"a","a"); $ac=array_count_values($array); /** * 输出结果: * Array( *   [4] => 1 *   [5] => 1 *   [1] => 2 *   [2] => 2 *   [3] 

献给 2018 还在艰苦奋斗的 Java 程序员,Java 常见面试题及答案!

1.什么是Java虚拟机?为什么Java被称作是"平台无关的编程语言"? Java 虚拟机是一个可以执行 Java 字节码的虚拟机进程.Java 源文件被编译成能被 Java 虚拟机执行的字节码文件. Java 被设计成允许应用程序可以运行在任意的平台,而不需要程序员为每一个平台单独重写或者是重新编译. Java 虚拟机让这个变为可能,因为它知道底层硬件平台的指令长度和其他特性. 2.JDK和JRE的区别是什么? JDK: java开发工具包,包含了JRE.编译器和其它工具(如:jav