我学《数据结构与算法》 20155314刘子健

我学《数据结构与算法》

我眼中的数据结构

一句话

组织数据的方式

分类

  • 逻辑结构
    • 线性结构(一对一)
    • 非线性结构
      • 集合(无逻辑关系)
      • 树(一对多)
      • 图(网)(多对多)
  • 存储结构物理结构
    • 顺序
    • 链式
    • 散列
    • 索引

整合起来看就是

基本操作

我学过的算法

  • 排序
    • 基于关键字比较
      • 插入排序
      • 快速排序
      • 堆排序
      • 归并排序
    • 不基于关键字比较
      • 计数排序
      • 基数排序
  • 查找
    • 静态
      • 折半查找
    • 动态
      • 散列查找
      • 基于二叉搜索树的查找
  • 遍历
    • 二叉树的遍历
      • 先序遍历
      • 中序遍历
      • 后序遍历
    • 图的遍历
      • 深度优先
      • 广度优先
    • 拓扑排序
  • 优化
    • 按问题组织算法
      • 最优二叉树——Huffman算法
      • 最小生成树
        • Prim算法
        • Kruskal算法
      • 最短路径
        • Dijkstra算法
        • Floyd算法
      • 关键路径
    • 按策略组织算法
      • 贪心算法
      • 动态规划
  • 字符串匹配——KMP算法
  • 经典问题
    • 背包问题
      • 0-1背包问题——动态规划
      • 分数背包问题——贪心策略
    • N皇后问题——回溯法
    • 旅行商问题——动态规划
    • 子集和问题
      • 回溯法
      • 动态规划——转化为0-1背包问题

整合起来看就是

C语言实现

数据结构(存储结构)

  • 线性表
    • 顺序表

        #define LIST_INIT_SIZE 80 //线性表存储空间的初始分配量
        #define LISTINCREMENT 10 //线性表存储空间的分配增量
        typedef int ElemType;
        typedef struct {
            ElemType *elem; //存储空间基址
            int length; //当前长度
            int listsize; //当前分配的存储容量(以sizeof(ElemType)为单位)
        }SqList; //顺序表
      
    • 单链表

        typedef int ElemType;
        typedef struct LNode {
            ElemType data; //数据域
            struct LNode *next; //指针域
        }LNode,*LinkList;
        LinkList L; //L为单链表的头指针
      
  • 栈(先进后出)
    • 顺序栈

        #define STACK_INIT_SIZE 100 //最大栈长度
        typedef int ElemType;
        typedef struct {
            ElemType *base; //栈底指针
            ElemType *top; //栈顶指针
            int stacksize;
        }SqStack;
      
    • 链栈

        #define STACK_INIT_SIZE 100
        typedef int ElemType;
        typedef struct Node {
            ElemType data;
            struct Node *next;
        }*LinkStack;
      
  • 队列(先进先出)
    • 循环队列

        #define MAXQSIZE 100 //最大队列长度
        typedef int ElemType;
        typedef struct {
            ElemType *base; //动态分配存储空间
            int front; //头指针,若队列不空,指向队列头元素
            int rear; //尾指针,若队列不空,指向队列尾元素的下一个位置
            int queuesize;
        }SqQueue;
      
    • 链队列

        typedef int QElemType;
        typedef struct QNode { //结点类型
            QElemType data;
            struct QNode *next;
        }QNode,*QueuePtr;
        typedef struct { //链队列类型
            QueuePtr front; //队头指针
            QueuePtr rear; //队尾指针
        }LinkQueue;
      
    • 二叉链表

        typedef int ElemType;
        typedef struct BiTNode { //结点结构
            ElemType data;
            struct BiTNode *lchild,*rchild; //左右孩子指针
        }BiTNode,*BiTree;
        BiTree T; //二叉链表的根指针
      
    • B树

        #define m 3  // B树的阶,此设为4
        typedef int KeyType;
        typedef struct {
            KeyType key;
            char data;
        }Record;
        typedef struct BTNode {
            int keynum; //结点中关键字个数,结点大小
            struct BTNode *parent; //指向双亲结点的指针
            KeyType key[m+1]; //关键字向量(0号单元不用)
            struct BTNode *ptr[m+1]; //子树指针向量
            Record *recptr[m+1]; //记录指针向量(0号单元不用)
        }BTNode,*BTree; //B树结点和B树的类型
        typedef struct {
            BTNode *pt; //指向找到的结点的指针
            int i; //1..m,在结点中的关键字序号
            int tag; //标志查找成功(=1)或失败(=0)
        } Result; //在B树的查找结果类型
      
    • 邻接矩阵

        #define MAX_VERTEX_NUM 100
        typedef char VertexType;
        typedef int EdgeType;
        typedef enum
        {
            DG,UDG
        }GraphKind;
        typedef struct { //图的定义
            VertexType vexs[MAX_VERTEX_NUM]; //存储顶点信息
            EdgeType arcs[MAX_VERTEX_NUM][MAX_VERTEX_NUM]; //邻接矩阵,存储边的信息
            int vexnum,arcnum; //顶点数,边数
            GraphKind kind; //图的种类标志
        }MGraph;
      
    • 邻接表

        #define MAX_VERTEX_NUM 100
        typedef char VertexType;
        typedef enum
        {
            DG,UDG
        }GraphKind;
        typedef struct ArcNode { //边的结点结构
            int adjvex; //该边所指向的顶点的位置
            struct ArcNode *nextarc; //指向下一条边的指针
        }ArcNode;
        typedef struct VNode { //顶点的顶点结构
            VertexType data; //顶点信息
            ArcNode *firstarc; //指向第一条依附于该顶点的边
        }VNode,AdjList[MAX_VERTEX_NUM];
        typedef struct { //图的定义
            AdjList vertices;
            int vexnum,arcnum; //顶点数,边数
            GraphKind kind; //图的种类标志
        }ALGraph;
      

