zoukankan      html  css  js  c++  java
  • 大话数据结构文摘

    第1章 数据结构绪论

    程序设计=数据结构+算法

    数据结构:是相互之间存在一种或多种特定关系的数据元素的集合

    1.逻辑结构 :是指数据对象中数据元素之间的相互关系

    a:集合结构  b:线性结构  c:树形结构  d:图形结构

    2.物理结构:在计算机中的存储形式

    a: 循序存储  b: 链式存储

    第2章 算法

    算法: 是解决特定问题求解步骤的描述,在计算机中表现为指令的有限序列,并且每条指令表示一个或多个操作

    特性:1.输入输出 2.有穷性 3.确定性 4.可行性

    算法设计的要求:

    1.正确性 2.可读性 3.健壮性 4.时间效率高和存储量低

    算法的时间复杂度:

    推导大O阶方法:

    1. 用常数1取代运行时间中的所有加法常数

    2.在修改后的运行次数函数中,只保留最高阶项

    3.如果最高价项存在且不是1,则去除与这个项相乘的常数

    常数阶:O(1)  ;   线性阶:   O(n) ;  对数阶:O(logn) ;  平方阶: O(n2)

    O(1)  <   O(logn)  <  O(n)   <   O(nlogn)  < O(n2)   <  O(n3)   <   O(2n)  < O(n!)  <  O(nn)

    第3章 线性表

    线性表:零个或多个数据元素的有限序列

    1.顺序存储结构:

    优点 缺点
    无须为表示表中元素之间的逻辑关系而增加额外的存储空间 插入和删除操作需要移动大量元素
    可以快速地存取表中任一位置的元素 当线性表长度变化较大时难以确定存储空间的容量
      造成存储空间的“碎片”

    2.链式存储结构:

    单链表:

    单链表与顺序存储结构作比较:

    存储分配方式 时间性能 空间性能
    顺序存储用一段连续的存储单元依次存储线性表的数据元素 查找:顺序:O(1),单链:O(n)
    单链表采用链式存储结构,用一组任意的存储单元存放线性表的元素 插入删除:顺序:O(n),单链:O(1)

    静态链表:用数组描述的链表

    优点 缺点
    在插入和删除操作时,只需要修改游标,不需要移动元素 没有解决连续存储分配带来的表长难以确定的问题
      失去了顺序存储结构随机存取的特性

    循环链表:将单链表中终端结点的指针由空指针改为指向头结点,就使整个单链表形成一个环,这种头尾相接的单链表称为单循环链表,简称循环链表

    双向链表:在单链表的每个结点中,再设置一个指向其前驱结点的指针域

    第4章 栈与队列

    栈:限定仅在表尾进行插入和删除操作的线性表

    后进先出,(3种元素,就有5种可能的出栈顺序)

    栈的顺序存储结构,进栈,出栈,O(1)

    两栈共享空间

    栈的链式存储结构,0(1)

    斐波那契数列:

    0 ,当n=0

    1,当n=1

    F(n) = F(n-1) + F(n-2),当n>1

    四则运算表达式求值:后缀表达法,(逆波兰)

    -----------------------------------------------------------------

    队列:只允许在一端进行插入操作,而在另一端进行删除操作的线性表

    先进先出

    第5章 串

    由零个或多个字符组成的有限序列,字符串

    朴素的模糊匹配算法:最好:O(n+m),n为主串长度,m为子串长度,最差:O((n-m+1)*m)

    KMP模式匹配算法:O(n+m)

    第6章 树

    完全二叉树

    二叉树遍历方法:1.前序遍历 2.中序遍历 3.后序遍历 4.层序遍历 

    线索二叉树

    赫夫曼树

    第7章 图 

    第8章 查找

    1.静态查找:

    顺序查找:O(n)

    /* 无哨兵顺序查找,a为数组,n为要查找的数组个数,key为要查找的关键字 */
    int Sequential_Search(int *a,int n,int key)
    {
        int i;
        for(i=1;i<=n;i++)
        {
            if (a[i]==key)
                return i;
        }
        return 0;
    }
    /* 有哨兵顺序查找 */
    int Sequential_Search2(int *a,int n,int key)
    {
        int i;
        a[0]=key;
        i=n;
        while(a[i]!=key)
        {
            i--;
        }
        return i;
    }

    有序表查找:

    二分查找:O(logn)/* 折半查找 */

    递归算法

      static int BinarySearch2(int[] a, int value, int low, int high)
            {
                int mid = (low + high) / 2;
                if (a[mid] == value)
                    return mid;
                else if (a[mid] > value)
                    return BinarySearch2(a, value, low, mid);
                else if (a[mid] < value)
                    return BinarySearch2(a, value, mid, high);
                else return 0;
            }

    非递归算法

    int Binary_Search(int *a,int n,int key)
    {
        int low,high,mid;
        low=1;    /* 定义最低下标为记录首位 */
        high=n;    /* 定义最高下标为记录末位 */
        while(low<=high)
        {
            mid=(low+high)/2;    /* 折半 */
            if (key<a[mid])        /* 若查找值比中值小 */
                high=mid-1;        /* 最高下标调整到中位下标小一位 */
            else if (key>a[mid])/* 若查找值比中值大 */
                low=mid+1;        /* 最低下标调整到中位下标大一位 */
            else
            {
                return mid;        /* 若相等则说明mid即为查找到的位置 */
            }
            
        }
        return 0;
    }


    c#版本:

    static int Test(int[] a,int x)
    {
    int low = 0, high = a.Length-1, mid;
    while (low <= high)
    {
    mid = (low + high) / 2;
    if (x < a[mid])
    {
    high = mid - 1;
    }
    else if (x > a[mid])
    {
    low = mid + 1;
    }
    else
    {
    return mid;
    }
    }
    return 0;
    }

     

    插值查找:O(logn)

    /* 插值查找 */
    int Interpolation_Search(int *a,int n,int key)
    {
        int low,high,mid;
        low=1;    /* 定义最低下标为记录首位 */
        high=n;    /* 定义最高下标为记录末位 */
        while(low<=high)
        {
            mid=low+ (high-low)*(key-a[low])/(a[high]-a[low]); /* 插值 */
            if (key<a[mid])        /* 若查找值比插值小 */
                high=mid-1;        /* 最高下标调整到插值下标小一位 */
            else if (key>a[mid])/* 若查找值比插值大 */
                low=mid+1;        /* 最低下标调整到插值下标大一位 */
            else
                return mid;        /* 若相等则说明mid即为查找到的位置 */
        }
        return 0;
    }

    斐波那契查找

    线性索引查找:

    稠密索引,在线性索引中,将数据项的每个记录对应一个索引项。

    分块索引,分块有序的数据集,将每块对应一个索引项。

    倒排索引,由属性值来确定记录的位置。

    2.动态查找:查找时需要插入和删除

    二叉排序树,O(logn)-O(n)

    平衡二叉树(AVL树),(O(logn))

    B树(多路查找树)

    2-3树

    2-3-4树

    B+树

    散列表查找

    直接定址法,数学分析法,平方取中法,折叠法,除留余数法,随机数法

    处理散列冲突的方法:1.开放定址法,2再散列函数法,3.链地址法,4,公共溢出区法

    第9章 排序

    排序
    插入排序类 选择排序类 交换排序类 归并排序类
    直接插入排序 希尔排序 简单选择排序 堆排序 冒泡排序 快速排序 归并排序

    排序方法 平均情况 最好情况 最坏情况 辅助空间 稳定性
     冒泡排序  O(n2)  O(n)  O(n2)  O(1) 稳定
     简单选择排序  O(n2)  O(n2)  O(n2)  O(1) 稳定 
     直接插入排序  O(n2)  O(n)  O(n2)  O(1) 稳定 
     希尔排序  O(nlogn)-O(n2)  O(n1.3)  O(n2)  O(1) 不稳定 
     堆排序  O(nlogn)  O(nlogn)  O(nlogn)  O(1) 不稳定 
     归并排序  O(nlogn)  O(nlogn)  O(nlogn)  O(n) 稳定 
     快速排序  O(nlogn)  O(nlogn)  O(n2)  O(nlogn)-O(n2) 不稳定 

    假设含有n个记录的序列为{r1,r2,.....rn},其对应的关键字分别为{k1,k2...kn},

    需确定1,2,。。。N的一种排列p1,p2,...pn,使其相应的关键字满足kp1<=kp2...<=kpn

    非递减(或非递增)关系,即使得序列成为一个按关键字有序的序列{rp1,rp2...rpn},这样的操作叫做排序

    排序的稳定性

    假设ki=kj,且在排序前的序列中ri领先于rj,如果排序后仍然领先,则是稳定的,反之是不稳定的。

    内排序与外排序

    内排序所有记录放在内存中,外排序需要在内外存之间多次交换数据才能进行。

    冒泡排序:

            int[] array = { };
            void swap(int[] array, int i, int j)
            {
                int temp = array[i];
                array[i] = array[j];
                array[j] = temp;
            }
            ///////////////冒泡排序1///////////
            void bubblesort1(int[] array)
            {
                for (int i = 0; i < array.Length;i++ )
                {
                    for (int j = i + 1; j < array.Length;j++ )
                    {
                        if (array[i] > array [j])
                        {
                            swap(array, i, j);
                        }
                    }
                }
            }
            ///////////////冒泡排序2///////////
            void bubblesort2(int[] array)
            {
                for (int i = 0; i < array.Length; i++)
                {
                    for (int j = array.Length-1; j >=i; j--)
                    {
                        if (array[i] > array[j])
                        {
                            swap(array, i, j);
                        }
                    }
                }
            }
            ///////////////冒泡排序3///////////
            void bubblesort3(int[] array)
            {
                bool flag = true;
                for (int i = 0; i < array.Length && flag; i++)
                {
                    flag = false;
                    for (int j = array.Length - 1; j >= i; j--)
                    {
                        if (array[i] > array[j])
                        {
                            swap(array, i, j);
                            flag = true;
                        }
                    }
                }
            }

    冒泡排序时间复杂度O(n2)

     简单选择排序:

    ////////////简单选择排序//////////
            void selectSort(int[] array)
            {
                int i,j,min;
                for (i = 0; i < array.Length-1; i++ )
                {
                    min = i;
                    for (j = i + 1; j <= array.Length-1;  j++)
                    {
                        if (array[min] > array[j])
                        {
                            min = j;
                        }
                    }
                    if (i != min)
                    {
                        swap(array,i,min);
                    }
                }
            }

    简单选择排序时间复杂度O(n2)

     直接插入排序: 扑克牌

            /// <summary>
            /// //////直接插入排序///////
            /// </summary>
            void insertSort(int[] array)
            {
                int t,i, j;
                for (i = 1; i < array.Length; i++)
                {
                    if (array[i] < array[i - 1])
                    {
                        t = array[i];
                        for (j = i - 1; j >= 0; j--)
                        {
                            array[j + 1] = array[j];
                        }
                        array[j + 1] = t;
                    }
                }
            }

    直接插入排序时间复杂度O(n2)

      希尔排序:

      static void shellSort(int[] array)
            {
                int i, j, temp;
                int increment = array.Length;
                do
                {
                    increment = increment / 3 + 1;
                    for (i = increment; i < array.Length; i++)
                    {
                        if (array[i] < array[i - increment])
                        {
                            temp = array[i];
                            for (j = i - increment; j >= 0 && temp < array[j]; j -= increment)
                            {
                                array[j + increment] = array[j];
                            }
                            array[j + increment] = temp;
                        }
                    }
                }
                while (increment > 1);
            }

    希尔排序时间复杂度O(n3/2)

    不稳定

    堆排序:

    堆是具有下列性质的完全二叉树:

    每个结点的值都大于或等于其左右孩子结点的值,称为大顶堆;

    每个结点的值都小于或等于其左右孩子结点的值,称为小顶堆;

      static void HeapSort(int[] array)
            {
                int i;
                for (i = array.Length / 2 - 1; i >= 0; i--)
                    HeapAdjust(array, i, array.Length - 1);
    
                for (i = array.Length - 1; i >= 1; i--)
                {
                    swap(array, 0, i);
                    HeapAdjust(array, 0, i - 1);
                }
            }
            static void HeapAdjust(int[] array, int i, int m)
            {
                int temp, j;
                temp = array[i];
                for (j = 2 * i; j <= m; j *= 2)
                {
                    if (j < m && array[j] < array[j + 1])
                        ++j;
                    if (temp >= array[j])
                        break;
                    array[i] = array[j];
                    i = j;
                }
                array[i] = temp;
            }

    时间复杂度O(nlogn)

    不稳定

    归并排序:

    时间复杂度O(nlogn)

    稳定

    快速排序:

    原始版本
      static void QuickSort(int[] array, int low, int high)
            {
                int pivot;
                if(low < high)
                {
                    pivot = Partition(array,low,high);
    
                    QuickSort(array, low, pivot - 1);
                    QuickSort(array, pivot + 1, high);
                }
            }
            static int Partition(int[] array, int low, int high)
            {
                int pivotkey = array[low];
                while (low < high)
                {
                    while (low < high && array[high] >= pivotkey)
                        high--;
                    swap(array, low, high);
    
                    while (low < high && array[low] <= pivotkey)
                        low++;
                    swap(array, low, high);
                }
                return low;
            }
    
    

    1 优化选取枢轴

    优化后的快速排序:

         static void QuickSort(int[] array, int low, int high)
            {
                int pivot;
                //优化小数组时的排序方案
                if ((high - low) > 50)
                {
                    //优化递归操作
                    while (low < high)
                    {
                        pivot = Partition(array, low, high);
    
                        QuickSort(array, low, pivot - 1);//对低子表进行递归排序
                        //QuickSort(array, pivot + 1, high);
                        low = pivot + 1;//尾递归
                    }
                }
                //else
                    //直接插入排序                
            }
            static int Partition(int[] array, int low, int high)
            {
                //优化选取枢轴
                int m = low + (high - low) / 2;
                if (array[low] > array[high])
                    swap(array, low, high);
                if (array[m] > array[high])
                    swap(array, m, high);
                if (array[m] > array[low])
                    swap(array, m, low);
    
                int pivotkey = array[low];
                int temp = pivotkey;
                while (low < high)
                {
                    while (low < high && array[high] >= pivotkey)
                        high--;
                    //优化不必要的交换
                    //swap(array, low, high);
                    array[low] = array[high];
                    while (low < high && array[low] <= pivotkey)
                        low++;
                    //优化不必要的交换
                    //swap(array, low, high);
                    array[high] = array[low];
                }
                array[low] = temp;
                return low;
            }

    快速时间复杂度O(nlogn)

    net SDK版本

    void QuickSort(int[] map, int left, int right) {
                do {
                    int i = left;
                    int j = right;
                    int x = map[i + ((j - i) >> 1)];
                    do {
                        while (i < map.Length && CompareKeys(x, map[i]) > 0) i++;
                        while (j >= 0 && CompareKeys(x, map[j]) < 0) j--;
                        if (i > j) break;
                        if (i < j) {
                            int temp = map[i];
                            map[i] = map[j];
                            map[j] = temp;
                        }
                        i++;
                        j--;
                    } while (i <= j);
                    if (j - left <= right - i) {
                        if (left < j) QuickSort(map, left, j);
                        left = i;
                    }
                    else {
                        if (i < right) QuickSort(map, i, right);
                        right = j;
                    }
                } while (left < right);
            }

    不稳定

  • 相关阅读:
    高精度
    SPOJ 3267(DQUERY) D-query 【主席树】【离线树状数组】
    POJ 3225 Help with Intervals 【线段树】
    HDU 4288 Coder 【线段树】
    HDU 1542 Atlantis 【线段树+扫描线】
    Codeforces 732D Exams【二分+贪心】
    HDU 2795 Billboard 【线段树】
    2015-2016 ACM-ICPC, NEERC, Northern Subregional Contest Problem J 【二分+DP+单调队列】
    HDU 5521 Meeting 【拆点+最短路】
    POJ 3255 Roadblocks 【次短路】
  • 原文地址:https://www.cnblogs.com/smileberry/p/2889579.html
Copyright © 2011-2022 走看看