数据结构与算法

本文深入探讨了数据结构中的核心概念,包括顺序表、链表、栈、队列、二叉树、哈希表等,并展示了它们在实际问题中的应用,如约瑟夫问题、二叉排序树、哈弗曼编码等。此外,还详细介绍了排序算法(如插入排序、冒泡排序、快速排序、希尔排序)和查找算法(如二分查找、回溯算法)。对于图论,讲解了拓扑排序、并查集以及它们的实现。这些基础知识对于理解计算机科学至关重要,是提升编程能力的基础。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

数据结构

1.顺序表

顺序表是在计算机内存中以数组的形式保存的线性表。(存储单元地址连续)

template <class T>
class SortList
{
   
   
private:
    T data[Masize]; //最大容量为MaxSize
    int length;

public:
    SortList();
    ~SortList();
    void Insert(T x); //有序插入(从小到大)
    int Locate(T x);  //查找
    void Display();   //输出表中信息
}; 
template <class T>
SortList<T>::SortList()
{
   
   
    for (int i = 0; i < MaxSize; i++)
    {
   
   
        data[i] = 0;
    }
    length = 0;
}
template <class T>
SortList<T>::~SortList()
{
   
   
}
template <class T>
void SortList<T>::Insert(T x)
{
   
   
    if (length >= Maxsize)
        throw "Overflow";
    int pos;
    for (pos = 0; pos < length; pos++)
    {
   
   
        if (x < data[pos])
            break;
    }
    for (int i = length; i >= pos; i--)
    {
   
   
        data[i + 1] = data[i];
    }
    data[pos] = x;
    lenght++;
}
template <class T>
int SortList<T>::Locate(T x)
{
   
   
    int ret = -1;
    for (int i = 0; i < length; i++)
    {
   
   
        if (data[i] == x)
            ret = i;
        else if (data[i] > x) //后续不可能存在比当前位置小的数据
            break;
    }
    if (ret == -1)
        throw "No found";
    else
        return ret;
}
template <class T>
void SortList<T>::Display()
{
   
   
    for (int i = 0; i < length; i++)
    {
   
   
        cout << data[i] << " ";
    }
    cout << endl;
}

2.链表

链表是一种物理存储单元上非连续、非顺序的存储结构,由一个一个的节点连接而成。

链表根据节点的不同分成单向、单向循环、双向循环链表。

//双向循环链表
template <class T>
struct Node//节点
{
   
   
    T data;//数据域
    Node<T> *prior, *next;//指针域(分别有前指针prior和后指针next)
};

template <class T>
class LinkList
{
   
   
public:
    LinkList();      //建立只有头结点的双向循环链表链表
    ~LinkList();     //析构函数
    int Length();     //求链表的长度
    void Insert(T x); //表尾插入x
    void DispListF(); //正向遍历链表,按照逻辑序号输出各元素
    void DispListR(); //反向遍历链表,按照反向逻辑序号输出各元素
private:
    Node<T> *first; //链表的头指针
};
template <class T>
LinkList<T>::LinkList()
{
   
   
    first = new Node<T>;
    first->next = first->prior = first;
}
template <class T>
LinkList<T>::~LinkList()
{
   
   
    Node<T> *s;
    s = first->next;
    while (s != first)
    {
   
   
        first->next = s->next;
        delete s;
        s = first->next;
    }
    delete s;
}
template <class T>
int LinkList<T>::Length()
{
   
   
    Node<T> *p;
    int length=0;
    p = first;
    while (p->next != first)
    {
   
   
        length++;
        p = p->next;
    }
    return length;
}
template <class T>
void LinkList<T>::Insert(T x)
{
   
   
    Node<T> *p;
    p=new Node<T>;
    p->data=x;
    p->prior=first->prior;
    p->prior->next=p;
    p->next=first;
    first->prior=p;
}
template <class T>
void LinkList<T>::DispListF()
{
   
   
    cout<<"The length:"<<Length()<<endl;
    cout<<"The elements:";
    Node<T> *p;
    p=first;
    while (p->next!=first)
    {
   
   
        p=p->next;
        cout<<p->data<<" ";
    }
    cout<<endl;
}
template <class T>
void LinkList<T>::DispListR()
{
   
   
    cout<<"The length:"<<Length()<<endl;
    cout<<"The elements:";
    Node<T> *p;
    p=first;
    while (p->prior!=first)
    {
   
   
        p=p->prior;
        cout<<p->data<<" ";
    }
    cout<<endl;
}

典型例题:约瑟夫问题。

3.栈

栈是一种运算受限的线性表,限定仅在表尾进行插入和删除操作的线性表。