算法

  • 排序算法

      #include <stdio.h>
      #include <stdlib.h>
      #define N 5
      void BubbleSort(int a[]);
      void SelectionSort(int a[]);
      void InsertionSort(int a[]);
      void QSort(int a[],int s,int t);
      int Partition(int R[],int low,int high);
      void CountingSort(int a[],int k);
      int max(int a[]);
      void HeapSort(int a[]);
      void MaxHeapify(int a[],int s,int m);
      void BuildMaxHeap(int a[]);
      void MergeSort(int a[],int s,int t);
      void Merge(int a[],int i,int m,int n);
      void main()
      {
          int i,j,temp;
          int a[N],b[N];
          printf("请输入%d个整数:",N);
          for(i=0;i<N;i++)
          {
              scanf("%d",&a[i]);
          }
          BubbleSort(a); //冒泡排序
          /*for(i=0;i<N;i++) //冒泡排序
          {
              for(j=0;j<N;j++)
              {
                  if(a[j]>a[j+1])
                  {
                      temp=a[j];
                      a[j]=a[j+1];
                      a[j+1]=temp;
                  }
              }
          }*///冒泡排序
          SelectionSort(a);
          //InsertionSort(a); //插入排序
          /*for(i=0,j=1;i<N,j<N+1;i++,j++) //将下标改为从1开始
          {
              b[j]=a[i];
          }
          QSort(b,1,N);
          for(i=1;i<N+1;i++)
          {
              printf("%d ",b[i]);
          }*/ //快速排序
          //CountingSort(a,max(a)); //计数排序
          //HeapSort(a); //堆排序
          /*for(i=0,j=1;i<N,j<N+1;i++,j++) //将下标改为从1开始
          {
              b[j]=a[i];
          }
          MergeSort(b,1,N);
          for(i=1,j=0;i<N+1,j<N;i++,j++) //将数组下标还原为从0开始
          {
              a[j]=b[i];
          }*/ //归并排序
          for(i=0;i<N;i++)
          {
              printf("%d ",a[i]);
          }
      }
      
      void BubbleSort(int a[]) //冒泡排序
      {
          int i,j,temp;
          for(i=0;i<N-1;i++)
          {
              for(j=i+1;j<N;j++)
              {
                  if(a[i]>a[j])
                  {
                      temp=a[i];
                      a[i]=a[j];
                      a[j]=temp;
                  }
              }
          }
      }
      
      void SelectionSort(int a[]) //选择排序
      {
          int i,j,k,temp;
          for(i=0;i<N-1;i++)
          {
              k=i; //从下标为0处开始记录
              for(j=i+1;j<N;j++)
              {
                  if(a[j]<a[k])
                  {
                      k=j; //记录最小数下标位置
                  }
              }
              if(k!=i) //优化处理:若最小数所在的下标位置不在下标位置i,则交换
              {
                  temp=a[k];
                  a[k]=a[i];
                  a[i]=temp;
              }
          }
      }
      
      void InsertionSort(int a[]) //插入排序
      {
          int i,j,b[N];
          for(i=0,j=1;i<N,j<N+1;i++,j++) //将下标改为从1开始,便于设置监视哨a[0]
          {
              b[j]=a[i];
          }
          for(i=2;i<=N;i++)
          {
              if(b[i]<b[i-1])
              {
                  b[0]=b[i]; //复制为监视哨
                  for(j=i-1;b[0]<b[j];j--)
                  {
                      b[j+1]=b[j];
                  }
                  b[j+1]=b[0];
              }
          }
          for(i=1,j=0;i<N+1,j<N;i++,j++) //将数组下标还原为从0开始
          {
              a[j]=b[i];
          }
      }
      
      void QSort(int a[],int s,int t) //快速排序
      {
          int pivotloc;
          if(s<t-1) //长度大于1
          {
              pivotloc=Partition(a,s,t); //对a[]进行一次划分
              QSort(a,s,pivotloc-1); //对左子序列递归排序,pivotloc是轴位置
              QSort(a,pivotloc+1,t); //对右子序列递归排序
          }
      
      
      }
      int Partition(int R[],int low,int high)
      {
          int pivotkey;
          R[0]=R[low];
          pivotkey=R[low]; //"轴"
          while (low<high)
          {
              while (low<high&&R[high]>=pivotkey)
                  high--;
              R[low]=R[high];
              while (low<high&&R[low]<=pivotkey)
                  ++low;
              R[high]=R[low];
          }
          R[low]=R[0];
          return low;
      }
      
      void CountingSort(int a[],int k) //计数排序
      {
          int i,j;
          int C[N]; //引入索引数组C
          int R[N]; //新建存储数组R
          for(i=0;i<=k;i++)
          {
              C[i]=0; //初始化数组c
          }
          for(i=0;i<N;i++)
          {
              C[a[i]]++; //c[i]中存值等于i的元素个数
          }
          for(i=1;i<=k;i++)
          {
              C[i]=C[i]+C[i-1]; //c[i]中存值小于等于i的元素个数
          }
          for(j=N-1;j>=0;j--)
          {
              R[C[a[j]]]=a[j];
              C[a[j]]--; //下一个值为a[j]的元素被放到a[j]的前一个位置
          }
          for(i=0;i<N;i++)
          {
              a[i]=R[i+1];
          }
      }
      int max(int a[])
      {
          int i;
          int max;
          max = a[0];
          for(i=1;i<N;i++)
          {
              if (max<a[i])
                  max=a[i];
          }
          return max;
      }
      
      void HeapSort(int a[]) //堆排序
      {
          int temp,i;
          BuildMaxHeap(a); //建大顶堆
          for(i=N;i>1;i--)
          {
              temp=a[0];  //将堆顶元素和当前未经排序子序列a[0...i-1]中最后一个元素交换
              a[0]=a[i-1];
              a[i-1]=temp;
              MaxHeapify(a,0,i-2); //调整a[0...i-2]使其成为大顶堆
          }
      }
      void MaxHeapify(int a[],int s,int m) //维护堆的性质
      {
          int rc,j;
          rc=a[s]; //暂存a[s]
          for(j=2*s;j<=m;j*=2)
          {
              if(j<m&&a[j]<a[j+1]) j++; //左右"孩子"之间先进行相互比较,令j指示较大的关键字所在位置
              if(rc>=a[j]) break; //再作"根"和"孩子"之间比较,若">="成立,则说明已找到rc的插入位置s,不需继续向下调整
              a[s]=a[j];
              s=j; //否则关键字上移,仍需继续向下调整
          }
          a[s]=rc; //将调整前的堆顶插入到s位置
      }
      void BuildMaxHeap(int a[]) //建堆
      {
          int i;
          for(i=N/2-1;i>=0;i--)
          {
              MaxHeapify(a,i,N); //建大顶堆
          }
      }
      
      void MergeSort(int a[],int s,int t) //归并排序
      {
          int m;
          if(s<t)
          {
              m=(s+t)/2; //分解
              MergeSort(a,s,m); //解决
              MergeSort(a,m+1,t);
              Merge(a,s,m,t); //合并
          }
      }
      void Merge(int a[],int i,int m,int n) //归并有序序列a[i...m]和a[m+1...n]
      {
          int j,k,p,q;
          int R[N];
          for(j=i;j<=n;j++)
          {
              R[j]=a[j]; //复制
          }
          for(j=m+1,k=i;i<=m&&j<=n;k++)
          {
              if(R[i]<=R[j]) a[k]=R[i++];
              else a[k]=R[j++];
          }
          if(i<=m)
          {
              for(p=i,q=k;p<=m,q<=n;p++,q++)
              {
                  a[q]=R[p];
              }
          }
          if(j<=n)
          {
              for(p=j,q=k;p<=n,q<=n;p++,q++)
              {
                  a[q]=R[p];
              }
          }
      }
    

参考资料

原文地址:https://www.cnblogs.com/crazymosquito/p/7082833.html