数据结构与算法--用单向链表实现栈(C++实现)

前言

栈是基本的数据结构。其特点是添加和访问数据都在线性表的一端(头端)。数据访问遵循后出先进(LIFO)的原则。栈一般用数组或者链表来实现。数组需要静态分配数据空间,占用空间比较大。链表则根据实际需要动态分配数据空间,占用空间相对小一些。本文用单向链表实现栈。程序用C++实现。本文是C++、数据结构及算法学习的一个小小练习。供大家参考。

栈的操作

栈的操作主要就两个:入栈(push)和出栈(pop)。顾名思义,入栈就是将数据压入栈中保存;出栈就是将数据弹出栈,同时访问数据。

数据结构和算法描述

节点的结构

节点(Node)分为两部分,数据和链接部分。数据部分存储数据,可以根据实际情况分为若干字段。本文数据部分分两个字段:key和data。链接部分就是一个指针,指向下一个节点。然后让头指针指向第一个节点,这样一个链式的栈就形成了。C++代码如下:

struct Node {
	int key;
	string data;
	Node *next=nullptr;
}

C++的结构允许有自己的构造函数,我们将上面的节点结构改写一下,包含构造函数:

struct Node {
	int key;
	string data;
	Node *next=nullptr;
	Node(int ky, string da, Node *nxt=nullptr) : key(ky), data(da), next(nxt) {};
}

算法描述

入栈和出栈的算法比较简单,直接用C++描述如下。

push(int ky, string da)
{
	head=new Node(ky,da,head);
	return;
}

pop(int &ky, string &da)
{
	Node *p;
	p=head;
	if (nullptr!=head) {
		ky=key;
		da=data;
		head=head->next;
		delete p;
	}	
	return;
}

类的定义

栈定义成一个类,其上定义了构造函数、析构函数、入栈(push)、出栈(pop)、判断空栈函数(isEmpty())以及指向链表头节点的指针head。C++代码如下:

class Stack
{
    public:
        Stack();
        virtual ~Stack();
        Stack(const Stack& other);
        Stack& operator=(const Stack& other);
        bool isEmpty() { return nullptr==head; }
        void push(int ky, string da);
        void pop(int &ky, string &da);
        void pop();
    protected:
    private:
        Node *head=nullptr;
};

程序清单及说明

除了以上类和结构的定义外,作为实验定义了数据读取函数readData(filename),从数据文件中读入实验数据并生成栈。主程序则对栈的操作做了相应试验。

全部程序清单如下:

#include <iostream>
#include <fstream>
using namespace std;
struct Node {
    int key;
    string data;
    Node *next=nullptr;
    Node(int ky, string da, Node *nxt=nullptr) : key(ky), data(da), next(nxt) {};
};
class Stack
{
    public:
        Stack();
        virtual ~Stack();
        Stack(const Stack& other);
        Stack& operator=(const Stack& other);
        bool isEmpty() { return nullptr==head; }
        void push(int ky, string da);
        void pop(int &ky, string &da);
        void pop();
    protected:
    private:
        Node *head=nullptr;
};
Stack::Stack()
{
    head=nullptr;
}
Stack::~Stack()
{ 
    while(!isEmpty()) { pop(); }
}
Stack::Stack(const Stack& other)
{ 
    head=other.head;
}
Stack& Stack::operator=(const Stack& rhs)
{
    if (this == &rhs) return *this;  
    head=rhs.head;
    return *this;
}
void Stack::push(int ky, string da)
{
    head=new Node(ky,da,head);
    return;
}
void Stack::pop(int &ky, string &da)
{
    Node *p=head;
    if (!isEmpty()) {
        ky=head->key;
        da=head->data;
        head=head->next;
        delete p;
    }
    return;
}
void Stack::pop()
{
    Node *p=head;
    if (!isEmpty()) {
        head=head->next;
        delete p;
    }
    return;
}

Stack st;
int readData(string fn)
{
    int itmsRead=0;
    int k;
    string str;
    ifstream datafile(fn);
    if (!datafile) {
        itmsRead=-1;
    }
    else {
        while (datafile >> k >> str) {
            st.push(k,str);
            itmsRead++;
        }
    }
    return itmsRead;
}

int main()
{
    int k;
    string str;
    int itms=0;
    string datafilename="datafile.txt";
    cout<<"Read data ... ";
    itms=readData(datafilename);
    if (-1==itms) {
        cout << "404, File not found." << endl;
    }
    else {
        cout<<itms<<" item(s) read."<<endl;
        cout<<"Pop data ... "<<endl;
        while (!st.isEmpty()) {
            st.pop(k,str);
            cout<<"("<<k<<", "<<str<<") ";
        }
    }
    return 0;
}

小结

整个程序比较简单。唯一要注意的是指针的运用。一是要防止出现野指针。指针定义的时候要赋初值。二是操作指针前先要判断指针是否为空,以避免在空指针上操作。

供试验用的数据文件,datafile.txt。内容如下:

24 Xyz
2 Bcd
3 Cde
1 Abc
4 Def
10 Exa
22 Vwx
7 Ghi
8 Hij
9 Ijk
1 A
10 Jkl
5 Efg
24 Xz
11 Klm
12 Lmn
26 Z
13 Mno
25 Sam
1 Ab
14 Nop
6 Fgh
15 Opq
16 Pqr
1 bc
18 Rst
19 Stu
20 Tuv
24 Xy
21 Txt
17 Qrs
21 Uvw
23 Wxy
25 Yz
原创文章 8 获赞 9 访问量 4万+

猜你喜欢

转载自blog.csdn.net/yang_deyuan/article/details/105328613