链表、数组、队列和栈都是常见的数据结构,用于存储和组织数据。它们在不同情况下有不同的特点和应用。
数组(Array):
1.数组是一种线性数据结构,元素在内存中是连续存储的。
2.元素可以通过索引访问,索引通常从0开始。
3.插入和删除操作的效率较低,时间复杂度为O(n),但查找操作的效率较高,时间复杂度为O(1)。
C++代码实现:
#include <iostream>
using namespace std;
//分数类
class CFraction {
int numerator, denominator; //分子分母
public:
CFraction(int n, int d) :numerator(n), denominator(d) { };
bool operator <(const CFraction& f) const
{//为避免除法产生的浮点误差,用乘法判断两个分数的大小关系
if (denominator * f.denominator > 0)
return numerator * f.denominator < denominator * f.numerator;
else
return numerator * f.denominator > denominator * f.numerator;
}
bool operator == (const CFraction& f) const
{//为避免除法产生的浮点误差,用乘法判断两个分数是否相等
return numerator * f.denominator == denominator * f.numerator;
}
friend ostream& operator <<(ostream& o, const CFraction& f);
};
template <class T> //声明函数模板
T MaxElement(T a[], int size) //定义函数体
{
//函数功能:找出数组中的最大值
T max_v = a[0];
for (int i = 1; i < size; i++) {
if (max_v < a[i]) {
max_v = a[i];
}
}
return max_v;
}
ostream& operator <<(ostream& o, const CFraction& f) //重载 << 使得分数对象可以通过cout输出
{
o << f.numerator << "/" << f.denominator << endl; //补充代码,输出"分子/分母" 形式
return o;
}
int main()
{
int a[5] = { 1,5,2,3,4 };//定义整数数组
CFraction f[4] = { CFraction(8,6),CFraction(-8,4),
CFraction(3,2), CFraction(5,6) };//定义分数类数组对象
int maxInt = MaxElement(a, 5);//调用模板函数MaxElement输出整数数组a的最大值
cout << "整数集合a[]的最大值为:" << maxInt << endl;
CFraction maxFraction = MaxElement(f, 4); //调用模板函数MaxElement和重载运算符函数”<<”输出分数数组对象的最大值
cout << "分数集合f[]的最大值为:" << maxFraction << endl;
return 0;
}
链表(Linked List):
1.链表是由一系列节点组成的数据结构,每个节点包含数据和指向下一个节点的指针。
2.分为单向链表和双向链表。单向链表的节点只有指向下一个节点的指针,而双向链表的节点除了指向下一个节点的指针外,还有指向前一个节点的指针。
3.插入和删除操作效率高,时间复杂度为O(1),但查找操作的效率较低,时间复杂度为O(n)。
C++代码实现:
#include<iostream>
using namespace std;
//定义结点模板类
template <class T> //前置申明模板类
class Node //定义一个Node类
{
public:
Node(T _value) //构造函数
{
value = _value;
next = NULL;
}
public:
T value; //结点数据域
Node* next; //结点指针域,指向后继结点
};
//定义链表模板类
template <class T> //申明模板类
class List //定义List类
{
public:
List()
{
ptr_head = NULL; //初始化链表头结点
ptr_tail = NULL; //初始化链表尾结点
}
void insertnodelist(T _value); //插入结点
void printlist(); //输出结点
void findlist(T value1); //查找结点
public:
Node<T>* ptr_head; //链表头结点
Node<T>* ptr_tail; //链表尾结点
};
//定义链表模板类
template <class T> //类外实现函数时该语句不能省!
void List<T>::insertnodelist(T _value) //类外实现插入结点函数
{
Node<T>* ptr_new = new Node<T>(_value); //创建新结点
if (ptr_head == NULL)
{
ptr_head = ptr_new; //如果头结点的后继指针为空,则该结点为头结点
}
else
{
ptr_tail->next = ptr_new; //链表尾结点指向新插入的结点
}
ptr_tail = ptr_new; //新插入的结点变为尾结点
}
//定义链表模板类
template <class T> //类外实现函数时该语句不能省!
void List<T>::printlist() //类外实现输出链表函数
{
Node<T>* current = ptr_head;
while (current != NULL) {
cout << current->value << " ";
current = current->next;
}
cout << endl;
}
template <class T> //类外实现函数时该语句不能省!
void List<T>::findlist(T value1) //类外实现查找链表函数
{
Node<T>* current = ptr_head;
while (current != NULL) {
if (current->value == value1) {
cout << "找到: " << value1 << endl;
return;
}
current = current->next;
}
cout << "未找到: " << value1 << endl;
}
int main()
{
List<int> list; //定义对象,使用时确定数据成员类型
list.insertnodelist(1); //创建链表
list.insertnodelist(2);
list.insertnodelist(5);
list.printlist(); //输出链表
list.findlist(3); //查找链表中某个数
return 0;
}
队列(Queue):
1.队列是一种先进先出(FIFO)的数据结构,类似于排队。
2.元素只能从队尾入队,从队首出队。
3.常见的队列有普通队列、优先级队列和循环队列。
C++代码实现:
#include<iostream>
using namespace std;
const int MaxQSize = 50;
template <class T>
class Queue
{
private:
int front, rear, count; //队头指针、队尾指针、元素个数
T qlist[MaxQSize]; //队列元素数组
public:
Queue() :front(0), rear(0), count(0) {} //构造函数
void QInsert(const T& item); //新元素入队
T QDelete(void); //元素出队
void ClearQueue(void); //清空队列
T QFront(void) const; //访问队首元素
int QLength(void) const; //求队列长度(元素个数)
int QEmpty(void) const; //判队队列空否
int QFull(void) const; //判断队列满否
void showdate();
};
template <class T>
void Queue<T>::QInsert(const T& item) //向队尾插入元素(入队)
{
if (count == MaxQSize) // 如果队满,中止程序
{
std::cerr << "Queue overflow!" << endl;
exit(1);
}
count++; //元素个数增1
qlist[rear] = item; //向队尾插入元素
rear = (rear + 1) % MaxQSize; //队尾指针增1,用取余运算实现循环队列
}
template <class T>
T Queue<T>::QDelete(void) //删除队首元素,并返回该元素的值(出队)
{
T temp;
if (count == 0) // 如果队空,中止程序
{
std::cerr << "Deleting from an empty queue!" << endl;
exit(1);
}
temp = qlist[front]; // 记录队首元素值
count--; // 元素个数自减
front = (front + 1) % MaxQSize; //队首指针增1。取余以实现循环队列
return temp; //返回首元素值
}
template <class T>
T Queue<T>::QFront(void) const // 访问队列首元素(返回其值)
{
return qlist[front];
}
template <class T>
int Queue<T>::QLength(void) const // 返回队列元素个数
{
return count;
}
template <class T>
int Queue<T>::QEmpty(void) const // 测试队空否
{
return count == 0;//返回逻辑值 count == 0
}
template <class T>
int Queue<T>::QFull(void) const // 测试队满否
{
return count == MaxQSize; // 返回逻辑值 count == MaxQSize
}
template <class T>
void Queue<T>::ClearQueue(void)
{
// 清空队列
count = 0;
front = 0;
rear = 0;
}
template <class T>
void Queue<T>::showdate()
{
cout << "当前队列数据为:";
for (int i = 0; i < count; i++)
cout << " " << qlist[i];
cout << endl;
}
int main()
{
const int a[8] = { 1, 2, 3, 4, 5, 6, 7, 8 };
Queue<int> s;
int n;
cout << "请输入要进行的操作次数:";
cin >> n;
while (n--)
{
int operation;
cout << "请输入操作:(1 表示入队,0 表示出队)";
cin >> operation;
if (operation == 1)
{
int index;
cout << "请输入要入队的元素下标:";
cin >> index;
s.QInsert(a[index]);
}
else if (operation == 0)
{
s.QDelete();
}}
s.showdate();
return 0;
}
栈(Stack):
1.常见的应用包括函数调用栈、表达式求值和浏览器历史记录等。
2.元素只能从栈顶压入(push)和弹出(pop)。
3.栈是一种后进先出(LIFO)的数据结构,类似于一摞盘子。
C++代码实现:
const int maxsize = 100;
template <typename T>
class Stack
{
private:
T elems[maxsize]; //elems数组用于存储栈的数据元素
int top; //栈顶的位置
public:
Stack() { top = 0; }
void push(T e); //入栈
T pop(); //出栈
bool empty(); //判断栈是否为空
bool full(); //判断栈是否满
};
template <typename T>
bool Stack<T>::empty()
{
if (top == 0) //判断栈是否为空
return true;
else
return false;
}
template <typename T>
bool Stack<T>::full()
{
if (top == maxsize) //判断栈是否满
return true;
else
return false;
}
template <typename T>
void Stack<T>::push(T e)
{
if (!full())
elems[top++] = e; //入栈
}
template <typename T>
T Stack<T>::pop()
{
if (!empty())
return elems[--top]; //出栈
}
void main()
{
int n,e;
while (cin >> n)
{
Stack<int> s;//定义堆栈对象
while (n--)
{
cin >> e;
s.push(e);//入栈
}
cin >> n;
while (n--) //出栈
{
if (!s.empty())
cout << s.pop();
else
cout << "empty!!";
if (n)
cout << " ";//注意这里的格式是每两个数或字符串或数与字符串之间有空格
}
cout << endl;
}
}