//链式栈
template <class T>
class Node
{
   
   
public:
    T data;
    Node<T> *prior;
};
template <class T>
class LinkStack
{
   
   
public:
    LinkStack();    //构造函数,置空链栈
    ~LinkStack();   //析构函数,释放链栈中各结点的存储空间
    void Push(T x); //将元素x入栈
    T Pop();        //将栈顶元素出栈
    T GetTop();     //取栈顶元素(并不删除)
    bool Empty();   //判断链栈是否为空栈
private:
    Node<T> *top; //栈顶指针即链栈的头指针
};
template <class T>
LinkStack<T>::LinkStack()
{
   
   
    top = NULL;
}
template <class T>
LinkStack<T>::~LinkStack()
{
   
   
    Node<T> *p, *s;
    p = top;
    while (p != NULL)
    {
   
   
        s = p;
        p = p->prior;
        delete s;
    }
    top = NULL;
}
template <class T>
void LinkStack<T>::Push(T x)
{
   
   
    Node<T> *p, *s;
    p = top;
    s = new Node<T>;
    s->data = x;
    s->prior = p;
    top = s;
}
template <class T>
T LinkStack<T>::Pop()
{
   
   
    Node<T> *p;
    p = top;
    top = top->prior;
    T s = p->data;
    delete p;
    return s;
}
template <class T>
T LinkStack<T>::GetTop()
{
   
   
    if (top != NULL)
        return top->data;
    else
        throw "Downflow";
}
template <class T>
bool LinkStack<T>::Empty()
{
   
   
    if (top == NULL)
        return true;
    return false;
}

典型例题:进制转换、逆波兰式。

4.队列

队列是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作。

//循环队列
class CirQueue
{
   
   
public:
    CirQueue();        //构造函数,置空队
    ~CirQueue();       //析构函数
    void EnQueue(T x); //将元素x入队
    T DeQueue();       //将队头元素出队
    T GetQueue();      //取队头元素(并不删除)
    bool Empty();      //判断队列是否为空
    bool Full();       //判断队列是否为满
private:
    T data[QueueSize]; //存放队列元素的数组
    int front, rear;   //队头和队尾指针,分别指向队头元素所在数组的前一下标和队尾元素的数组下标
    int count;         //记录队列中数据个数
};
template <class T>
CirQueue<T>::CirQueue()
{
   
   
    front = rear = QueueSize - 1;
    count = 0;
}
template <class T>
CirQueue<T>::~CirQueue()
{
   
   
}
template <class T>
T CirQueue<T>::DeQueue()
{
   
   
    if (Empty())
        throw "Downflow";
    count--;
    int tmp = front;
    front = (front + 1) % QueueSize; //队头指针在循环意义下加1
    return data[tmp];                //读取并返回出队前的队头元素,注意队头指针
}
template <class T>
T CirQueue<T>::GetQueue()
{
   
   
    int i;
    if (Empty())
        throw "Downflow";
    i = (front + 1) % QueueSize; //注意不要给队头指针赋值
    return data[i];
}
template <class T>
bool CirQueue<T>::Empty()
{
   
   
    if (count == 0)
        return true;
    return false;
}
template <class T>
bool CirQueue<T>::Full()
{
   
   
    if (count == 5)
        return true;
    return false;
}
template <class T>
void CirQueue<T>::EnQueue(T x)
{
   
   
    if (!Full())
    {
   
   
        count++;
        data[rear] = x;
        rear = (rear + 1) % QueueSize;
    }
    else
        throw "Overflow";
}

5.二叉树

二叉树是树形结构的一个重要类型,二叉树特点是每个结点最多只能有两棵子树,且有左右之分。

先序遍历(递归):先访问根节点,然后访问左节点,最后访问右节点。

中序遍历(递归):先访问左节点,然后访问根节点,最后访问右节点。

后序遍历(递归):先访问左节点,然后访问右节点,最后访问根节点。

非递归遍历:利用栈消除递归。

层次遍历:利用队列遍历。

计算叶子节点:递归统计左右子叶的和。

计算高度:递归比较左右子叶高度。

5.1数组实现

template <class T>
class BiTree
{
   
   
public:
    BiTree(T *);             //构造函数,初始化一棵二叉树,其前序序列由键盘输入
    void PreOrder(int pos);  //前序遍历二叉树
    void InOrder(int pos);   //中序遍历二叉树
    void PostOrder(int pos); //后序遍历二叉树
    int CountLeaf(int pos);  //计算叶子结点总数
    int Depth(int pos);      //计算高度
    void PreOrder();         //非递归先序遍历
    void LevelOrder();       //层次遍历
private:
    T data[TreeSize];
    //存储结点的元素值,根结点存储在1下标,双亲下标为i,则左右孩子依次为2i,2i+1
};

