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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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;

}


以上是关于c++实现单向单链表及常见面试题的主要内容,如果未能解决你的问题,请参考以下文章

java 多态性详解及常见面试题

redis知识点及常见面试题

JAVA异常架构图及常见面试题

RabbitMQ简单介绍及常见面试题

第十二章 Shell脚本编写及常见面试题

数据结构之链表+常见面试题