c++ 单链表 双向链表 链表笔试题
1 单链表 以及链表笔试题
--------------------------------Slist.h----
#ifndef __SLIST_H__
#define __SLIST_H__
//#pragma once
#include
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 = 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.PopBack(); cout< s1.PopBack(); cout< s1.PopBack(); cout< s1.PopBack(); cout< s1.PopBack(); cout< } /* * 测试 * 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.PopFront(); cout< s1.PopFront(); cout< s1.PopFront(); cout< s1.PopFront(); cout< s1.PopFront(); cout< s1.PopFront(); cout< } /* * 测试 * 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< /*cout< cout< cout< cout< s1.Insert(s1.Find(0),0); cout< s1.Insert(s1.Find(1),0); cout< s1.Insert(s1.Find(2),8); cout< s1.Insert(s1.Find(4),9); cout< } /* * 测试 * 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< cout< cout< cout< cout<<"================="< s1.Reverse(); cout< s2.Reverse(); cout< s3.Reverse(); cout< s4.Reverse(); cout< cout<<"================="< s1.Sort(); cout< s2.Sort(); cout< s3.Sort(); cout< s4.Sort(); cout< } /* * 测试 * 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< cout<<"================="< /*s1.Remove(0); cout< s1.Remove(1); cout< s1.Remove(3); cout< s1.Remove(4); cout< s1.RemoverAll(5); cout< s1.RemoverAll(1); cout< } //===============面试题测试================== /* * 测试 * 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< cout< 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< cout< 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.Find(4)->_next = NULL; s1.Find(4)->_next = s1.Find(1); cout< //s1.Find(4)->_next = NULL; } int main() { test8(); getchar(); return 0; } ======================================================================== 2 双向链表 --------------------------------------------DList.h---- #pragma once #include 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 = 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.PopBack(); cout< l1.PopBack(); cout< l1.PopBack(); cout< l1.PopBack(); cout< l1.PopBack(); cout< l1.PopBack(); } /* * 测试 * void DList::PopBack() * void DList::PopFront() */ void test2() { DList l1; l1.PushFront(1); cout< l1.PushFront(2); cout< l1.PushFront(3); cout< l1.PushFront(4); cout< l1.PopFront(); cout< l1.PopFront(); cout< l1.PopFront(); cout< l1.PopFront(); cout< l1.PopFront(); cout< l1.PopFront(); cout< l1.PopFront(); cout< } /* * 测试 * 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< cout< cout< cout< cout< cout< l1.Insert(NULL,1); cout< l1.Insert(l1.Find(1),5); cout< l1.Insert(l1.Find(2),6); cout< l1.Insert(l1.Find(3),7); cout< l1.Insert(l1.Find(4),8); cout< } /* * 测试 * 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< cout< cout< l1.Reverse(); cout< l2.Reverse(); cout< l3.Reverse(); cout< l1.Sort(); cout< l2.Sort(); cout< l3.Sort(); cout< } /* * 测试 * 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< cout<<"================="< //s1.Remove(0); //cout< //s1.Remove(1); //cout< //s1.Remove(3); //cout< //s1.Remove(4); //cout< s1.RemoveAll(5); cout< s1.RemoveAll(1); cout< } /* * 测试 * 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.Erase(NULL); cout< l1.Erase(l1.Find(1)); cout< l1.Erase(l1.Find(5)); cout< l1.Erase(l1.Find(3)); cout< } int main() { test6(); getchar(); return 0; }