c++ 单链表 双向链表 链表笔试题
1 单链表 以及链表笔试题
--------------------------------Slist.h----
#ifndef __SLIST_H__
#define __SLIST_H__
//#pragma once
#include <iostream>
using namespace std;
typedef int DataType;
struct Node
{
Node(const DataType& d)
:_data(d)
,_next(NULL)
{}
DataType _data;
struct Node* _next;
};
class Slist
{
friend ostream& operator<<(ostream& os, const Slist& s);
public:
Slist()
:_head(NULL)
,_tail(NULL)
{
}
Slist(const Slist& s)
:_head(NULL)
,_tail(NULL)
{
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()
{
Node* cur = _head;
while(cur && cur != _tail)//用cur != _tail 防止存在环时 入口点释放两次 导致程序崩溃
{
Node* del = cur;
cur = cur->_next;
delete del;
}
delete _tail;
_head = NULL;
_tail = NULL;
}
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();
void Sort();
void Remove(const DataType& d);
void RemoverAll(const DataType& d);
int GetLength();
/*面试题*/
/* 1、判断两个单链表是不是相交*/
static bool CheckCross(const Slist& list1, const Slist& list2);
/* 2、找到两个单链表的交点*/
static Node* GetCrossNode(Slist& list1, Slist& list2);
/* 3、判断一个单链表是否带环*/
Node* CheckCycle();
/* 4、求取环的长度*/
int GetCircleLength();
/* 5、找到环的入口点*/
Node* GetCycleEntryNode(Node* meetNode);
private:
Node* _head;
Node* _tail;
};
#endif //__SLISH_H__
-------------------------------------Slist.cpp----
#include "Slist.h"
ostream& operator<<(ostream& os, const Slist& s)
{
if(NULL == s._head)
return os;
Node* cur = s._head;
while(NULL != cur)
{
os<<cur->_data<<"->";
cur = cur->_next;
}
os<<"over";
return os;
}
void Slist::PushBack(const DataType& d)
{
Node* newNode = new Node(d);
if(_head == NULL)
{
_head = newNode;
_tail = newNode;
}
else
{
_tail->_next = newNode;
_tail = newNode;
}
}
void Slist::PopBack()
{
if(NULL == _head)
{
return ;
}
else if(_head == _tail)
{
delete _tail;
_tail = _head = NULL;
}
else
{
Node* cur = _head;
while(_tail != cur->_next)
{
cur = cur->_next;
}
delete _tail;
_tail = cur;
_tail->_next = NULL;
}
}
void Slist::PushFront(const DataType& d)
{
Node* newNode = new Node(d);
if(NULL == _head)
{
_head = _tail = newNode;
}
else
{
newNode->_next = _head;
_head = newNode;
}
}
void Slist::PopFront()
{
Node* del = _head;
if(NULL == _head)
{
return ;
}
else if(NULL == _head->_next)
{
_head = _tail = NULL;
}
else
{
_head = _head->_next;
}
delete del;
}
Node* Slist::Find(const DataType& d)
{
Node* cur = _head;
while(cur != NULL)
{
if(cur->_data == d)
{
return cur;
}
cur = cur->_next;
}
return NULL;
}
void Slist::Insert(Node* pos, const DataType& d)//pos后插
{
if(NULL == pos)
{
return ;
}
Node* newNode = new Node(d);
if(pos == _tail)
{
_tail->_next = newNode;
_tail = newNode;
}
else
{
newNode->_next = pos->_next;
pos->_next = newNode;
}
}
//=================================
void Slist::Reverse()
{
if(NULL == _head || NULL == _head->_next)
{
return;
}
Node* pos = _head->_next;
_tail =_head;
_head->_next = NULL;
while(NULL != pos)
{
Node* tmp = pos->_next;
pos->_next = _head;
_head = pos;
pos = tmp;
}
}
void Slist::Sort()
{
Node* pos = _head;
while(NULL != pos)
{
bool flag = true;
Node* index = pos;
Node* min = pos;
while(NULL != index)
{
if(index->_data < min->_data)
{
min = index;
flag = false;
}
index = index->_next;
}
if(true == flag)
{
return;
}
DataType tmp = min->_data;
min->_data = pos->_data;
pos->_data = tmp;
pos = pos->_next;
}
}
void Slist::Remove(const DataType& d)
{
if(NULL == _head)
{
return;
}
Node* pos = _head;
if(pos->_data == d)//头节点
{
if(NULL == pos->_next)
{
delete pos;
_head = _tail = NULL;
}
else
{
Node* del = pos;
pos = pos->_next;
_head = pos;
delete del;
}
return;
}
while(NULL != pos && NULL != pos->_next)
{
if(pos->_next->_data == d)
{
Node* del = pos->_next;
pos->_next = del->_next;
if(del == _tail)
{
_tail = pos;
pos->_next = NULL;
}
delete del;
return;
}
else
{
pos = pos->_next;
}
}
}
void Slist::RemoverAll(const DataType& d)
{
//一定要先删后面的 再考虑第一个
//(若先考虑第一个 删到最后 又成了考虑第一个的情况)
if(NULL == _head)
{
return;
}
Node* pos = _head;
while( pos != _tail)
{
if(pos->_next->_data == d)
{
Node* del = pos->_next;
pos->_next = del->_next;
if(del == _tail)
{
_tail = pos;
_tail->_next = NULL;
delete del;
break;
}
delete del;
}
else
{
pos = pos->_next;
}
}
pos = _head;
if(pos->_data == d)
{
if(pos == _tail)//防止全是d
{
delete pos;
_head = _tail = NULL;
}
else
{
Node* del = pos;
_head = pos->_next;
delete del;
}
}
}
//===============================笔试题 80:12
int Slist::GetLength()
{
int count = 0;
Node* pos = _head;
while(pos)
{
pos = pos->_next;
count++;
}
return count;
}
/* 1、判断两个单链表是不是相交 (主要是判断最后一个点是否相同)*/
bool Slist::CheckCross(const Slist& list1, const Slist& list2)
{
if(NULL == list1._head || NULL == list2._head)
{
return false;
}
Node* l1 = list1._head;
Node* l2 = list2._head;
while(l1->_next)
{
l1 = l1->_next;
}
while(l2->_next)
{
l2 = l2->_next;
}
if(l1 == l2)
{
return true;
}
else
{
return false;
}
}
/* 2、找到两个单链表的交点
* (快慢指针应用)
* 快的先走多出的步 (可能为0 退化成等长) 然后两条链一起走 同时判断是否相等
*/
Node* Slist::GetCrossNode(Slist& list1, Slist& list2)
{
if(list1._head == NULL || list2._head == NULL)
{
return NULL;
}
Node* fast = list1._head;
Node* slow = list2._head;
int len1 = list1.GetLength();
int len2 = list2.GetLength();
int diff = len1 - len2;
if(diff < 0)
{
diff = diff * (-1);
fast = list2._head;
slow = list1._head;
}
while(diff--)
{
fast = fast->_next;
}
while(fast && slow)
{
if(fast == slow)
{
return fast;
}
fast = fast->_next;
slow = slow->_next;
}
return NULL;
}
/*
* 3 判断一个单链表是否带环
* (快慢指针)
*/
Node* Slist::CheckCycle()
{
if(NULL == _head)
{
return NULL;
}
Node* slow = _head;
Node* fast = _head;
while(fast && fast->_next)
{
slow = slow->_next;
fast = fast->_next->_next;
if(fast == slow)
{
return fast;
}
}
return NULL;
}
/*
* 4 求取环的长度
*
*/
int Slist::GetCircleLength()
{
Node* meet = CheckCycle();
int count = 0;
if(meet)
{
Node* cur = meet;
do
{
cur = cur->_next;
count++;
}while(cur != meet);
}
return count;
}
/*
* 5 找到环的入口点
* 两个指针 一次走一步 一个从头开始走 一个从环上的相遇点开始走
* 两指针相遇点即为入口点
*/
/* 方法1
Node* Slist::GetCycleEntryNode(Node* meet)
{
Node* list1 = _head;
Node* list2 = meet;
while(list1 && list2)
{
if(list1 == list2)
{
return list1;
}
list1 = list1->_next;
list2 = list2->_next;
}
return NULL;
}
*/
/* 方法2
* 从判断环的相遇点拆开 拆成两条相交的链 问题转化成求相交链的交点
*/
Node* Slist::GetCycleEntryNode(Node* meet)
{
if(NULL == meet || NULL == _head)
{
return NULL;
}
Slist s1,s2,s3;
s1._head =_head;
s1._tail = meet;
s2._head = meet->_next;
s2._tail = meet;
s1._tail->_next = NULL;//拆分
Node* ret = GetCrossNode(s1, s2);
s1._tail->_next = s2._head;//还原
s1._head = s1._tail = NULL;
s2._head = s2._tail = NULL;
return ret;
}
--------------------------------------------------test.cpp----
#include "Slist.h"
/*
* 测试
* ostream& operator<<(ostream& os, const Slist& s)
* void Slist::PushBack(const DataType& d)
* void Slist::PopBack()
*/
void test1()
{
Slist s1;
s1.PushBack(1);
s1.PushBack(2);
s1.PushBack(3);
s1.PushBack(4);
cout<<s1<<endl;
s1.PopBack();
cout<<s1<<endl;
s1.PopBack();
cout<<s1<<endl;
s1.PopBack();
cout<<s1<<endl;
s1.PopBack();
cout<<s1<<endl;
s1.PopBack();
cout<<s1<<endl;
}
/*
* 测试
* void PushFront(const DataType& d);
* void PopFront();
*/
void test2()
{
Slist s1;
s1.PushFront(1);
s1.PushFront(2);
s1.PushFront(3);
s1.PushFront(4);
cout<<s1<<endl;
s1.PopFront();
cout<<s1<<endl;
s1.PopFront();
cout<<s1<<endl;
s1.PopFront();
cout<<s1<<endl;
s1.PopFront();
cout<<s1<<endl;
s1.PopFront();
cout<<s1<<endl;
s1.PopFront();
cout<<s1<<endl;
}
/*
* 测试
* Node* Find(const DataType& d);
* void Insert(Node* pos, const DataType& d);
*/
void test3()
{
Slist s1;
s1.PushBack(1);
s1.PushBack(2);
s1.PushBack(3);
s1.PushBack(4);
cout<<s1<<endl;
/*cout<<s1.Find(5)<<endl;
cout<<s1.Find(1)<<endl;
cout<<s1.Find(3)->_data<<endl;
cout<<s1.Find(4)->_data<<endl;*/
s1.Insert(s1.Find(0),0);
cout<<s1<<endl;
s1.Insert(s1.Find(1),0);
cout<<s1<<endl;
s1.Insert(s1.Find(2),8);
cout<<s1<<endl;
s1.Insert(s1.Find(4),9);
cout<<s1<<endl;
}
/*
* 测试
* void Reverse();
* void Sort();
*/
void test4()
{
Slist s1,s2,s3,s4;
s1.PushBack(1);
s1.PushBack(2);
s1.PushBack(3);
s1.PushBack(4);
s3.PushBack(1);
s4.PushBack(1);
s4.PushBack(2);
cout<<s1<<endl;
cout<<s2<<endl;
cout<<s3<<endl;
cout<<s4<<endl;
cout<<"================="<<endl;
s1.Reverse();
cout<<s1<<endl;
s2.Reverse();
cout<<s2<<endl;
s3.Reverse();
cout<<s3<<endl;
s4.Reverse();
cout<<s4<<endl;
cout<<"================="<<endl;
s1.Sort();
cout<<s1<<endl;
s2.Sort();
cout<<s2<<endl;
s3.Sort();
cout<<s3<<endl;
s4.Sort();
cout<<s4<<endl;
}
/*
* 测试
* void Remove(const DataType& d);
* void RemoverAll(const DataType& d);
*
*/
void test5()
{
Slist s1;
s1.PushBack(1);
s1.PushBack(1);
s1.PushBack(2);
s1.PushBack(3);
s1.PushBack(4);
s1.PushBack(1);
s1.PushBack(2);
s1.PushBack(3);
s1.PushBack(4);
s1.PushBack(1);
s1.PushBack(1);
cout<<s1<<endl;
cout<<"================="<<endl;
/*s1.Remove(0);
cout<<s1<<endl;
s1.Remove(1);
cout<<s1<<endl;
s1.Remove(3);
cout<<s1<<endl;
s1.Remove(4);
cout<<s1<<endl;*/
s1.RemoverAll(5);
cout<<s1<<endl;
s1.RemoverAll(1);
cout<<s1<<endl;
}
//===============面试题测试==================
/*
* 测试
* static bool CheckCross(const Slist& list1, const Slist& list2);
* static Node* GetCrossNode(Slist& list1, Slist& list2);
*/
void test6()
{
Slist s1,s2;
s1.PushBack(1);
s1.PushBack(2);
s1.PushBack(3);
s1.PushBack(4);
s2.PushBack(1);
s2.PushBack(2);
s2.PushBack(3);
Node* p_tail = s2.Find(3);
p_tail->_next = s1.Find(4);
cout<<Slist::CheckCross(s1, s2)<<endl;
cout<<Slist::GetCrossNode(s1,s2)->_data<<endl;
p_tail->_next = NULL;
}
/*
* 测试
* Node* CheckCycle();
* int Slist::GetCircleLength()
*/
void test7()
{
Slist s1;
s1.PushBack(1);
s1.PushBack(2);
s1.PushBack(3);
s1.PushBack(4);
s1.Find(4)->_next = s1.Find(1);
cout<<s1.CheckCycle()->_data<<endl;
cout<<s1.GetCircleLength()<<endl;
s1.Find(4)->_next = NULL;//防止析构出错
}
/*
* 测试
* Node* Slist::GetCycleEntryNode(Node* meet)
*/
void test8()
{
Slist s1;
s1.PushBack(1);
s1.PushBack(2);
s1.PushBack(3);
s1.PushBack(4);
s1.Find(4)->_next = s1.Find(3);
cout<<s1.GetCycleEntryNode(s1.CheckCycle())->_data;
//改造析构后 析构可以处理环 不用再s1.Find(4)->_next = NULL;
s1.Find(4)->_next = s1.Find(1);
cout<<s1.GetCycleEntryNode(s1.CheckCycle())->_data;
//s1.Find(4)->_next = NULL;
}
int main()
{
test8();
getchar();
return 0;
}
========================================================================
2 双向链表
--------------------------------------------DList.h----
#pragma once
#include <iostream>
using namespace std;
typedef int DataType;
struct Node
{
Node(const DataType& d)
:_data(d)
,_prev(NULL)
,_next(NULL)
{
}
Node* _next;
Node* _prev;
DataType _data;
};
class DList
{
friend ostream& operator<<(ostream& os, const DList& d);
public:
DList()
:_head(NULL)
,_tail(NULL)
{}
~DList()
{
Node* cur = _head;
while(cur)
{
Node* del = cur;
cur = cur->_next;
delete del;
}
}
public:
void PushBack(const DataType& d);
void PushFront(const DataType& d);
void PopBack();
void PopFront();
Node* Find(const DataType& d);
void Insert(Node* pos, const DataType& d);
void Sort();
void Reverse();
void Remove(const DataType& d);
void RemoveAll(const DataType& d);
void Erase(Node* pos);//删除
private:
Node* _head;
Node* _tail;
};
------------------------------------DList.cpp----
#define _CRT_SECURE_NO_WARNINGS 1
#include "DList.h"
ostream& operator<<(ostream& os, const DList& d)
{
Node* cur = d._head;
while(cur)
{
os<<cur->_data<<"<=>";
cur = cur->_next;
}
os<<"over";
return os;
}
void DList::PushBack(const DataType& d)
{
Node* newNode = new Node(d);
if(NULL == _head)
{
_head = newNode;
_tail = newNode;
}
else
{
_tail->_next = newNode;
newNode->_prev = _tail;
_tail = newNode;
}//============120:18
}
void DList::PushFront(const DataType& d)
{
Node* newNode = new Node(d);
if(NULL == _head)
{
_head = newNode;
_tail = newNode;
return;
}
else
{
newNode->_next = _head;
_head = newNode;
}
}
void DList::PopBack()
{
if(NULL == _head)
{
return;
}
else if(_head == _tail)
{
delete _head;
_head = _tail = NULL;
}
else
{
_tail = _tail->_prev;
delete _tail->_next;
_tail->_next = NULL;
}
}
void DList::PopFront()
{
if(NULL == _head)
{
return;
}
else if(_tail == _head)
{
delete _head;
_head = _tail = NULL;
}
else
{
Node* del = _head;
_head = _head->_next;
_head->_prev = NULL;
delete del;
}
}
Node* DList::Find(const DataType& d)
{
Node* cur = _head;
while(cur)
{
if(cur->_data == d)
{
return cur;
}
cur = cur->_next;
}
return NULL;
}
void DList::Insert(Node* pos, const DataType& d)
{
if(NULL == pos)
{
return;
}
Node* newNode = new Node(d);
newNode->_next = pos->_next;
newNode->_prev = pos;
pos->_next = newNode;
if(pos == _tail)
{
_tail = newNode;
}
}
void DList::Sort()
{
if(NULL == _head)
{
return;
}
Node* cur = _head;
while(cur->_next)
{
bool flag = true;
Node* min = cur;
Node* index = cur;
while(index)
{
if(index->_data < min->_data)
{
min = index;
flag = false;
}
index = index->_next;
}
if(flag)
{
return;
}
DataType tmp = min->_data;
min->_data = cur->_data;
cur->_data = tmp;
cur = cur->_next;
}
}
void DList::Reverse()
{
Node* cur = _head;
_head = NULL;
_tail = NULL;
while(cur)
{
PushFront(cur->_data);
cur = cur->_next;
}
}
void DList::Remove(const DataType& d)
{
Node* del = Find(d);
if(del)
{
if(_head == _tail)//一个结点
{
delete del;
_head = _tail = NULL;
return;
}
if(_head == del)//在头结点 但不是一个结点
{
_head = del->_next;
_head->_prev = NULL;
delete del;
return;
}
if(del == _tail)
{
_tail = del->_prev;
_tail->_next = NULL;
delete del;
return;
}
del->_prev->_next = del->_next;
del->_next->_prev = del->_prev;
delete del;
}
}
void DList::RemoveAll(const DataType& d)
{
Node* del = Find(d);
while(del)
{
Remove(d);
del = Find(d);
}
}
void DList::Erase(Node* pos) //删除
{
if(NULL == _head || NULL == pos)
{
return;
}
if(_head == _tail )
{
if(_head == pos)
{
delete pos;
_head = _tail = NULL;
return;
}
}
if(pos == _head)
{
_head = _head->_next;
_head->_prev = NULL;
delete pos;
return;
}
if(pos == _tail)
{
_tail = _tail->_prev;
_tail->_next = NULL;
delete pos;
return;
}
pos->_prev->_next = pos->_next;
pos->_next->_prev = pos->_prev;
delete pos;
}
--------------------------------test.cpp----
#define _CRT_SECURE_NO_WARNINGS
#include "DList.h"
/*
* 测试
* PushBack() PopBack() operator<<
*/
void test1()
{
DList l1;
l1.PushBack(1);
l1.PushBack(2);
l1.PushBack(3);
l1.PushBack(4);
cout<<l1<<endl;
l1.PopBack();
cout<<l1<<endl;
l1.PopBack();
cout<<l1<<endl;
l1.PopBack();
cout<<l1<<endl;
l1.PopBack();
cout<<l1<<endl;
l1.PopBack();
cout<<l1<<endl;
l1.PopBack();
}
/*
* 测试
* void DList::PopBack()
* void DList::PopFront()
*/
void test2()
{
DList l1;
l1.PushFront(1);
cout<<l1<<endl;
l1.PushFront(2);
cout<<l1<<endl;
l1.PushFront(3);
cout<<l1<<endl;
l1.PushFront(4);
cout<<l1<<endl;
l1.PopFront();
cout<<l1<<endl;
l1.PopFront();
cout<<l1<<endl;
l1.PopFront();
cout<<l1<<endl;
l1.PopFront();
cout<<l1<<endl;
l1.PopFront();
cout<<l1<<endl;
l1.PopFront();
cout<<l1<<endl;
l1.PopFront();
cout<<l1<<endl;
}
/*
* 测试
* Node* DList::Find(const DataType& d)
* void DList::Insert(Node* pos, const DataType& d)
*/
void test3()
{
DList l1;
l1.PushBack(1);
l1.PushBack(2);
l1.PushBack(3);
l1.PushBack(4);
cout<<l1<<endl;
cout<<l1.Find(-1)<<endl;
cout<<l1.Find(1)->_data<<endl;
cout<<l1.Find(2)->_data<<endl;
cout<<l1.Find(3)->_data<<endl;
cout<<l1.Find(4)->_data<<endl;
l1.Insert(NULL,1);
cout<<l1<<endl;
l1.Insert(l1.Find(1),5);
cout<<l1<<endl;
l1.Insert(l1.Find(2),6);
cout<<l1<<endl;
l1.Insert(l1.Find(3),7);
cout<<l1<<endl;
l1.Insert(l1.Find(4),8);
cout<<l1<<endl;
}
/*
* 测试
* void DList::Sort()
* void DList::Reverse()
*/
void test4()
{
DList l1,l2,l3;
l1.PushBack(1);
l1.PushBack(2);
l1.PushBack(3);
l1.PushBack(4);
l2.PushBack(1);
l2.PushBack(2);
cout<<l1<<endl;
cout<<l2<<endl;
cout<<l3<<endl;
l1.Reverse();
cout<<l1<<endl;
l2.Reverse();
cout<<l2<<endl;
l3.Reverse();
cout<<l3<<endl;
l1.Sort();
cout<<l1<<endl;
l2.Sort();
cout<<l2<<endl;
l3.Sort();
cout<<l3<<endl;
}
/*
* 测试
* void DList::RemoveAll(const DataType& d)
* void DList::RemoveAll(const DataType& d)
*/
void test5()
{
DList s1;
s1.PushBack(1);
s1.PushBack(1);
s1.PushBack(2);
s1.PushBack(3);
s1.PushBack(4);
s1.PushBack(1);
s1.PushBack(2);
s1.PushBack(3);
s1.PushBack(4);
s1.PushBack(1);
s1.PushBack(1);
cout<<s1<<endl;
cout<<"================="<<endl;
//s1.Remove(0);
//cout<<s1<<endl;
//s1.Remove(1);
//cout<<s1<<endl;
//s1.Remove(3);
//cout<<s1<<endl;
//s1.Remove(4);
//cout<<s1<<endl;
s1.RemoveAll(5);
cout<<s1<<endl;
s1.RemoveAll(1);
cout<<s1<<endl;
}
/*
* 测试
* void DList::Erase(Node* pos) //删除
*/
void test6()
{
DList l1;
l1.PushBack(1);
l1.PushBack(2);
l1.PushBack(3);
l1.PushBack(4);
l1.PushBack(5);
cout<<l1<<endl;
l1.Erase(NULL);
cout<<l1<<endl;
l1.Erase(l1.Find(1));
cout<<l1<<endl;
l1.Erase(l1.Find(5));
cout<<l1<<endl;
l1.Erase(l1.Find(3));
cout<<l1<<endl;
}
int main()
{
test6();
getchar();
return 0;
}