//constructor
template <class T>
BiTree<T>::BiTree(T *str)
{
   
   
    strcpy(data + 1, str);
}
template <class T>
void BiTree<T>::PreOrder(int pos)
{
   
   
    if (data[pos] != '#')
    {
   
   
        cout << data[pos] << " "; //根
        PreOrder(pos * 2);        //左
        PreOrder(pos * 2 + 1);    //右
    }
} //前序遍历二叉树
template <class T>
void BiTree<T>::InOrder(int pos)
{
   
   
    if (data[pos] != '#')
    {
   
   
        InOrder(pos * 2);         //左
        cout << data[pos] << " "; //根
        InOrder(pos * 2 + 1);     //右
    }
} //中序遍历二叉树
template <class T>
void BiTree<T>::PostOrder(int pos)
{
   
   
    if (data[pos] != '#')
    {
   
   
        PostOrder(pos * 2);       //左
        PostOrder(pos * 2 + 1);   //右
        cout << data[pos] << " "; //根
    }
} //后序遍历二叉树
template <class T>
int BiTree<T>::CountLeaf(int pos)
{
   
   
    if (data[pos] == '#')
    {
   
   
        return 0;
    }
    if (data[pos * 2] == '#' && data[pos * 2 + 1] == '#')
    {
   
   
        return 1;
    }
    return CountLeaf(pos * 2) + CountLeaf(pos * 2 + 1); //递归
} //计算叶子结点总数
template <class T>
int BiTree<T>::Depth(int pos)
{
   
   
    if (data[pos] == '#')
    {
   
   
        return 0;
    }
    return max(Depth(pos * 2), Depth(pos * 2 + 1)) + 1; //比较高度

} //计算高度
template <class T>
void BiTree<T>::PreOrder()
{
   
   
    stack<int> stack;
    stack.push(1);
    while (!stack.empty())
    {
   
   
        int top = stack.top();
        stack.pop();
        cout << data[top] << " "; //根
        if (data[top * 2 + 1] != '#')
        {
   
   
            stack.push(top * 2 + 1); //右
        }
        if (data[top * 2] != '#')
        {
   
   
            stack.push(top * 2); //左
        }
    }
} //非递归先序遍历
template <class T>
void BiTree<T>::LevelOrder()
{
   
   
    queue<int> queue;
    queue.push(1);
    while (!queue.empty())
    {
   
   
        int front = queue.front();
        queue.pop();
        cout << data[front] << " "; //根
        if (data[front * 2] != '#')
        {
   
   
            queue.push(front * 2); //左
        }
        if (data[front * 2 + 1] != '#')
        {
   
   
            queue.push(front * 2 + 1); //右
        }
    }
} //层次遍历

5.2节点实现

template <class T>
struct BiNode //二叉树的结点结构
{
   
   
    T data;
    BiNode<T> *lchild, *rchild;
};
template <class T>
class BiTree
{
   
   
public:
    BiTree();             //构造函数,初始化一棵二叉树,其前序序列由键盘输入
    ~BiTree();            //析构函数,释放二叉链表中各结点的存储空间
    void PreOrder(BiNode<T> *bt);  //前序遍历二叉树
    void InOrder(BiNode<T> *bt);   //中序遍历二叉树
    void PostOrder(BiNode<T> *bt); //后序遍历二叉树
    int CountLeaf(BiNode<T> *a); //递归方法计算叶子数
    int Depth(BiNode<T> *a);     //递归方法计算高度
    void PreOrder(void);   //先序非递归
    void LevelOrder(void); //层次遍历
    void change(BiNode<T> *bt);   //交换左右子树
    BiNode<T> *SearchBST(BiNode<T> *bt, T key); //查找值为k的结点,返回值为k所在结点的地址

private:
    BiNode<T> *root;               //指向根结点的头指针
    void Creat(BiNode<T> *&bt);    //被构造函数调用,递归方式生成二叉树
    void Release(BiNode<T> *&bt);  //被析构函数调用
    
};
//构造函数:Creat利用创建二叉树
template <class T>
BiTree<T>::BiTree()
{
   
   
    Creat(root);
}
//功    能:递归方法创建一棵二叉树,由构造函数调用
template <class T>
void BiTree<T>::Creat(BiNode<T> *&bt)
{
   
   
    T ch;
    cin >> ch;
    if (ch == "#")
        bt = nullptr; //创建结点值为字符串的二叉树
    else
    {
   
   
        bt = new BiNode<T>; //生成一个结点
        bt->data = ch;
        Creat(bt->lchild); //递归建立左子树
        Creat(bt->rchild); //递归建立右子树
    }
}
//功    能:析构函数,释放二叉链表中各结点的存储空间
template <class T>
BiTree<T>::~BiTree() //析构函数不能带参数
{
   
   
    Release(root);
}
//功    能:释放二叉树的存储空间,析构函数调用
template <class T>
void BiTree<T>::Release(BiNode<T> *&bt)
{
   
   
    if (bt != nullptr)
    {
   
   
        Release(bt
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值