精华内容
下载资源
问答
  • ![图片说明](https://img-ask.csdn.net/upload/201708/26/1503755196_260855.jpg) (2)中按行求和是什么意思?
  • List 按层次结构排序

    千次阅读 2013-11-02 21:34:14
    一个List, T 的基本定义如下Data,要求实现按照层次结构排序,即排序结果如下: L1  L1.1  L1.1.1  L1.1.3  L1.2  L1.2.1  L1.2.2  L1.3 L4  L4.1 using System; using System.Collections.Generic;...

    问题描述:

    一个List<T>, T 的基本定义如下Data,要求实现按照层次结构排序,即排序结果如下:

    L1

     L1.1

       L1.1.1

       L1.1.3

     L1.2

       L1.2.1

       L1.2.2

     L1.3

    L4

     L4.1


    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace TestProject
    {
        public class Data
        {
            public Data()
            {
    
            }
    
            public Data(string id ,string parentId,string name)
            {
                Id = id;
                ParentId = parentId;
                Name = name;
                        
            }
    
            public string Id
            {
                get;
                set;
            }
    
            public string Name
            {
                get;
                set;
            }
    
            public string ParentId
            {
                get;
                set;
            }
    
        
    
         
    
        }
    }
    

    一个简单的实现是:通过计算各个list Item的 nodepath 来实现, 为了简单,增加了一个Path属性,如果不想修改原来Data定义,可以投影出一个新的对象来。

    using System;
    using Microsoft.VisualStudio.TestTools.UnitTesting;
    using System.Collections.Generic;
    using System.Linq;
    
    namespace TestProject
    {
        [TestClass]
        public class UnitTest1
        {
            private readonly Random _rng = new Random();
            private const string _chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    
            [TestMethod]
            public void TestMethod1()
            {
                List<Data> list = GenerateData();
                bool allUnique=  list.TrueForAll(p=>list.Count(c=>c.Id ==p.Id)==1  );
                Console.WriteLine("all id unique!");
                list.ForEach(p => GetDept(list, p));
    
                //foreach (var item in list)
                //{
                //    Console.WriteLine("id:{0} name :{2} ,depth:{1}", item.Id, item.Depth,item.Name);
                //}
    
                Console.WriteLine();
                Console.WriteLine("======orginal with node path==============");
    
                var roots = list.FindAll(p => string.IsNullOrEmpty(p.ParentId));
                //计算Node Path
                roots.ForEach(p => CreateNodePath(p, string.Empty, list));
    
                foreach (var item in list)
                {
                    Console.WriteLine("id:{0} ,depth:{1},path ={2} name = {3}", item.Id, item.Depth, item.Path, item.Name);
                }
    
                Console.WriteLine();
                Console.WriteLine("shuffled");
            
                // 把list 以随机顺序排列
                Shuffle<Data>(list);
                foreach (var item in list)
                {
                    Console.WriteLine("id:{0} ,depth:{1},path ={2} name = {3}", item.Id, item.Depth, item.Path, item.Name);
                }
                Console.WriteLine();
                Console.WriteLine("after sort by depth====");
                //按层次排序
                list.Sort((p1, p2) => string.Compare(p1.Path, p2.Path));
    
                foreach (var item in list)
                {
                    Console.WriteLine("id:{0} ,depth:{1},path ={2} name = {3}", item.Id, item.Depth, item.Path, item.Name);
                }
                return;
            }
    
    
            int GetDept(List<Data> list, Data data)
            {
                if (data == null)
                    return -1;
                if (data.ParentId == null)
                {
                    data.Depth = 1;
                    //data.Path = data.Id;
                    //return 1;
                }
                else
                {
                    int depth = GetDept(list, list.FirstOrDefault(p => p.Id == data.ParentId));
                    data.Depth= depth + 1;
                  
                   // data.Path = string.Compare("{0}.1", data.Depth);
                }
                return data.Depth;
            }
    
         
    
            void CreateNodePath(Data rootNode ,string startPath,List<Data> list)  
            {
                rootNode.Path = string.Format("{0}.{1}", startPath, rootNode.Id);
                startPath = rootNode.Path;
                var subnodes = list.FindAll(p => p.ParentId == rootNode.Id);
                foreach (var sub in subnodes)
                {
                    CreateNodePath(sub, startPath, list);
                }
            }
    
    
            List<Data> GenerateData()
            {
    
                var l1 = new Data(RandomString(8), null, RandomString(8) + "(1)");
                var l1_1 = new Data(RandomString(8), l1.Id, RandomString(8) + "(1.1)");
                var l1_2 = new Data(RandomString(8), l1.Id, RandomString(8) + "(1.2)");
    
                ///
                var l2 = new Data(RandomString(8), null, RandomString(8) + "(2)");
                var l2_1 = new Data(RandomString(8), l2.Id, RandomString(8) + "(2.1)");
                var l2_2 = new Data(RandomString(8), l2.Id, RandomString(8) + "(2.2)");
                    var l_2_2_1 = new Data(RandomString(8), l2_2.Id, RandomString(8) + "(2.2.1)");
                    var l_2_2_2= new Data(RandomString(8), l2_2.Id, RandomString(8) + "(2.2.2)");
                var l2_3 = new Data(RandomString(8), l2.Id, RandomString(8) + "(2.3)");
    
                
    
                var l3 = new Data(RandomString(8), null, RandomString(8) + "(3)");
                var l3_1 = new Data(RandomString(8), l3.Id, RandomString(8) + "(3.1)");
    
                var l4 = new Data(RandomString(8), null, RandomString(8) + "(4)");
    
                ///
                var l5 = new Data(RandomString(8), null, RandomString(8) + "(5)");
                var l5_1 = new Data(RandomString(8), l5.Id, RandomString(8) + "(5.1)");
                    var l5_1_1 = new Data(RandomString(8), l5_1.Id, RandomString(8) + "(5.1.1)");
                    var l5_1_2 = new Data(RandomString(8), l5_1.Id, RandomString(8) + "(5.1.2)");
                
                var l5_2 = new Data(RandomString(8), l5.Id, RandomString(8) + "(5.2)");
    
    
    
                var list = new List<Data>
                {
                    l1,
                        l1_1,
                        l1_2
    
                    ,l2,
                        l2_1,
                        l2_2,
                           l_2_2_1,
                           l_2_2_2,
                        l2_3
    
                   , l3
                   ,l3_1,
    
                    l4
    
                    ,l5
                        ,l5_1
                            ,l5_1_1
                            ,l5_1_2
                        ,l5_2
                };
    
    
    
                return list;
    
            }
            private string RandomString(int size)
            {
                char[] buffer = new char[size];
    
                for (int i = 0; i < size; i++)
                {
                    buffer[i] = _chars[_rng.Next(_chars.Length)];
                }
                return new string(buffer);
            }
    
            public static void Shuffle<T>( IList<T> list)
            {
                int n = list.Count;
                Random rnd = new Random();
                while (n > 1)
                {
                    int k = (rnd.Next(0, n) % n);
                    n--;
                    T value = list[k];
                    list[k] = list[n];
                    list[n] = value;
                }
            }
    
        }
    }
    


    结果如下:



    展开全文
  • 快速排序层次改进

    千次阅读 2014-02-15 17:27:17
    1 快速排序划分序列的方法 (1) 第一种 第一种方法,先扫描右边的元素,一旦遇到比t大的元素就将此元素移到最左边,然后再从左边开始,一旦遇到比t大的元素就将此元素放到右边,再从右边…….直到左右交错。最后将t放...

    1 快速排序划分序列的方法

    (1) 第一种

    第一种方法,先扫描右边的元素,一旦遇到比t大的元素就将此元素移到最左边,然后再从左边开始,一旦遇到比t大的元素就将此元素放到右边,再从右边…….直到左右交错。最后将t放到划分位置处。

    while( l < h){
        //Check elements in back
        while(h > l && a[h] >= t){
            --h;
        }
        //The back element which less than the key value
        a[l] = a[h];

        while(l < h && a[l] <= t){
            ++l;
        }
        a[h] = a[l];
    }
    //l = h
    a[l] = temp;

    (2) 第二种Lomuto划分方案

    从左到右扫描,遇见比t小的就和最左大的元素交换,用m作为比t小的最右元素的下标,最后再将t和划分位置(m)元素交换。

    m = l -1
    for i = [l, h]
        if  a[i] < t  // a[i] > t若从大到小排序
            swap(++m, i)
    swap(m, l) //a[l]被选作划分序列的元素即t

    swap()函数用于交换数组中的两个元素。程序中能访问到的a[m]始终是左边最后一个小于于t的数组元素,a[m+1](除a[u+1])是大于t的第一个数组元素。


    (3)第三种 Bob Sedgewick划分方案

    m = h + 1
    for i = [u, l]
        if a[i] >= t
            swap(--m, i)

    程序中能访问到的a[m]是大于等于t最左边的一个元素,a[m-1]是小于t的一个元素。故而循环完毕后,不再需要swap语句。这样就比Lomuto少一个语句。


    在代码优化的层面上,Bob Sedgewick还采用了消除循环内的判别语句的方式让代码再次加速,当然这种加速只限于这个算法被运行的时间比例占据极大的情况下才会显得比较明显

    m = i = h + 1
    do
        while a[--i] < t
            NULL;
        swap(--m, i)
    while i != l

    程序中能访问到的a[m]为大于t的最左一个元素。


    2 特殊输入时改善快速排序

    当待排序列全为相等的元素(某部分为全为相等的序列)和待排序列已经有序时快排的时间复杂度为O(n^2)(当选取第一个元素作为t时)。当序列达到1M时,此时快速排序的时间将会达几个小时,而O(nlogn)处理1M数据是秒级别的。


    (1) 排相等元素

    此时划分序列的代码需要更改如下:

    loop
        do    i++  while  i < h && a[i] < t
        do    j--   while  a[j] > t
        if i > j  break
        swap(i, j)    
    swap(i, j)    //划分完成
    “当前序列”的所有元素相同时,i, j每次都分别增加1和减少1,这样可保证这个序列基本被二分,故而递归处理深度为logn,而函数的复杂度为n,故而这样改写程序后,即便在所有序列元素都相同的情况下,快速排序的时间复杂度都能够有O(nlogn)的保证。在各元素不相同时,swap(i, j)完成左右两边不满足和t关系的元素之间的交换。


    (2) 排有序元素

    因为当待排序列已经有序时,每次都将序列划分为1 和n-1的序列,如此就需要n此划分。结合函数本身的O(n),造就快排的时间复杂度为O(n^2)。


    此时采取t的值为序列中的一个随机值就能够排除序列被n次划分(先将序列打乱,打乱序列没关系,很短时间内就能够恢复),从而又获得快速排序的O(nlogn)复杂度。


    3 总结

    这只是快排的一个例子,它经历了两个层次:

    • 算法本身的改进。
    • 改进算法面对的特殊情况。
    同理对于其它的排序算法及编写的其它程序代码,都应该尝试着按照以上两个层次编写出稳定可运行可通用的程序代码,成为产品级别的程序。


    Small Box Note Over。

    展开全文
  • 今天用connect by来构建一个树结构,结果发现树出来了,但是子节点的顺序却没有按要求排好序,用order by 按序号排...想想oracle应该用提供这种按各层次排序的功能的啊,于是网上搜索一番,真找到了答案,原来要在conn
        今天用connect by来构建一个树结构,结果发现树出来了,但是子节点的顺序却没有按要求排好序,用order by 按序号排了下序,NONONO,把子节点结排到父结点前面来了。想想oracle应该用提供这种按各层次排序的功能的啊,于是网上搜索一番,真找到了答案,原来要在connect by 树里按各层次的顺序排序,应该用order siblings by 来排序,OK,问题解决了。 
    
    展开全文
  • 大话桶排序 基数排序和计数排序

    千次阅读 2015-03-29 15:22:48
    由于用来计数的数组C的长度取决于待排序数组中数据的范围(等于待排序数组的最大值与最小值的差加上1),这使得计数排序对于数据范围很大的数组,需要大量时间内存。例如:计数排序是用来排序0到100之间的数字的...

    (0) 相关排序

    排序 之 归并排序(二路)

    大话快排 和 归排的渊源

    各种排序算法的效率比较(bubblesort,quicksort,insertsort)

    堆排序 之 c 和 c++函数模板(初谈模板类)

    队列优先 之 插入排序实现(插入思想)

    外部排序 之 概念篇

    STL 二分查找三兄弟(lower_bound(),upper_bound(),binary_search())

    二分查找的改进 差值查找(low<=high,这与快排low<high)

    一:计数排序

    (1)当输入的元素是 n 个 0 到 k 之间的整数时,它的运行时间是 Θ(n + k)。计数排序不是比较排序,排序的速度快于任何比较排序算法。由于用来计数的数组C的长度取决于待排序数组中数据的范围(等于待排序数组的最大值与最小值的差加上1),这使得计数排序对于数据范围很大的数组,需要大量时间和内存。例如:计数排序是用来排序0到100之间的数字的最好的算法,但是它不适合按字母顺序排序人名。但是,计数排序可以用在基数排序中的算法来排序数据范围很大的数组。 
    (2)算法的步骤如下:
     1.找出待排序的数组中最大和最小的元素
     2.统计数组中每个值为i的元素出现的次数,存入数组C的第i项
     3.对所有的计数累加(从C中的第一个元素开始,每一项和前一项相加)
     4.反向填充目标数组:将每个元素i放在新数组的第C(i)项,每放一个元素就将C(i)减去1

    (3)代码

    #include <ctime>
    #include <iostream>
    #include <cstdlib>
    #include <cstring>
    
    using namespace std;
    const int NUM_RANGE = 100;
    const int RATE = 10; // 进制
    // output the arr
    void print_arr(const int *arr,const int &n)
    {
    	int i;
    	for(i=0; i<n; i++)
    	{
    		if(!i)
    		{
    			cout << arr[i];
    		}
    		else
    		{
    			cout << " " << arr[i];
    		}
    	}
           printf("\n");
    }
    // 计算最长的位数
    int counting_digits(int *arr,const int &n)
    {
    	int digits = 0;
    	int MyMax = arr[0];
    	int i;
    
    	for(i=1; i!=n; ++i)
    	{
    		if(MyMax < arr[i])
    			MyMax = arr[i];
    	}
    
    	while(MyMax)
    	{
    		++digits;
    		MyMax /= RATE;
    	}
    	return digits;
    
    }
    // sort by counting 计数
    void counting_sort(int *ini_arr,int *sorted_arr,const int &n)
    {
    	//int digits = counting_digits(arr,n); // 用不到的
    	int *count_arr = (int *)malloc(sizeof(int)*NUM_RANGE);// 相当于bitMap统计数量类似
    	int i,j,k;
    	memset(count_arr,0,sizeof(int)*NUM_RANGE);
    
    	for(i=0; i!=n; ++i)
    	{//分别计数
    		count_arr[ini_arr[i]]++;// 以实际的 元素值 为count_arr的下标
    	}
    	for(i=1; i!=NUM_RANGE; ++i)
    	{// 计算排序后的位置
    		count_arr[i] += count_arr[i-1];
    	}
    	for(i=n-1;i>=0;--i)
    	{
    		int index = count_arr[ini_arr[i]]-1;//排序后的下标
    		sorted_arr[index] = ini_arr[i];
    		count_arr[ini_arr[i]]--;// 这是为了处理重复的数据
    	}
    	free(count_arr);
    }
    
    int main(int argc, char *argv[])
    {
    	int n;
    	if(argc < 2)
    	{
    		n = 10;
    	}
    	else
    	{
    		n = atoi(argv[1]);
    	}
    	int i;
    	int *arr = (int *)malloc(sizeof(int)*n);
    	int *sorted_arr = (int *)malloc(sizeof(int)*n);
    	srand(time(0));
    
    	for(i=0; i<n; i++){
    		arr[i] = rand() % NUM_RANGE;
    	}
    	
    	printf("ini_array: ");
    	print_arr(arr, n);
    	counting_sort(arr, sorted_arr, n);
    	printf("sorted_array: ");
    	print_arr(sorted_arr, n);
    	free(arr);
           free(sorted_arr);
    	return 0;
    }

    二:基数排序

    (1)  基数排序
    上面的问题是多关键字的排序,但单关键字也仍然可以使用这种方式。比如字符串“abcd” “aesc” "dwsc" "rews"就可以把每个字符看成一个关键字。另外还有整数 425、321、235、432也可以每个位上的数字为一个关键字。
    基数排序的思想就是将待排数据中的每组关键字依次进行桶分配。比如下面的待排序列:
    278、109、063、930、589、184、505、269、008、083
    我们将每个数值的个位,十位,百位分成三个关键字: 278 -> k1(个位)=8 ,k2(十位)=7 ,k3=(百位)=2。
    然后从最低位个位开始(从最次关键字开始),对所有数据的k1关键字进行桶分配(因为,每个数字都是 0-9的,因此桶大小为10),再依次输出桶中的数据得到下面的序列。
    930、063、083、184、505、278、008、109、589、269
    再对上面的序列接着进行针对k2的桶分配,输出序列为:
    505、008、109、930、063、269、278、083、184、589
    最后针对k3的桶分配,输出序列为:
    008、063、083、109、184、269、278、505、589、930
    (2)  性能分析
    很明显,基数排序的性能比桶排序要略差。每一次关键字的桶分配都需要O(N)的时间复杂度,而且分配之后得到新的关键字序列又需要O(N)的时间复杂度。假如待排数据可以分为d个关键字,则基数排序的时间复杂度将是O(d*2N) ,当然d要远远小于N,因此基本上还是线性级别的。基数排序的空间复杂度为O(N+M),其中M为桶的数量。一般来说N>>M,因此额外空间需要大概N个左右。
    但是,对比桶排序,基数排序每次需要的桶的数量并不多。而且基数排序几乎不需要任何“比较”操作,而桶排序在桶相对较少的情况下,桶内多个数据必须进行基于比较操作的排序。因此,在实际应用中,基数排序的应用范围更加广泛。

    (3)代码

    #include <ctime>
    #include <iostream>
    #include <cstdlib>
    #include <cstring>
    
    using namespace std;
    const int NUM_RANGE = 100;
    const int RATE = 10; // 进制
    // output the arr
    void print_arr(const int *arr,const int &n)
    {
    	int i;
    	for(i=0; i<n; i++)
    	{
    		if(!i)
    		{
    			cout << arr[i];
    		}
    		else
    		{
    			cout << " " << arr[i];
    		}
    	}
    	printf("\n");
    }
    // 计算最长的位数
    int counting_digits(int *arr,const int &n)
    {
    	int digits = 0;
    	int MyMax = arr[0];
    	int i;
    	
    	for(i=1; i!=n; ++i)
    	{
    		if(MyMax < arr[i])
    			MyMax = arr[i];
    	}
    	
    	while(MyMax)
    	{
    		++digits;
    		MyMax /= RATE;
    	}
    	return digits;
    	
    }
    // sort by counting 计数
    void radix_sort(int *ini_arr,const int &n)
    {
    	int digits = counting_digits(ini_arr,n); 
    	int *cnt = (int *)malloc(sizeof(int)*RATE);// 0-9基数的个数啦,进制数
    	int *sorted_arr = (int *)malloc(sizeof(int)*n);
    	int i,j;
    	
    	int divide = 1;
    
    	for(i=0;i!=digits;++i)
    	{
    		memset(cnt,0,sizeof(int)*RATE);
    		for(j=0;j!=n;++j)
    		{// 统计计数
    			sorted_arr[j] = ini_arr[j];
    			int index = (sorted_arr[j]/divide)%RATE;//取某一位作为下标
    			cnt[index]++;
    		}
    
    		for(j=1; j!=RATE; ++j)
    		{
    			cnt[j] += cnt[j-1];// 计算新的排名后的下标
    		}
    		// 非常类似于计数排序,逆序排列
    		for(j=n-1; j>=0; --j)
    		{
    			int index = (sorted_arr[j]/divide)%RATE;//取某一位作为下标
    			ini_arr[cnt[index]-1] = sorted_arr[j];
    			cnt[index]--;// 处理重复数据
    		}
    		divide *= RATE;
    	}
    	
    	free(sorted_arr);
    	free(cnt);
    }
    
    int main(int argc, char *argv[])
    {
    	int n;
    	if(argc < 2)
    	{
    		n = 10;
    	}
    	else
    	{
    		n = atoi(argv[1]);
    	}
    	int i;
    	int *arr = (int *)malloc(sizeof(int)*n);
    	srand(time(0));
    	
    	for(i=0; i<n; i++){
    		arr[i] = rand() % NUM_RANGE;
    	}
    	
    	printf("ini_array: ");
    	print_arr(arr, n);
    	radix_sort(arr, n);
    	printf("sorted_array: ");
    	print_arr(arr, n);
    	free(arr);
    	return 0;
    }


    三:桶排序

    (1)桶排序的基本思想
    假设有一组长度为N的待排关键字序列K[1....n]。首先将这个序列划分成M个的子区间(桶) 。然后基于某种映射函数 ,将待排序列的关键字k映射到第i个桶中(即桶数组B的下标 i) ,那么该关键字k就作为B[i]中的元素(每个桶B[i]都是一组大小为N/M的序列)。接着对每个桶B[i]中的所有元素进行比较排序(可以使用快排)。然后依次枚举输出B[0]....B[M]中的全部内容即是一个有序序列。
    假如待排序列K= {49、 38 、 35、 97 、 76、 73 、 27、 49 }。这些数据全部在1—100之间。因此我们定制10个桶,然后确定映射函数f(k)=k/10。则第一个关键字49将定位到第4个桶中(49/10=4)。依次将所有关键字全部堆入桶中,并在每个非空的桶中进行快速排序。
    (2)桶排序代价分析
    桶排序利用函数的映射关系,减少了几乎所有的比较工作。实际上,桶排序的f(k)值的计算,其作用就相当于快排中划分,已经把大量数据分割成了基本有序的数据块(桶)。然后只需要对桶中的少量数据做先进的比较排序即可。
    对N个关键字进行桶排序的时间复杂度分为两个部分:
    1) 循环计算每个关键字的桶映射函数,这个时间复杂度是O(N)。
    2) 利用先进的比较排序算法对每个桶内的所有数据进行排序,其时间复杂度为 ∑ O(Ni*logNi) 。其中Ni 为第i个桶的数据量。
    很显然,第(2)部分是桶排序性能好坏的决定因素。尽量减少桶内数据的数量是提高效率的唯一办法(因为基于比较排序的最好平均时间复杂度只能达到O(N*logN)了)。因此,我们需要尽量做到下面两点:
    1) 映射函数f(k)能够将N个数据平均的分配到M个桶中,这样每个桶就有[N/M]个数据量。
    2) 尽量的增大桶的数量。极限情况下每个桶只能得到一个数据,这样就完全避开了桶内数据的“比较”排序操作。 当然,做到这一点很不容易,数据量巨大的情况下,f(k)函数会使得桶集合的数量巨大,空间浪费严重。这就是一个时间代价和空间代价的权衡问题了。
    对于N个待排数据,M个桶,平均每个桶[N/M]个数据的桶排序平均时间复杂度为:
    O(N)+O(M*(N/M)*log(N/M))=O(N+N*(logN-logM))=O(N+N*logN-N*logM)
    当N=M时,即极限情况下每个桶只有一个数据时。桶排序的最好效率能够达到O(N)。
    总结: 桶排序的平均时间复杂度为线性的O(N+C),其中C=N*(logN-logM)。如果相对于同样的N,桶数量M越大,其效率越高,最好的时间复杂度达到O(N)。 当然桶排序的空间复杂度 为O(N+M),如果输入数据非常庞大,而桶的数量也非常多,则空间代价无疑是昂贵的。此外,桶排序是稳定的。
    我个人还有一个感受:在查找算法中,基于比较的查找算法最好的时间复杂度也是O(logN)。比如折半查找、平衡二叉树、红黑树等。但是Hash表却有O(C)线性级别的查找效率(不冲突情况下查找效率达到O(1))。大家好好体会一下:Hash表的思想和桶排序是不是有一曲同工之妙呢?
     参考自 :http://blog.csdn.net/quietwave/article/details/8008572   http://www.cnblogs.com/hxsyl/p/3214379.html

    (3)代码

    #include <ctime>
    #include <iostream>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    
    using namespace std;
    const int NUM_RANGE = 100;
    const int RATE = 10; // 进制
    struct Node
    {
    	int data;
    	struct Node *next;
    };
    // output the arr
    void print_arr(const int *arr,const int &n)
    {
    	int i;
    	for(i=0; i<n; i++)
    	{
    		if(!i)
    		{
    			cout << arr[i];
    		}
    		else
    		{
    			cout << " " << arr[i];
    		}
    	}
    	printf("\n");
    }
    
    void destory(Node arr[])
    {
    	;
    }
    // sort by counting 计数
    void bucket_sort(int *ini_arr,const int &n)
    {
    	int i,j;
    	Node *t_node,*cur_node;
    	Node *arr = (Node *)malloc(sizeof(Node)*n);
    
    	for(i=0;i!=n;++i)
    	{
    		arr[i].data = -1;
    		arr[i].next = NULL;
    	}
    	
    	//划分桶并填元素
    	for(i=0;i!=n;++i)
    	{
    		int tmp = (int)floor(ini_arr[i]/10);
    		if(NULL == arr[tmp].next)
    		{
    			//cout << "test" << endl;
    			t_node = (Node *)malloc(sizeof(Node));
    			t_node->data = ini_arr[i];
    			t_node->next = NULL;
    			arr[tmp].next = t_node;
    		}
    		else// 插入排序
    		{
    			
    			if(arr[tmp].next->data >= ini_arr[i])
    			{
    				t_node = (Node *)malloc(sizeof(Node));
    				t_node->data = ini_arr[i];
    				t_node->next = arr[tmp].next;
    				arr[tmp].next = t_node;
    			}
    			cur_node = arr[tmp].next;// cur_node已经比较过 了
    
    			while(cur_node->next)// 从arr[tmp].next开始
    			{
    				if(cur_node->next->data < ini_arr[i])
    				{
    					cur_node = cur_node->next;
    				}
    				else
    				{
    					t_node = (Node *)malloc(sizeof(Node));
    					t_node->data = ini_arr[i];
    					t_node->next = cur_node->next;
    					cur_node->next = t_node;
    					break;// 插入了
    				}
    			}// while到了尾巴
    			if(NULL == cur_node->next)
    			{
    				t_node = (Node *)malloc(sizeof(Node));
    				t_node->data = ini_arr[i];
    				t_node->next = NULL;
    				cur_node->next = t_node;
    			}
    			
    		}// end else
    	}// end for
    	 // 排序后的结果
    	for(i=0;i!=n;++i)
    	{
    		int j = 0;
    		cur_node = arr[i].next;// 从arr[tmp].next开始
    		while(cur_node)// 从arr[tmp].next开始
    		{
    			ini_arr[j++] = cur_node->data;
    			cur_node = cur_node->next;
    		}// 到了尾巴
    		
    	}
    	destory(arr);
    }
    
    int main(int argc, char *argv[])
    {
    	int n;
    	if(argc < 2)
    	{
    		n = 10;
    	}
    	else
    	{
    		n = atoi(argv[1]);
    	}
    	int i;
    	int *arr = (int *)malloc(sizeof(int)*n);
    	srand(time(0));
    	
    	for(i=0; i<n; i++){
    		arr[i] = rand() % NUM_RANGE;
    	}
    	
    	printf("ini_array: ");
    	print_arr(arr, n);
    	bucket_sort(arr, n);
    	printf("sorted_array: ");
    	print_arr(arr, n);
    	free(arr);
    	return 0;
    }

    四:草图分析

    (1)基数排序


    五:美文分享

    题记

    今天发现要学的东西好多啊,自己学得又慢,快没信心了。转一篇文章,激励下自己,重要是掌握好学习方法。

    也可以参考我之前的一篇文章 http://blog.csdn.net/whuslei/article/details/6661435 。

    以下是原文,原始链接:http://blog.csdn.net/heiyeshuwu/article/details/6920880


    一、想学的技术非常多怎么办?

    区分重点,选定目标,循序渐进。技术是无边际的,随着知识的不断增加,会发现未知的东西更多。我们能做的是:

    1、找重点:区分感兴趣的技能和必须技能,将重点放在必须技能上。如实在区分不开,可以这样问自己:不学这个技术会现在的工作是不是干不下去了?(必要技能和感兴趣的技能,不学此技能是不是就把自己的饭碗给砸了?)

    2、定目标:在一段时间(至少半年)选定一个方向,深精下去(选定一个方向,至少研究半年,否则就像习武,半途而废,切记,切记!!!)

    3、不断向前:当某一种技术掌握之后,再开始另一门技术的研究

    4、找圈子:找一个适合自己的圈子,讨论问题的朋友、博友、qq好友、室友等。(技术blog,关注大牛的blog,找技术大牛请教问题,找同一层次的人讨论问题,技术的路上,是孤独的,所以一定要有自己的圈子)

    5、360行,行行出状元;万事开头难……需要找一个带路者。。。

    6、独立解决问题:相信每一程序员,最兴奋的时刻,是查找了3天的bug终于找到,并解决了。因此,一定要有自己独立思考、独立研究、独立解决问题的时间,一定要保持这种兴奋。

    二、想学技术,但目前项目工作太多,没时间展开,一直拖着,怎么办?

    生存状况和工作性质注定了我们不能像在学校和外企那样有大把的可支配时间,所以要追求技术进步只能自己找时间,也即"白天求生存,晚上谋发展"的道理,我一般会将晚上和周末的时间拿出一部分用来学习。(还是那句古话:时间就像海绵里的水,……生存的竞争和工作的任务要平衡好,不管有多么忙,多么的没有时间,总该一周抽出一段空闲的时间,总结一下,并坚持下去。)

    三、选定一个技术方向后该如何展开?

    学习一门技术一般分为三个阶段:入门>掌握>精通。一般情况下达到熟练程度即可,要实现至少需要一年的积累

    可以分下面几步:

    1、知其然:了解该技术的基本原理和应用场景,并进行简单的实践。这个阶段,官方文档是最好的教材;

    2、站在巨人的肩膀上:找该技术业界成熟的开源类库和应用系统进行学习,精读源代码

    3、在问答中进步:去相关论坛学习,提问或者回答问题,并尝试独立解决论坛中已有问题,www.stackoverflow.com是最好的选择。

    4、躬身而行:实践相关技术,达到能独立完成中等规模应用的程度;

    5、知其所以然:深入了解该技术的运行机制、周边技术、性能优化、深度知识等;

    6、善用资源:在公司,高手很多,你想了解的任何一门技术,差不多都能找到相应的牛人,多和这些人沟通,会事半功倍。

    以PHP为例:
    熟悉语法&api-> 阅读zend、ci、wordpress源码 -> 用PHP独立开发项目 -> 深入了解PHP引擎实现细节、扩展编写、性能优化等

    四、外界干扰太多,静不下心来学习,怎么办?

    刚来百度的时候,前辈给过我一个建议:关掉QQ(注:我觉得有些时候应该关掉浏览器!!^_^),结合在学校时的体会,我深知这个建议的重要性,欣然接受了。其实,静心是做好任何事的前提,关掉QQ只是一个表象,最本质的是我们要给自己营造一个好的学习环境。做技术需要一个安静的环境和一套方法论,方法论可以找到很多(论语第一篇讲的最好),环境必须我们自己营造。所以我的建议是:忘掉QQ、适度娱乐,努力使自己沉迷到工作和学习中。虽然不太容易做到,但做到了对提高效率、找出学习时间都很有帮助。

    一些复杂的技术会涉及很多方向,每个方向也可以按照上边的方式分解。技术学习可以触类旁通,当你完全吃透一门技术的时候,其它的再学起来就快了;

    以上内容归根结底就是要我们:懂得选择,学会放弃,耐得住寂寞,经得起诱惑。

    做技术如同做学问,关于如何做学问,王国维有段话我高中以来一直非常喜欢:

    古今之成大事业、大学问者,罔不经过三种之境界:“昨夜西风凋碧树。独上高楼,望尽天涯路。”此第一境界也。“衣带渐宽终不悔,为伊消得人憔悴。”此第二境界也。“众里寻他千百度,蓦然回首,那人却在灯火阑珊处。”此第三境界也。

     

    今天有点小郁闷,本来好不容易把webx的基本流程熟悉了,但是突然被告知改用SpringMVC模式。虽然思想上差不多,但是用法上还是有差异的,特别是Spring2以后采用了annotation。纠结的地方来了!一知半解,心里真不踏实啊!人们不是常说,"知道了怎么做,还需要知道为什么这么做!"。所以就想到一个问题,面对新的知识,我们应该怎么去学习?

        第一反应,Google or Baidu ?不错,很多人第一选择应该就是这个。但是结果是好坏各一半吧网上的资源,很多都是带你入门的,比如一些小实例啊,贴些代码解释下呀,写得好的文章就稍微顺带讲点原理啊!开始接触新的东西,确实需要一些实例去理解,实践。但是是不是这样就够了?

        不一定!对于一些工具的用法,如SVN之类的,可以参考一些网上的文章,知道怎么用,以及用了之后会出现什么后果就可以了。但是像Spring这种成熟的框架,想在网上找两篇文章就想理解它?很难!!特别是理解它的思想!这个时候,我觉得理智的做法是去搜下有什么相关的好书!成熟的技术,一般都有很多经典的书,真的需要耐心去读读看。第一遍不懂,没关系。实践之后,做几个小例子后再看,你会有意想不到的收获!

        看完之后,最好对照自己的例子,或者参考网上的文章,将自己对这些技术的想法写下来,一方面,检验下自己是否真的明白了;另一方面,也许可以帮助到别人!时间长了,对自己也很有帮助。

        写这篇文章的目的,一是理清下思路,我写东西的时候心很静,我很喜欢这种感觉;二是希望可以和大家分享下我的个人理解。

      【注意】本文的标题起的不太好,没有真的告诉你怎么去学,只是表达了一些个人关于学习方面的理解,如有不对,虚心接受意见。



    展开全文
  • **算法思想:**求指定结点的层次也就是求指定结点的高度,理论上来说有好几种方法,可以类比二叉树求高度的算传送门进行改造,或者直接根据二叉排序树的查找来直接计算,下面给出直接根据二叉排序树查找直接计算的...
  • 排序算法复杂度 iostream继承层次

    千次阅读 2011-04-10 14:30:00
    几种排序算法的时间、空间复杂度: <br /> 像你这样出色的男人,无论在什么地方,都像黑夜中的萤火虫一样,那样的鲜明,那样的出众。你那忧郁的眼神,稀疏的胡茬子,神乎其神的刀法,太阳啊~
  • 排序(1)--插入排序和交换排序

    千次阅读 2014-02-23 11:14:54
    首先引入几个概念:  内部排序:整个排序过程不需要访问外... 稳定性不稳定性: 设 Ki、Kj (1≤i≤n, 1≤j≤n, i≠j ) 分别为记录 Ri、Rj 的关键字,且 Ki = Kj ,在排序前的序列中 Ri 领先于 Rj (即 i 一.
  • 层次查询中,如果想让“亲兄弟”按规矩进行升序排序就不得不借助ORDERSIBLINGS BY这个特定的排序语句,若要降序输出可以在其后添加DESC关键字。 通过这个实验给大家展示一下这个“亲兄弟”间的排序功能。 1....
  • 有个朋友今天问我数据库方面的问题,建议我把一些经验共享出来,才动手写此贴》数据层次是在表达数据的一种重要关系。 在数据库设计中,如:组织结构分解、工作任务分解、行政区划的分解等都是层次关系数据的典型...
  • 数据层次的概念: 数据层次是表达数据的一种重要关系,在数据库的设计中,如:组织结构分解、工作任务分解、行政区划的分解等都是层次关系数据的典型实例。 表达层次关系的数据一般需要实现如下属性:   ...
  • 二叉排序树的建立各种遍历方法 二叉排序树的定义: 二叉排序树或者是一棵空树,或者是具有下列性质的二叉树: (1)若左子树不空,则左子树上所有结点的值均小于它的根结点的值; (2)若右子树不空,则右子树...
  • 在二叉排序树中查找节点,每查找一次,层次就+1,因此判断指定节点在二叉树中的层次,只需要看进行了几次非递归查找操作。 有了这个思路之后代码就非常简单啦~ int search_1(btree T, int a) { while (T!=...
  • 快速排序

    千次阅读 2016-03-16 20:28:34
    针对冒泡排序我们进行一次优化,就引进了快速排序在此基础上进行优化基本思想: 任取一个记录(如第一个)作为 枢轴或支点,设其关键字为pivotkey。...具体操作(1)附设两个指针lowhigh,初始时分别指向
  • 归并排序算法的编码优化

    千次阅读 2017-12-02 10:39:21
    在大型公司的面试过程中,排序是必问的知识。本篇内容来自《算法(第4版)》 — — Robert Sedgewick, Kevin Wayne概念归并排序的实现我是这样来描述的:先对少数几个元素通过两两合并的方式进行排序,形成一个长度...
  • 快速排序也是用到了分治思想递归实现方式,这一点跟归并排序是一样的,但是快速排序的实现跟归并是完全不一样的。 归并排序是先分解再合并,从下到上解决问题。 快速排序是从上到下进行分区实现排序。俯视这个...
  • 在Oracle层次查询中给SIBLINGS排序

    千次阅读 2007-05-29 14:22:00
    SELECT last_name, employee_id, manager_id, LEVELFROM employeesSTART WITH employee_id = 100CONNECT BY PRIOR employee_id = manager_idORDER SIBLINGS BY last_name; 
  • 代码出自雨松MOMO的Blog。
  • C++实现直接插入排序,折半插入排序,希尔排序,冒泡排序,简单选择排序,快速排序,堆排序。 如有不足之处,还望指正!  [cpp] view plaincopy // Sort.cpp : 定义控制台应用程序的...
  • (1)用于分区排序 (2)动态Group By (3)Top N (4)累计计算 (5)层次查询 Hive分析窗口函数(一) SUM,AVG,MIN,MAX Hive中提供了越来越多的分析函数,用于完成负责的统计分析。抽时间将所有的分析窗口函数理一...
  • 归并排序、堆排序、计数排序、桶排序、基数排序
  • 常用内部排序算法之二:快速排序

    千次阅读 2015-12-01 20:51:11
    前言快速排序可以说是内部排序算法中的高手,之所以称为快速排序,是因为快速排序算法从整体性能上讲是排序冠军。快速排序算法的思想是:通过一趟快速排序将待排序的记录分割成独立的两部分,其中一部分记录的关键字...
  • 排序算法七:选择排序之堆排序

    千次阅读 2015-09-26 11:37:09
    排序算法七:选择排序之堆排序声明:引用请注明出处http://blog.csdn.net/lg1259156776/引言在我的博文《...上博文讲述了选择排序中的简单排序算法,本文介绍的堆排序是树性选择排序,采用堆这个数据结构来辅助排序
  • 对许多问题,比如排序或计算离散傅里叶变换最自然的量度是输入中的项数,例如带排序数组的规模n。对许多其他问题,比如两个整数相乘,输入规模的最佳量度是用通常的二进制记号表示输入所需的位数。
  •  插入排序是在这里的实现是从有序数组的最后一个元素来进行比较插入,当然这里也可以从第一个元素来进行比较插入操作。  归并元素是基于2分法来进行分拆、排序归并的。  代码如下: import java.util.Arrays;...
  • 排序——基于C++ STL的排序

    千次阅读 2020-02-11 20:42:57
    概述 前面我们介绍了十种排序算法。在实际使用中,我们需要在每道 OI 题目中完成排序算法的具体实现。...STL中的sort不是普通的快排,除了对普通的快速排序进行优化,它还结合了插入排序和排序。根据不同的数量级...
  • 看过了很多介绍指令重排序的文章,可惜由于自己硬件计算机理论知识缺乏,很难理解深层次的奥秘实现原理。不过也有很多帖子,讲的浅显易懂,使用的例子很形象。大牛就是能用简单的解释通俗的比喻,给我们讲明白...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 141,632
精华内容 56,652
关键字:

层次单排序和层次总排序