Reverse a Singly Linked List without using Recursion.
///
/// Revert a single linked list
///
///a single linked list
///
public static SingleLinkedListNode Reverse(SingleLinkedListNode root) {
if (root == null)
throw new ArgumentNullException("root");
SingleLinkedListNode iter = root, next = root.Next;
SingleLinkedListNode newRoot = root;
root.Next = null;
while (next != null)
{
newRoot = next.Next;
next.Next = iter;
iter = next;
next = newRoot;
}
return iter;
}
Reverse a Singly Linked List with using Recursion.
编程找出N以下的所有素数
void findPrimes(bignum topCandidate)
{
bignum candidate = 2;
while(candidate <= topCandidate)
{
bignum trialDivisor = 2;
int prime = 1;
while(trialDivisor * trialDivisor <= candidate)
{
if(candidate % trialDivisor == 0)
{
prime = 0;
break;
}
trialDivisor++;
}
if(prime) printPrime(candidate);
candidate++;
}
}
Reverse every word in a String (abc def becomes cba fed).
1. private static string ReverseStringByWord(string input)
2. {
3. if (string.IsNullOrEmpty(input))
4. throw new ArgumentNullException("input");
5.
6. char[] sb = new char[input.Length];
7. int lastIndex = input.Length;
8. while ((lastIndex > 0) && char.IsWhiteSpace(input[lastIndex - 1])) lastIndex--;
9.
10. int appendIndex = 0;
11. for (int i = lastIndex - 1; i >= 0; i--)
12. {
13. char c = input[i];
14. // if (char.IsWhiteSpace(input[i]))
15. if ( c == ' ' || c == '\t' || c == '\n' || c == '\r' )
16. {
17. for (int j = i + 1; j < lastIndex; ++j)
18. sb[appendIndex++] = input[j];
19.
20. sb[appendIndex++] = input[i];
21. lastIndex = i;
22. }
23. }
24.
25. for (int j = 0; j < lastIndex; ++j)
26. sb[appendIndex++] = input[j];
27.
28. return new string(sb);
29. }
Write a function that takes in a string parameter and checks to see whether or not it is an integer, and if it is then return the integer value.
1. public static int Parse(string args)
2. {
3. // Author: Yimin Shi. 2008-05-30
4. // 这个函数也有一个BUG, 比如在处理字符串 "-5147483648"时候,就不会throw OverflowException.
5. if (string.IsNullOrEmpty(args))
6. throw new ArgumentNullException("args");
7.
8. int iter = 0;
9. bool bNegative = false;
10. int result = 0;
11. // Skip whites
12. while (iter < args.Length && (args[iter] == ' ')) iter++;
13.
14. if (args[iter] == '-')
15. {
16. bNegative = true;
17. iter++;
18. }
19. else if (args[iter] == '+')
20. iter++;
21.
22. for (; iter < args.Length; ++iter)
23. {
24. if (args[iter] >= '0' && args[iter] <= '9')
25. {
26. int cur = args[iter] - '0';
32.
33. checked(result *= 10);
34.
35. result = bNegative ? result - cur
36. : result + cur;
42. }
43. else
44. break;
45. }
46.
47. // Skip whites
48. while (iter < args.Length && (args[iter] == ' ')) iter++;
49. if (iter != args.Length)
50. throw new ArgumentException();
51.
52. return result;
53. }
Implement strstr() (or some other string library function).
char * __cdecl strstr (
const char * str1,
const char * str2
)
{
char *cp = (char *) str1;
char *s1, *s2;
if ( !*str2 )
return((char *)str1);
while (*cp)
{
s1 = cp;
s2 = (char *) str2;
while ( *s1 && *s2 && !(*s1-*s2) )
s1++, s2++;
if (!*s2)
return(cp);
cp++;
}
return(NULL);
}
Implement an algorithm to print out all files below a given root node. public abstract class AbstractGraph : AbstractContainer, Graph
{
protected int numberOfVertices;
protected int numberOfEdges;
protected Vertex[] vertex;
public void BreadthFirstTraversal(
Visitor visitor, int start)
{
bool[] enqueued = new bool[numberOfVertices];
for (int v = 0; v < numberOfVertices; ++v)
enqueued[v] = false;
Queue queue = new QueueAsLinkedList();
queue.Enqueue(vertex[start]);
enqueued[start] = true;
while (!queue.IsEmpty && !visitor.IsDone)
{
Vertex v = (Vertex)queue.Dequeue();
visitor.Visit(v);
foreach (Vertex to in v.Successors)
{
if (!enqueued[to.Number])
{
queue.Enqueue(to);
enqueued[to.Number] = true;
}
}
}
}
}
现有一单链表,输出从尾端开始的第5个数值,并写出相应的测试用例
Given two linked lists which have data in ascending order, how would you merge them
///
/// Merge two sorted linked list in sorted order
///
///the first sorted linked list
///the second sorted linked list
///
/// The result sorted linked list
///
/// For e.g.
///
SingleLinkedListNode.PrintLinkedList(SingleLinkedListNode.OrderedMerge(SingleLinkedLis tNode.InitializeTestList(new int[] { 1, 2, 4, 5, 6, 7, 8, 9 }),
SingleLinkedListNode.InitializeTestList(new int[] { 3, 6, 8, 9, 10 })));
/// - returns -
/// 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 6 -> 7 -> 8 -> 8 -> 9 -> 9 -> 10 ->
///
///
SingleLinkedListNode.PrintLinkedList(SingleLinkedListNode.OrderedMerge(SingleLinkedLis tNode.InitializeTestList(new int[] { 1, 2, 4, 5, 7 }),
SingleLinkedListNode.InitializeTestList(new int[] { 3, 6, 8, 9, 10 })));
/// - returns -
/// 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10 ->
///
public static SingleLinkedListNode OrderedMerge(SingleLinkedListNode first, SingleLinkedListNode second)
{
if (first == null)
throw new ArgumentNullException("first");
if (second == null)
throw new ArgumentNullException("second");
SingleLinkedListNode less = first.Value < second.Value ? first : second;
SingleLinkedListNode larger = first.Value > second.Value ? first : second;
SingleLinkedListNode newRoot = less;
SingleLinkedListNode iter = newRoot;
less = less.Next;
while (less != null && larger != null)
{
if (less.Value < larger.Value)
{
iter.Next = less;
less = less.Next;
}
else
{
iter.Next = larger;
larger = larger.Next;
}
iter = iter.Next;
}
while (less != null)
{
iter = iter.Next = less;
less = less.Next;
}
while (larger != null)
{
iter = iter.Next = larger;
larger = larger.Next;
}
return newRoot;
}
Implement an algorithm to do wild card string matching.
1. private static bool WildCardMatch(string pattern, string input)
2. {
3. if (string.IsNullOrEmpty(pattern))
4. throw new ArgumentNullException("pattern");
5. if (string.IsNullOrEmpty(input))
6. throw new ArgumentNullException("input");
7.
8. int inputIter = 0;
9. int patternIter = 0;
10. for (; patternIter < pattern.Length; ++patternIter)
11. {
12. if (pattern[patternIter] == '*')
13. {
14. while ((patternIter < pattern.Length - 1) && (pattern[patternIter + 1] == '*')) patternIter++;
15. if (patternIter == pattern.Length - 1)
16. return true;
17.
18. while ((patternIter < pattern.Length) &&
19. (inputIter < input.Length) &&
20. (pattern[patternIter + 1] !=
input[inputIter]))
21. {
22. inputIter++;
23. }
24. }
25. else
26. {
27. if (inputIter >= input.Length) break;
28.
29. if (pattern[patternIter] != input[inputIter++])
30. return false;
31. }
32. }
33.
34. return patternIter == pattern.Length && inputIter ==
input.Length;
35. }
Write a routine that prints out a 2-D array in spiral order!
int
left=0,top=0,right=3,bottom=3,CurrentRow=0,CurrentCulom=0,step;
int[,] Num = new int[,] { { 1, 2, 3,4 }, { 5, 6 ,7,8},
{ 9,10,11,12 }, { 13,14,15,16 } };
//rule define:{X,Y},if X=0,traversal colum,if X=1,traversal
row;if Y=1,increase by degrees,if Y=-1,decrease by degrees
//int[,] rule = new int[,] { { 1, 1 }, { 0, 1 }, { 1, -1 }, { 0, -1 } };//clockwise
int[,] rule = new int[,] { { 0, 1 }, { 1, 1 }, { 0, -1 }, { 1, -
1 } }; //counter-clockwise
int a = Num.Rank;
int b = Num.Length;
int process=0;
while (true)
{
switch (rule[process, 0])
{
case 1://row
step = rule[process, 1];
for (; CurrentCulom >= left && CurrentCulom <= right; CurrentCulom += step)
{
Console.WriteLine(Num[CurrentRow, CurrentCulom]); }
CurrentCulom -= step;
if (CurrentRow == top)
{
top++;
CurrentRow++;
}
else
{
bottom--;
CurrentRow--;
}
break;
case 0://colum
step = rule[process, 1];
for (; CurrentRow >= top && CurrentRow <= bottom; CurrentRow += step)
{
Console.WriteLine(Num[CurrentRow, CurrentCulom]);
}
CurrentRow -= step;
if (CurrentCulom == left)
{
CurrentCulom++;
left++;
}
else
{
CurrentCulom--;
right--;
}
break;
}
if (top > bottom || left > right)
break;
process =( process + 1) % 4;
}
}
Implement a string.Replace.
1. public static string Replace(string strSrc, string oldStr, string newStr)
2. {//Implement a string.Replace.
3.
4. if (string.IsNullOrEmpty(strSrc) || string.IsNullOrEmpty(oldStr) || newStr == null)
5. throw new ArgumentNullException("string is null or empty.");
6.
7. string strResult = "";
8. int lenSrc = strSrc.Length;
9. int lenOld = oldStr.Length;
10. for (int i = 0; i <= lenSrc - lenOld; )
11. {
12. bool flag = false;
13. int indexOld = 0;
14. while (indexOld < lenOld)
15. {
16. if (strSrc[i + indexOld] != oldStr[indexOld])
17. break;
18. else
19. indexOld++;
20. }
21. if (indexOld == lenOld) flag = true;
22.
23. if ( flag/*strSrc.Substring(i, lenOld) == oldStr*/)
24. {
25. strResult += newStr;
26. i += lenOld;
27. }
28. else
29. {
30. strResult += strSrc[i];
31. i++;
32. }
33. }
34.
35. return strResult;
36. }
Count the number of set bits in a number. Now optimize for speed. Now optimize for size.
///
/// Given any integer, return the count of 1 in its binary representation.
///
/// any integer
///
/// The count of 1 in its binary representation, for e.g.
///
/// GetBitCount(3) returns 2, because 3's binary reprenstation is 11.
/// GetBitCount(2) returns 1, because 2's binary reprenstation is 10.
///
1. private static int GetBitCount(int value)
2. {
3. int iter = 1;
4. int count = 0;
5.
6. for (int i = 0; i < 32; ++i)
7. {
8. if ((value & iter) != 0)
9. count++;
10.
11. iter <<= 1;
12. }
13.
14. return count;
15. }
Implement an algorithm to sort a linked list. Why did you pick the method you did? Now do it in O(n) time.
1. typedef struct LinkedList
2. {
3. int Value;
4. struct LinkedList *Next;
5. } LINKLIST, *LPLINKLIST;
6.
7. LPLINKLIST InsertionSortLinkedList(LPLINKLIST lpList)
8. {
9. if ( lpList == NULL ) return NULL;
10.
11. LPLINKLIST lpHead = lpList;
12. LPLINKLIST lpIter = lpList->Next;
13.
14. lpHead->Next = NULL;
15. while ( lpIter != NULL )
16. {
17. LPLINKLIST lpNext = lpIter->Next;
18. lpIter->Next = NULL;
19. LPLINKLIST lpPrev = NULL;
20.
21. bool bInserted = false;
22. for ( LPLINKLIST lpI = lpHead;
23. lpI != NULL;
24. lpPrev = lpI, lpI = lpI->Next )
25. {
26. if ( lpIter->Value < lpI->Value )
27. {
28. lpIter->Next = lpI;
29. if ( lpPrev == NULL )
30. lpHead = lpIter;
31. else
32. lpPrev->Next = lpIter;
33.
34. bInserted = true;
35. break;
36. }
37. }
38.
39. if ( !bInserted )
40. lpPrev->Next = lpIter;
41.
42. lpIter = lpNext;
43. }
44.
45. return lpHead;
46. }
Write a function to print the Fibonacci numbers.
int fib ( int n )
{
if (n == 0) return 1;
else return fib(n-1) + fib(n-2);
}
int fibo (int n)
{
int i, current, one_back, two_back;
if (n <= 1)
return 1;
else {
one_back = 1;
two_back = 1;
for ( i = 2; i <= n; i++) {
current = one_back + two_back;
one_back = two_back;
two_back = current;
} /* end for loop */
} /* end else block */
return current;
}
有一个有序数组,其中可能包含重复的元素,去除其重复的部分返回数组的长度。如一个数组包含:1,3,7,7,8,9,9,9,10,运行后应当为1,3,7,8,9,10,返回长度6。
private static int CountAfterRemoveDups(int[] data)
{
if ( data == null ) throw new ArgumentNullException("data");
if ( data.Length == 0 ) return 0;
int result = 1;
int lastNondup = data[0];
for ( int i = 1; i < data.Length; ++i )
{
if ( data[i] != lastNondup )
{
result++;
lastNondup = data[i];
}
}
return result;
}
将一个字符串中的整数输出(比如“14ab5eer87”,应该输出“14,5,87”)。易犯的错误:没有分组输出,即输出为14587了。
private static string PrintGroup(string data)
{
if ( data == null ) throw new ArgumentNullException("data");
char[] result = new char[data.Length];
int resultIter = 0;
bool doGroup = false;
foreach ( char c in data )
{
if ( c >= '0' && c <= '9' )
{
result[resultIter++] = c;
doGroup = true;
}
else
{
if ( doGroup )
{
result[resultIter++] = ',';
doGroup = false;
}
}
}
return new string(result);
}
Implement an algorithm to sort an array. Why did you pick the method you did?
Bubble sort:
for(int x=0; x { int index_of_min = x; for(int y=x; y { if(array[index_of_min] { index_of_min = y; } } int temp = array[x]; array[x] = array[index_of_min]; array[index_of_min] = temp; } Quick Sort: void swap(int *x,int *y) { int temp; temp = *x; *x = *y; *y = temp; } int choose_pivot(int i,int j ) { return((i+j) /2); } void quicksort(int list[],int m,int n) { int key,i,j,k; if( m < n) { k = choose_pivot(m,n); swap(&list[m],&list[k]); key = list[m]; i = m+1; j = n; while(i <= j) { while((i <= n) && (list[i] <= key)) i++; while((j >= m) && (list[j] > key)) j--; if( i < j) swap(&list[i],&list[j]); } // swap two elements swap(&list[m],&list[j]); // recursively sort the lesser list quicksort(list,m,j-1); quicksort(list,j+1,n); } } Insertion Sort: void insertion_sort(int x[],int length) { int key,i; for(int j=1;j { key=x[j]; i=j-1; while(x[i]>key && i>=0) { x[i+1]=x[i]; i--; } x[i+1]=key; } } Switch every pair of words in a string ("ab cd ef gh" becomes "cd ab gh ef") private static string ReverseWordPair(string input) { if (string.IsNullOrEmpty(input)) throw new ArgumentNullException("input"); char[] result = new char[input.Length]; int resultIter = 0; int begin = 0; // skip leading whitespace while (begin < input.Length && input[begin] == ' ') { result[resultIter++] = input[begin]; begin++; } ReverseWordPairImp(result, resultIter, input, begin); return new string(result); } private static void ReverseWordPairImp(char[] result, int resultIter, string input, int inputIter) { int[] indics = new int[2]; int i = inputIter; indics[0] = inputIter; for (; i < input.Length; ++i) { if (input[i] == ' ' && indics[1] == 0) indics[1] = -1; else if ( input[i] != ' ' && indics[1] == -1 ) indics[1] = i; else if (input[i] == ' ' && indics[1] > 0) break; } int firstWordEnd = 0; if (indics[1] > 0) { // copy second word for (firstWordEnd = indics[1]; firstWordEnd < i; firstWordEnd++) result[resultIter++] = input[firstWordEnd]; // copy spaces for (firstWordEnd = indics[1] - 1; firstWordEnd > 0; firstWordEnd--) { if (input[firstWordEnd] != ' ') break; result[resultIter++] = input[firstWordEnd]; } } else firstWordEnd = input.Length - 1; for (int j = indics[0]; j <= firstWordEnd; j++) result[resultIter++] = input[j]; while (i < input.Length && input[i] == ' ') { result[resultIter++] = input[i]; i++; } if ( i < input.Length ) ReverseWordPairImp(result, resultIter, input, i); } Write a function to zero all duplicate values in an integer array. How would you test it? Approach 1: Sort the array, and remove all duplicate values. Approach 2: Remove dups while sorting, (as highlighted in below code): static void swap(int[] list, int x, int y) { if (list[x] == list[y]) list[y] = 0; int temp; temp = list[x]; list[x] = list[y]; list[y] = temp; } static int choose_pivot(int i, int j) { return((i+j) /2); } static void quicksort(int[] list, int m, int n) { int key,i,j,k; if( m < n) { k = choose_pivot(m,n); swap(list, m, k); key = list[m]; i = m+1; j = n; while(i <= j) { while((i <= n) && (list[i] <= key)) i++; while((j >= m) && (list[j] > key)) j--; if( i < j) swap(list, i, j); } // swap two elements swap(list, m, j); // recursively sort the lesser list quicksort(list,m,j-1); quicksort(list,j+1,n); } } 编程去掉两个string list中重复的部分。 /// /// Remove all characters occupied in s2 from s1 /// ///S1 ///S2 /// /// For e.g. /// /// RemoveCharactersOccursInS2FromS1("This is a book", "is") returns /// Th a book /// 1. private static string RemoveCharactersOccursInS2FromS1(string s1, string s2) 2. { 3. if (string.IsNullOrEmpty(s1)) 4. throw new ArgumentNullException("s1"); 5. if (string.IsNullOrEmpty(s2)) 6. throw new ArgumentNullException("s2"); 7. 8. int[] occurrency = new int[53]; 9. foreach (char c in s2) 10. { 11. if (c >= 'a' && c <= 'z') 12. occurrency[c - 'a']++; 13. else if (c >= 'A' && c <= 'Z') 14. occurrency[c - 'A' + 26]++; 15. else if (char.IsWhiteSpace(c)) 16. occurrency[occurrency.Length - 1]++; 17. else 18. throw new ArgumentException("Only characters between 'a' and 'z' and characters between 'A' and 'Z' are supported."); 19. } 20. 21. char[] result = new char[s1.Length]; 22. int resultIndex = 0; 23. foreach (char c in s1) 24. { 25. int index = -1; 26. if (c >= 'a' && c <= 'z') 27. index = c - 'a'; 28. else if (c >= 'A' && c <= 'Z') 29. index = c - 'A' + 26; 30. else if (char.IsWhiteSpace(c)) 31. index = occurrency.Length - 1; 32. else 33. throw new ArgumentException("Only characters between 'a' and 'z' and characters between 'A' and 'Z' are supported."); 34. 35. if (occurrency[index] == 0) 36. { 37. result[resultIndex++] = c; 38. } 39. } 40. 41. return new string(result, 0, resultIndex); 42. } 现有一单链表,输出从尾端开始的第5个数值,并写出相应的测试用例 两个指针遍历,一个提前走5步,一个走一步,步步更新,走5步碰到结尾了以后,第二个指针指向倒数第5个数值。 What is reflection? Can you tell me some use scenarios of reflection, and how do you use reflection? 反射提供了封装程序集、模块和类型的对象(Type 类型)。可以使用反射动态创建类型的实例,将类型绑定到现有对象,或从现有对象获取类型并调用其方法或访问其字段和属性。如果代码中使用了属性,可以利用反射对它们进行访问。有关更多信息,请参见属性。 反射在下列情况下很有用: 1.需要访问程序元数据的属性。请参见主题使用反射访问属性。 2.检查和实例化程序集中的类型。 3.在运行时构建新类型。使用 System.Reflection.Emit 中的类。 4.执行后期绑定,访问在运行时创建的类型的方法。请参见主题动态加载和使用类型。 What is delegate? Please provide some use scenarios of delegate. Is delegate the same as event, what’s the different? 委托是一种引用方法的类型。一旦为委托分配了方法,委托将与该方法具有完全相同的行为。委托方法的 使用可以像其他任何方法一样,具有参数和返回值。 与委托的签名(由返回类型和参数组成)匹配的任何方法都可以分配给该委托。这样就可以通过编程方式 来更改方法调用,还可以向现有类中插入新代码。只要知道委托的签名,便可以分配自己的委托方法。 将方法作为参数进行引用的能力使委托成为定义回调方法的理想选择。例如,可以向排序算法传递对比较 两个对象的方法的引用。分离比较代码使得可以采用更通用的方式编写算法。 委托概述 1.委托类似于 C++ 函数指针,但它是类型安全的。 2.委托允许将方法作为参数进行传递。委托可用于定义回调方法。委托可以链接在一起; 3.例如,可以对一个事件调用多个方法。 4.方法不需要与委托签名精确匹配。有关更多信息,请参见协变和逆变。 5.C# 2.0 版引入了匿名方法的概念,此类方法允许将代码块作为参数传递,以代替单独定义的方法。 What’s box and unbox? What is the performance impact? 装箱就是隐式的将一个值型转换为引用型对象。比如: int i=0; Syste.Object obj=i; 这个过程就是装箱!就是将i装箱! 拆箱就是将一个引用型对象转换成任意值型!比如: int i=0; System.Object obj=i; int j=(int)obj; 这个过程前2句是将i装箱,后一句是将obj拆箱! 装箱和拆箱需要在堆上分配空间,因此效率上会比较慢。 C#里值传递与引用传递有什么区别? 所谓的值传递,是指将要传递的值作为一个副本传递 引用传递,传递的是引用对象的内存地址 Please describe the difference between Array and ArrayList Array是定长的数组,但是ArrayList是变长的数组。 StringBuilder和string的区别? 在.Net或者C#中,String是常量,即创建以后,不能被修改,但是StringBuilder是可以被修改的。一般来说,string + string会导致第三个string实例被创建出来,而StringBuilder.Append(string)不会创建新的实例(也就 是不会浪费内存)。 What is the different between data Set and data Reader in https://www.doczj.com/doc/9316435260.html, dataset表示一个数据集,是数据在内存中的缓存。可以包括多个表 DatSet 连接数据库时是非面向连接的。把表全部读到Sql中的缓冲池,并断开于数据库的连接 datareader 连接数据库时是面向连接的。读表时,只能向前读取,读完数据后有用户决定是否断开连接。 当设计应用程序时,要考虑应用程序所需功能的等级,以确定使用DataSet或者是DataReader。 要通过应用程序执行以下操作,就要使用DataSet: ?在结果的多个离散表之间进行导航。 ?操作来自多个数据源(例如,来自多个数据库、一个XML文件和一个电子表格的混合数据)的数据。 ?在各层之间交换数据或使用XML Web服务。与DataReader不同的是,DataSet能传递给远程客户端。 ?重用同样的记录集合,以便通过缓存获得性能改善(例如排序、搜索或筛选数据)。 ?每条记录都需要执行大量处理。对使用DataReader返回的每一行进行扩展处理会延长服务于DataReader的连接的必要时间,这影响了性能。 ?使用XML操作对数据进行操作,例如可扩展样式表语言转换(XSLT转换)或XPath查询。 对于下列情况,要在应用程序中使用DataReader: ?不需要缓存数据。 ?要处理的结果集太大,内存中放不下。 ?一旦需要以仅向前、只读方式快速访问数据。 注:填充DataSet时,DataAdapter使用DataReader。因此,使用DataAdapter取代DataSet提升的性能表现 为节省了DataSet占用内存和填充DataSet需要的循环。一般来说,此性能提升只是象征性的,因此,设计 决策应以所需功能为基础。 C#中property与attribute的区别? property和attribute汉语都称之为属性。不过property是指类向外提供的数据区域。而attribute则是描述 对象在编译时或运行时属性的。这两者是有本质区别的。 能用foreach遍历访问的对象需要实现哪个接口或声明哪个方法的类型? How to enable https://www.doczj.com/doc/9316435260.html, debugging support in production web server? 在web.config里面添加下面这一节: Can you tell me why we apply Generics in C# code? What’s the benefit of Generics? Generics provide the solution to a limitation in earlier versions of the common language runtime and the C# language in which generalization is accomplished by casting types to and from the universal base type Object. By creating a generic class, you can create a collection that is type-safe at compile-time. CLR provides Cross-Language interoperability support, can you describe how CLR provides the support? 使用符合CLS的各种语言编程时,首先,编译输出的exe是一个由中间语言(IL),元数据(Metadata)和一个额外的被编译器添加的目标平台的标准可执行文件头(比如 win32平台就是加了一个标准Win32可执行文件头)组成的PE(portable executable,可移植执行体)文件,而不是传统的二进制可执行文件--虽然他们有着相同的扩展名。中间语言是一组独立于CPU的指令集,它可以被即时编译器(Just In Time)翻译成目标平台的本地代码。中间语言代码使得所有https://www.doczj.com/doc/9316435260.html,平台的高级语言C#,https://www.doczj.com/doc/9316435260.html,,https://www.doczj.com/doc/9316435260.html,等得以平台独立,并实现语言之间实现互操作。 What is GAC? What is strong-named assembly, why strong-named assembly? GAC全称是Global Assembly Cache 安装有公共语言运行库的每台计算机都具有称为全局程序集缓存的计算机范围内的代码缓存。全局程序集缓存中存储了专门指定给由计算机中若干应用程序共享的程序集。 strong-named assembly 强名称(强命名)是由程序集的标识加上公钥和数字签名组成的。其中,程序集的标识包括简单文本名称、版本号和区域性信息(如果提供的话)。强名称是使用相应的私钥,通过程序集文件(包含程序集清单的文件,并因而也包含构成该程序集的所有文件的名称和散列)生成的。 因为强名称具有以下特点: 强名称依赖于唯一的密钥对来确保名称的唯一性。任何人都不会生成与您生成的相同的程序集名称,因为用一个私钥生成的程序集的名称与用其他私钥生成的程序集的名称不相同。 强名称保护程序集的版本沿袭。强名称可以确保没有人能够生成您的程序集的后续版本。用户可以确信,他们所加载的程序集的版本出自创建该版本(应用程序是用该版本生成的)的同一个发行者。 强名称提供可靠的完整性检查。通过 .NET Framework 安全检查后,即可确信程序集的内容在生成后未被更改过。但请注意,强名称中或强名称本身并不暗含信任级别,例如由数字签名和支持证书提供的信任。 从而可以得到更好的版本控制和命名保护,避免DLL冲突等好处。 Remoting在客户端服务器怎么实现? 服务器端 第一步:确定使用的信道。 .NET Remoting提供了三种预定义的信道:TCP、HTTP、IPC,他们各有自己的特点,根据自己需要进行选择。 第二步:注册信道。 注册信道就是把已经创建的信道,使用ChannelServices类的RegisterChannel方法来“向信道服务注册信道” 第三步:注册远程对象。 在.NET Remoting中,注册远程对象,使用RemotingConfiguration类提供的静态方法RegisterWellKnownServiceType或RegisterActivatedServiceType来进行注册。 第四步:注销信道。 在程序关闭时,或者清理资源时,要关闭调已经注册的信道,这样好让出服务所使用的计算机端口,方法就是调用ChannelServices.UnregisterChannel即可实现。 客户端: 第一步:创建信道 客户端的信道注册,跟服务器端的注册基本相同。 第二步:发现URL 客户端要激活服务器上的远程对象,也就是说要获得一个远程对象的本地代理,则必须首先获得远程对象的URL。该URL和Web浏览器的URL具有一样的含义,具有如下的格式: Protocol://server:port/URI 这里的协议,也就是信道的格式,如tcp、http、ipc。 第三步:创建对象 创建对象,也就是在客户端激活服务器上的对象,并获得这个远程对象的一个本地代理(透明代理)。 在客户端创建远程对象,有两种方法,一种是使用new方法来创建,另外一种方法则是使用激活类的Activator的创建方法。 第四步:注销信道 客户端的信道注销和服务器端是一样的。 You have a linked list and don't know how long it is; how do you find the middle of it? 编程题目,无固定答案,个人思路: 每次去掉一个头节点和一个尾节点,当链表只剩一个或者两个节点的时候,返回其值。(操作很灵活,比如改成双向链表或者设置头尾的监视哨等) 如果只想拿到节点值的话,复制链表到一个数组里,取中值即可。 What's the difference between a linked list and an array? A 从逻辑结构来看 A-1. 数组必须事先定义固定的长度(元素个数),不能适应数据动态地增减的情况。当数据增加时,可能超出原先定义的元素个数;当数据减少时,造成内存浪费。 A-2. 链表动态地进行存储分配,可以适应数据动态地增减的情况,且可以方便地插入、删除数据项。(数组中插入、删除数据项时,需要移动其它数据项) B 从内存存储来看 B-1. (静态)数组从栈中分配空间, 对于程序员方便快速,但是自由度小 B-2. 链表从堆中分配空间, 自由度大但是申请管理比较麻烦. 数组中的数据在内存中的按顺序存储的,而链表是随机存储的! 要访问数组中的元素可以按下标索引来访问,速度比较快,如果对他进行插入操作的话,就得移动很多元素,所以对数组进行插入操作效率很低! 由于连表是随机存储的,链表在插入,删除操作上有很高的效率(相对数组),如果要访问链表中的某个元素的话,那就得从链表的头逐个遍历,直到找到所需要的元素为止,所以链表的随机访问的效率就比数组要低 数组在内存中开辟连续的一块区域,如果一个数据要两个内存单元,一组5个数据10个单元就够了,无需标记其地址,因为数组定义时候标顶了第一个原许的地址,其他四个都知道了。 链表可可以是连续的,也可以是不连续的,但一般都是不连续的,尽管在内存中是连续的,我们也不把他当作是连续的,而是把他当作是不连续的,因为如果把他当作是连续的,不如当作是数组了,在某些情况下。一链5个数据,如果每个数据本身用2个内存单元,那么10个单元是不够的,因为每个数据都要表示出下个数据在哪里,所以一个数据本身用2个单元,再用1个单元表示此链下一个数据在什么地址。 How would you find a cycle in a linked list? 设置两个指针(fast, slow),初始值都指向头,slow每次前进一步,fast每次前进二步,如果链表存在环,则fast必定先进入环,而slow后进入环,两个指针必定相遇。(当然,fast先行头到尾部为NULL,则为无环链表)程序如下: bool IsExitsLoop(slist * head) { slist * slow = head , * fast = head; while ( fast && fast -> next ) { slow = slow -> next; fast = fast -> next -> next; if ( slow == fast ) break ; } return ! (fast == NULL || fast -> next == NULL); } 进程和线程的区别? 进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位. 线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源. Implement a linked list. Why did you pick the method you did? 可选择头插法或者位插法,取决于监视哨的位置。