当前位置:文档之家› 算法大全-面试题-链表-栈-二叉树-数据结构

算法大全-面试题-链表-栈-二叉树-数据结构

算法大全-面试题-链表-栈-二叉树-数据结构
算法大全-面试题-链表-栈-二叉树-数据结构

一、单链表

目录

1.单链表反转

2.找出单链表的倒数第4个元素

3.找出单链表的中间元素

4.删除无头单链表的一个节点

5.两个不交叉的有序链表的合并

6.有个二级单链表,其中每个元素都含有一个指向一个单链表的指针。写程序把这个二级链表称一级单链表。

7.单链表交换任意两个元素(不包括表头)

8.判断单链表是否有环?如何找到环的“起始”点?如何知道环的长度?

9.判断两个单链表是否相交

10.两个单链表相交,计算相交点

11.用链表模拟大整数加法运算

12.单链表排序

13.删除单链表中重复的元素

首先写一个单链表的C#实现,这是我们的基石:

public class Link

{

public Link Next;

public string Data;

public Link(Link next, string data)

{

this.Next = next;

this.Data = data;

}

}

其中,我们需要人为地在单链表前面加一个空节点,称其为head。例如,一个单链表是1->2->5,如图所示:

对一个单链表的遍历如下所示:

static void Main(string[] args)

{

Link head = GenerateLink();

Link curr = head;

while (curr != null)

{

Console.WriteLine(curr.Data);

curr = curr.Next;

}

}

1.单链表反转

这道题目有两种算法,既然是要反转,那么肯定是要破坏原有的数据结构的:算法1:我们需要额外的两个变量来存储当前节点curr的下一个节点next、再下一个节点nextnext:

public static Link ReverseLink1(Link head)

{

Link curr = head.Next;

Link next = null;

Link nextnext = null;

//if no elements or only one element exists

if (curr == null || curr.Next == null)

{

return head;

}

//if more than one element

while (curr.Next != null)

{

next = curr.Next; //1

nextnext = next.Next; //2

next.Next = head.Next; //3

head.Next = next; //4

curr.Next = nextnext; //5

}

return head;

}

算法的核心是while循环中的5句话

我们发现,curr始终指向第1个元素。

此外,出于编程的严谨性,还要考虑2种极特殊的情况:没有元素的单链表,以及只有一个元素的单链表,都是不需要反转的。

算法2:自然是递归

如果题目简化为逆序输出这个单链表,那么递归是很简单的,在递归函数之后输出当前元素,这样能确保输出第N个元素语句永远在第N+1个递归函数之后执行,也就是说第N个元素永远在第N+1个元素之后输出,最终我们先输出最后一个元素,然后是倒数第2个、倒数第3个,直到输出第1个:

public static void ReverseLink2(Link head)

{

if (head.Next != null)

{

ReverseLink2(head.Next);

Console.WriteLine(head.Next.Data);

}

}

但是,现实应用中往往不是要求我们逆序输出(不损坏原有的单链表),而是把这个单链表逆序(破坏型)。这就要求我们在递归的时候,还要处理递归后的逻辑。

首先,要把判断单链表有0或1个元素这部分逻辑独立出来,而不需要在递归中每次都比较一次:

public static Link ReverseLink3(Link head)

{

//if no elements or only one element exists

if (head.Next == null || head.Next.Next == null)

return head;

head.Next = ReverseLink(head.Next);

return head;

}

我们观测到:

head.Next = ReverseLink(head.Next);

这句话的意思是为ReverseLink方法生成的逆序链表添加一个空表头。

接下来就是递归的核心算法ReverseLink了:

static Link ReverseLink(Link head)

{

if (head.Next == null)

return head;

Link rHead = ReverseLink(head.Next);

head.Next.Next = head;

head.Next = null;

return rHead;

}

算法的关键就在于递归后的两条语句:

head.Next.Next = head; //1

head.Next = null; //2

啥意思呢?画个图表示就是:

这样,就得到了一个逆序的单链表,我们只用到了1个额外的变量rHead。

2.找出单链表的倒数第4个元素

这道题目有两种算法,但无论哪种算法,都要考虑单链表少于4个元素的情况:第1种算法,建立两个指针,第一个先走4步,然后第2个指针也开始走,两个指针步伐(前进速度)一致。

static Link GetLast4thOne(Link head)

{

Link first = head;

Link second = head;

for (int i = 0; i < 4; i++)

{

if (first.Next == null)

throw new Exception("Less than 4 elements");

first = first.Next;

}

while (first != null)

{

first = first.Next;

second = second.Next;

}

return second;

}

第2种算法,做一个数组arr[4],让我们遍历单链表,把第0个、第4个、第8个……第4N个扔到arr[0],把第1个、第5个、第9个……第4N+1个扔到arr[1],把第2个、第6个、第10个……第4N+2个扔到arr[2],把第3个、第7个、第11个……第4N+3个扔到arr[3],这样随着单链表的遍历结束,arr中存储的就是单链表的最后4个元素,找到最后一个元素对应的arr[i],让k=(i+1)%4,则arr[k]就是倒数第4个元素。

static Link GetLast4thOneByArray(Link head)

{

Link curr = head;

int i = 0;

Link[] arr = new Link[4];

while (curr.Next != null)

{

arr[i] = curr.Next;

curr = curr.Next;

i = (i + 1) % 4;

}

if (arr[i] == null)

throw new Exception("Less than 4 elements");

return arr[i];

}

本题目源代码下载:

推而广之,对倒数第K个元素,都能用以上2种算法找出来。

3.找出单链表的中间元素

算法思想:类似于上题,还是使用两个指针first和second,只是first每次走一步,second每次走两步:

static Link GetMiddleOne(Link head)

{

Link first = head;

Link second = head;

while (first != null && first.Next != null)

{

first = first.Next.Next;

second = second.Next;

}

return second;

}

但是,这道题目有个地方需要注意,就是对于链表元素个数为奇数,以上算法成立。如果链表元素个数为偶数,那么在返回second的同时,还要返回second.Next 也就是下一个元素,它俩都算是单链表的中间元素。

下面是加强版的算法,无论奇数偶数,一概通杀:

static void Main(string[] args)

{

Link head = GenerateLink();

bool isOdd = true;

Link middle = GetMiddleOne(head, ref isOdd);

if (isOdd)

{

Console.WriteLine(middle.Data);

}

else

{

Console.WriteLine(middle.Data);

Console.WriteLine(middle.Next.Data);

}

Console.Read();

}

static Link GetMiddleOne(Link head, ref bool isOdd)

{

Link first = head;

Link second = head;

while (first != null && first.Next != null)

{

first = first.Next.Next;

second = second.Next;

}

if (first != null)

isOdd = false;

return second;

}

4.一个单链表,很长,遍历一遍很慢,我们仅知道一个指向某节点的指针curr,而我们又想删除这个节点。

这道题目是典型的“狸猫换太子”,如下图所示:

如果不考虑任何特殊情况,代码就2行:

curr.Data = curr.Next.Data;

curr.Next = curr.Next.Next;

上述代码由一个地方需要注意,就是如果要删除的是最后一个元素呢?那就只能从头遍历一次找到倒数第二个节点了。

此外,这道题目的一个变身就是将一个环状单链表拆开(即删除其中一个元素),

此时,只要使用上面那两行代码就可以了,不需要考虑表尾。

相关问题:只给定单链表中某个结点p(非空结点),在p前面插入一个结点q。话说,交换单链表任意两个节点,也可以用交换值的方法。但这样就没意思了,所以,才会有第7题霸王硬上工的做法。

5.两个不交叉的有序链表的合并

有两个有序链表,各自内部是有序的,但是两个链表之间是无序的。

算法思路:当然是循环逐项比较两个链表了,如果一个到了头,就不比较了,直接加上去。

注意,对于2个元素的Data相等(仅仅是Data相等哦,而不是相同的引用),我们可以把它视作前面的Data大于后面的Data,从而节省了算法逻辑。

static Link MergeTwoLink(Link head1, Link head2)

{

Link head = new Link(null, Int16.MinValue);

Link pre = head;

Link curr = head.Next;

Link curr1 = head1;

Link curr2 = head2;

//compare until one link run to the end

while (curr1.Next != null && curr2.Next != null)

{

if (curr1.Next.Data < curr2.Next.Data)

{

curr = new Link(null, curr1.Next.Data);

curr1 = curr1.Next;

}

else

{

curr = new Link(null, curr2.Next.Data);

curr2 = curr2.Next;

}

pre.Next = curr;

pre = pre.Next;

}

//if head1 run to the end

while (curr1.Next != null)

{

curr = new Link(null, curr1.Next.Data);

curr1 = curr1.Next;

pre.Next = curr;

pre = pre.Next;

}

//if head2 run to the end

while (curr2.Next != null)

{

curr = new Link(null, curr2.Next.Data);

curr2 = curr2.Next;

pre.Next = curr;

pre = pre.Next;

}

return head;

}

如果这两个有序链表交叉组成了Y型呢,比如说:

这时我们需要先找出这个交叉点(图中是11),这个算法参见第9题,我们这里直接使用第10道题目中的方法GetIntersect。

然后局部修改上面的算法,只要其中一个链表到达了交叉点,就直接把另一个链表的剩余元素都加上去。如下所示:

static Link MergeTwoLink2(Link head1, Link head2)

{

Link head = new Link(null, Int16.MinValue);

Link pre = head;

Link curr = head.Next;

Link intersect = GetIntersect(head1, head2);

Link curr1 = head1;

Link curr2 = head2;

//compare until one link run to the intersect

while (curr1.Next != intersect && curr2.Next != intersect)

{

if (curr1.Next.Data < curr2.Next.Data)

{

curr = new Link(null, curr1.Next.Data);

curr1 = curr1.Next;

}

else

{

curr = new Link(null, curr2.Next.Data);

curr2 = curr2.Next;

}

pre.Next = curr;

pre = pre.Next;

}

//if head1 run to the intersect

if (curr1.Next == intersect)

{

while (curr2.Next != null)

{

curr = new Link(null, curr2.Next.Data);

curr2 = curr2.Next;

pre.Next = curr;

pre = pre.Next;

}

}

//if head2 run to the intersect

else if (curr2.Next == intersect)

{

while (curr1.Next != null)

{

curr = new Link(null, curr1.Next.Data);

curr1 = curr1.Next;

pre.Next = curr;

pre = pre.Next;

}

}

return head;

}

6.有个二级单链表,其中每个元素都含有一个指向一个单链表的指针。写程序把这个二级链表展开称一级单链表。

这个简单,就是说,这个二级单链表只包括一些head:

public class Link

{

public Link Next;

public int Data;

public Link(Link next, int data)

{

this.Next = next;

this.Data = data;

}

}

public class CascadeLink

{

public Link Next;

public CascadeLink NextHead;

public CascadeLink(CascadeLink nextHead, Link next)

{

this.Next = next;

this.NextHead = nextHead;

}

}

下面做一个二级单链表,GenerateLink1和GenerateLink2方法在前面都已经介绍过了:

public static CascadeLink GenerateCascadeLink()

{

Link head1 = GenerateLink1();

Link head2 = GenerateLink2();

Link head3 = GenerateLink1();

CascadeLink element3 = new CascadeLink(null, head3);

CascadeLink element2 = new CascadeLink(element3, head2);

CascadeLink element1 = new CascadeLink(element2, head1);

CascadeLink head = new CascadeLink(element1, null);

return head;

}

就是说,这些单链表的表头head1、head2、head3、head4……,它们组成了一个二级单链表head:null –> head1 –> head2 –> head3 –> head4

–>

我们的算法思想是:进行两次遍历,在外层用curr1遍历二级单链表head,在内层用curr2遍历每个单链表:

public static Link GenerateNewLink(CascadeLink head)

{

CascadeLink curr1 = head.NextHead;

Link newHead = curr1.Next;

Link curr2 = newHead;

while (curr1 != null)

{

curr2.Next = curr1.Next.Next;

while (curr2.Next != null)

{

curr2 = curr2.Next;

}

curr1 = curr1.NextHead;

}

return newHead;

}

其中,curr2.Next = curr1.Next.Next; 这句话是关键,它负责把上一个单链表的表尾和下一个单链表的非空表头连接起来。

7.单链表交换任意两个元素(不包括表头)

先一次遍历找到这两个元素curr1和curr2,同时存储这两个元素的前驱元素pre1和pre2。

然后大换血

public static Link SwitchPoints(Link head, Link p, Link q)

{

if (p == head || q == head)

throw new Exception("No exchange with head");

if (p == q)

return head;

//find p and q in the link

Link curr = head;

Link curr1 = p;

Link curr2 = q;

Link pre1 = null;

Link pre2 = null;

int count = 0;

while (curr != null)

{

if (curr.Next == p)

{

pre1 = curr;

count++;

if (count == 2)

break;

}

else if (curr.Next == q)

{

pre2 = curr;

count++;

if (count == 2)

break;

}

curr = curr.Next;

}

curr = curr1.Next;

pre1.Next = curr2;

curr1.Next = curr2.Next;

pre2.Next = curr1;

curr2.Next = curr;

return head;

}

注意特例,如果相同元素,就没有必要交换;如果有一个是表头,就不交换。

8.判断单链表是否有环?如何找到环的“起始”点?如何知道环的长度?

算法思想:

先分析是否有环。为此我们建立两个指针,从header一起向前跑,一个步长为1,一个步长为2,用while(直到步长2的跑到结尾)检查两个指针是否相等,直到找到为止。

static bool JudgeCircleExists(Link head)

{

Link first = head; //1 step each time

Link second = head; //2 steps each time

while (second.Next != null && second.Next.Next != null)

{

second = second.Next.Next;

first = first.Next;

if (second == first)

return true;

}

return false;

}

那又如何知道环的长度呢?

根据上面的算法,在返回true的地方,也就是2个指针相遇处,这个位置的节点P肯定位于环上。我们从这个节点开始先前走,转了一圈肯定能回来:

static int GetCircleLength(Link point)

{

int length = 1;

Link curr = point;

while (curr.Next != point)

{

length++;

curr = curr.Next;

}

return length;

}

继续我们的讨论,如何找到环的“起始”点呢?

延续上面的思路,我们仍然在返回true的地方P,计算一下从有环单链表的表头head到P点的距离

static int GetLengthFromHeadToPoint(Link head, Link point)

{

int length = 1;

Link curr = head;

while (curr != point)

{

length++;

curr = curr.Next;

}

return length;

}

如果我们把环从P点“切开”(当然并不是真的切,那就破坏原来的数据结构了),那么问题就转化为计算两个相交“单链表”的交点(第10题):

一个单链表是从P点出发,到达P(一个回圈),距离M;另一个单链表从有环单链表的表头head出发,到达P,距离N。

我们可以参考第10题的GetIntersect方法并稍作修改。

private static Link FindIntersect(Link head)

{

Link p = null;

//get the point in the circle

bool result = JudgeCircleExists(head, ref p);

if (!result) return null;

Link curr1 = head.Next;

Link curr2 = p.Next;

//length from head to p

int M = 1;

while (curr1 != p)

{

M++;

curr1 = curr1.Next;

}

//circle length

int N = 1;

while (curr2 != p)

{

N++;

curr2 = curr2.Next;

}

//recover curr1 & curr2

curr1 = head.Next;

curr2 = p.Next;

//make 2 links have the same distance to the intersect

if (M > N)

{

for (int i = 0; i < M - N; i++)

curr1 = curr1.Next;

}

else if (M < N)

{

for (int i = 0; i < N - M; i++)

curr2 = curr2.Next;

}

//goto the intersect

while (curr1 != p)

{

if (curr1 == curr2)

{

return curr1;

}

curr1 = curr1.Next;

curr2 = curr2.Next;

}

return null;

}

9.判断两个单链表是否相交

这道题有多种算法。

算法1:把第一个链表逐项存在hashtable中,遍历第2个链表的每一项,如果能在第一个链表中找到,则必然相交。

static bool JudgeIntersectLink1(Link head1, Link head2)

{

Hashtable ht = new Hashtable();

Link curr1 = head1;

Link curr2 = head2;

//store all the elements of link1

while (curr1.Next != null)

{

ht[curr1.Next] = string.Empty;

curr1 = curr1.Next;

}

//check all the elements in link2 if exists in Hashtable or not

while (curr2.Next != null)

{

//if exists

if (ht[curr2.Next] != null)

{

return true;

}

curr2 = curr2.Next;

}

return false;

}

算法2:把一个链表A接在另一个链表B的末尾,如果有环,则必然相交。如何判断有环呢?从A开始遍历,如果能回到A的表头,则肯定有环。

注意,在返回结果之前,要把刚才连接上的两个链表断开,恢复原状。

static bool JudgeIntersectLink2(Link head1, Link head2)

{

bool exists = false;

Link curr1 = head1;

Link curr2 = head2;

//goto the end of the link1

while (curr1.Next != null)

{

curr1 = curr1.Next;

}

//join these two links

curr1.Next = head2;

//iterate link2

while (curr2.Next != null)

{

if (curr2.Next == head2)

{

exists = true;

break;

}

curr2 = curr2.Next;

}

//recover original status, whether exists or not

curr1.Next = null;

return exists;

}

算法3:如果两个链表的末尾元素相同,则必相交。

static bool JudgeIntersectLink3(Link head1, Link head2)

{

Link curr1 = head1;

Link curr2 = head2;

//goto the end of the link1

while (curr1.Next != null)

{

curr1 = curr1.Next;

}

//goto the end of the link2

while (curr2.Next != null)

{

curr2 = curr2.Next;

}

if (curr1 != curr2)

return false;

else

return true;

}

10.两个单链表相交,计算相交点

分别遍历两个单链表,计算出它们的长度M和N,假设M比N大,则长度M 的链表先前进M-N,然后两个链表同时以步长1前进,前进的同时比较当前的元素,如果相同,则必是交点。

public static Link GetIntersect(Link head1, Link head2)

{

Link curr1 = head1;

Link curr2 = head2;

int M = 0, N = 0;

//goto the end of the link1

while (curr1.Next != null)

{

curr1 = curr1.Next;

M++;

}

//goto the end of the link2

while (curr2.Next != null)

{

curr2 = curr2.Next;

N++;

}

//return to the begining of the link

curr1 = head1;

curr2 = head2;

if (M > N)

{

for (int i = 0; i < M - N; i++)

curr1 = curr1.Next;

}

else if (M < N)

{

for (int i = 0; i < N - M; i++)

curr2 = curr2.Next;

}

while (curr1.Next != null)

{

if (curr1 == curr2)

{

return curr1;

}

curr1 = curr1.Next;

curr2 = curr2.Next;

}

return null;

}

11.用链表模拟大整数加法运算

例如:9>9>9>NULL + 1>NULL =>

1>0>0>0>NULL

肯定是使用递归啦,不然没办法解决进位+1问题,因为这时候要让前面的节点加1,而我们的单链表是永远指向前的。

此外对于999+1=1000,新得到的值的位数(4位)比原来的两个值(1个1位,1个3位)都多,所以我们将表头的值设置为0,如果多出一位来,就暂时存放

到表头。递归结束后,如果表头为1,就在新的链表外再加一个新的表头。

//head1 length > head2, so M > N

public static int Add(Link head1, Link head2, ref Link newHead, int M, int N)

{

// goto the end

if (head1 == null)

return 0;

int temp = 0;

int result = 0;

newHead = new Link(null, 0);

if (M > N)

{

result = Add(head1.Next, head2, ref newHead.Next, M - 1, N);

temp = head1.Data + result;

newHead.Data = temp % 10;

return temp >= 10

1 : 0;

}

else // M == N

{

result = Add(head1.Next, head2.Next, ref newHead.Next, M - 1, N - 1);

temp = head1.Data + head2.Data + +result;

newHead.Data = temp % 10;

return temp >= 10

1 : 0;

}

}

这里假设head1比head2长,而且M、N分别是head1和head2的长度。

12.单链表排序

无外乎是冒泡、选择、插入等排序方法。关键是交换算法,需要额外考虑。第7题我编写了一个交换算法,在本题的排序过程中,我们可以在外层和内层循环里面,捕捉到pre1和pre2,然后进行交换,而无需每次交换又要遍历一次单链表。在实践中,我发现冒泡排序和选择排序都要求内层循环从链表的末尾向前走,这明显是不合时宜的。

所以我最终选择了插入排序算法,如下所示:

先给出基于数组的算法:

代码

static int[]

InsertSort(int[] arr)

{

for(int i=1; i

{

for(int j =i; (j>0)&&arr[j]

{

arr[j]=arr[j]^arr[j-1];

arr[j-1]=arr[j]^arr[j-1];

arr[j]=arr[j]^arr[j-1];

}

}

return arr;

}

仿照上面的思想,我们来编写基于Link的算法:

public static Link SortLink(Link head)

{

Link pre1 = head;

Link pre2 = head.Next;

Link min = null;

for (Link curr1 = head.Next; curr1 != null; curr1 = min.Next)

{

if (curr1.Next == null)

break;

min = curr1;

for (Link curr2 = curr1.Next; curr2 != null; curr2 = curr2.Next)

{

//swap curr1 and curr2

if (curr2.Data < curr1.Data)

{

min = curr2;

curr2 = curr1;

curr1 = min;

pre1.Next = curr1;

curr2.Next = curr1.Next;

curr1.Next = pre2;

//if exchange element n-1 and n, no need to add reference from pre2 to curr2, because they are the same one

if (pre2 != curr2)

pre2.Next = curr2;

}

pre2 = curr2;

}

pre1 = min;

pre2 = min.Next;

}

return head;

}

值得注意的是,很多人的算法不能交换相邻两个元素,这是因为pre2和curr2是相等的,如果此时还执行pre2.Next = curr2; 会造成一个自己引用自己的环。

交换指针很是麻烦,而且效率也不高,需要经常排序的东西最好不要用链表来实现,还是数组好一些。

13.删除单链表中重复的元素

用Hashtable辅助,遍历一遍单链表就能搞定。

实践中发现,curr从表头开始,每次判断下一个元素https://www.doczj.com/doc/0910418157.html,x是否重复,如果重复直接使用curr.Next = curr.Next.Next; 就可以删除重复元素——这是最好的算法。唯一的例外就是表尾,所以到达表尾,就break跳出while循环。public static Link DeleteDuplexElements(Link head)

{

Hashtable ht = new Hashtable();

Link curr = head;

while (curr != null)

{

if (curr.Next == null)

{

break;

}

if (ht[curr.Next.Data] != null)

{

curr.Next = curr.Next.Next;

}

else

{

ht[curr.Next.Data] = "";

}

curr = curr.Next;

}

return head;

}

数据结构与算法模拟试题

一、选择题 1.在逻辑上可以把数据结构分成() A.线性结构和非线性结构 B.动态结构和静态结构 C.紧凑结构和非紧凑结构 D.内部结构和外部结构 2.单链表中各结点之间的地址() A.必须连续 B.部分必须连续 C.不一定连续 D.以上均不对 3.在一个长度为n的顺序表中向第i个元素(0front==L C.P==NULL D.P->rear==L 12. 已知P为单链表中的非首尾结点,删除P结点的后继结点Q的语句为()。 A.P->NEXT=Q->NEXT;FREE(Q); B.Q->NEXT=P; FREE(Q); C.Q->NEXT=P->NEXT;FREE(Q); D.P->NEXT=S;S->NEXT=P; 13.循环队列SQ队满的条件是()。 A.SQ->rear==SQ->front B. (SQ->rear+1)%MAXLEN==SQ->front C.SQ->rear==0 D. SQ->front==0 14.一组记录的排序码为(46,79,56,38,40,84),则利用堆排序的方法建立的初始堆为()。 A、79,46,56,38,40,80 B、84,79,56,38,40,46 C、84,79,56,46,40,38 D、84,56,79,40,46,38 15.排序趟数与序列原始状态(原始排列)有关的排序方法是()方法。 A、插入排序 B、选择排序 C、冒泡排序 D、快速排序 16.下列排序方法中,()是稳定的排序方法。 A、直接选择排序 B、二分法插入排序

力 扣 数 据 结 构 与 算 法

前端如何搞定数据结构与算法(先导篇) 「观感度:?」 「口味:锅包肉」 「烹饪时间:20min」 本文已收录在Github? 为什么要学习数据结构与算法? 在0202年的今天,由于每天被无数的信息轰炸,大多数人已经变得越来越浮躁了,并且丧失了独立思考的能力。 你可能会经常听到这样的感慨: 技术人究竟能走多远?我遇到了天花板 35岁的程序员要如何面对中年危机? 技术更新太快,好累,学不动了 然后,你也变得焦虑起来。那你有没有静下心来想过,如何才能抵御年龄增长并且使自己增值呢? 无非是终身学习,持续修炼自己的内功。内功也就是基础知识和核心概念,这些轰轰烈烈发展的技术本质,其实都是基础知识,也就是我们在大学里学过的基础课-程。 操作系统 计算机组成原理 计算机网络 编译原理

设计模式 数据结构与算法 这也就是为什么越靠谱的面试官越注重你基础知识的掌握程度,为什么越牛的的企业越重视你的算法能力。因为当你拥有了这些,你已经比大多数人优秀了。你的天花板由你自己来决定,大家口中的中年危机可能并不会成为你的危机。新技术来临时,你对它的本质会看得更加透彻,学起来会一通百通。这样的人才,公司培养你也会花费更少的成本。 (不过,一辈子做个开开心心的 CRUD Boy 也是一种选择。) 数据结构与算法之间的关系 Rob Pikes 5 Rules of Programming中的第五条是这样说的: Data dominates. If youve chosen the right data structures and organized things well, the algorithms will almost always be self-evident. Data structures, not algorithms, are central to programming. 数据占主导。如果您选择了正确的数据结构并组织得当,那么这些算法几乎总是不言而喻的。数据结构而非算法是编程的核心。 瑞士计算机科学家,Algol W,Modula,Oberon 和 Pascal 语言的设计师 Niklaus Emil Wirth 写过一本非常经典的书《Algorithms + Data Structures = Programs》,即算法 + 数据结构 = 程序。 我们可以得出结论,数据结构与算法之间是相辅相成的关系。数据结构服务于算法,算法作用于特定的数据结构之上。 数据结构与算法好难,怎么学?

数据结构树和二叉树实验报告

《数据结构》课程实验报告 实验名称树和二叉树实验序号 5 实验日期 姓名院系班级学号 专业指导教师成绩 教师评语 一、实验目的和要求 (1)掌握树的相关概念,包括树、结点的度、树的度、分支结点、叶子结点、儿子结点、双亲结点、树 的深度、森林等定义。 (2)掌握树的表示,包括树形表示法、文氏图表示法、凹入表示法和括号表示法等。 (3)掌握二叉树的概念,包括二叉树、满二叉树和完全二叉树的定义。 (4)掌握二叉树的性质。 (5)重点掌握二叉树的存储结构,包括二叉树顺序存储结构和链式存储结构。 (6)重点掌握二叉树的基本运算和各种遍历算法的实现。 (7)掌握线索二叉树的概念和相关算法的实现。 (8)掌握哈夫曼树的定义、哈夫曼树的构造过程和哈夫曼编码产生方法。 (9)掌握并查集的相关概念和算法。 (10)灵活掌握运用二叉树这种数据结构解决一些综合应用问题。 二、实验项目摘要 1.编写一程序,实现二叉树的各种基本运算,并在此基础上设计一个主程序完成如下功能: (1)输出二叉树b; (2)输出H结点的左、右孩子结点值; (3)输出二叉树b的深度; (4)输出二叉树b的宽度; (5)输出二叉树b的结点个数; (6)输出二叉树b的叶子结点个数。 2.编写一程序,实现二叉树的先序遍历、中序遍历和后序遍历的各种递归和非递归算法,以及层次遍历的算法。 三、实验预习内容 二叉树存储结构,二叉树基本运算(创建二叉树、寻找结点、找孩子结点、求高度、输出二叉树)

三、实验结果与分析 7-1 #include #include #define MaxSize 100 typedef char ElemType; typedef struct node { ElemType data; struct node *lchild; struct node *rchild; } BTNode; void CreateBTNode(BTNode *&b,char *str) { BTNode *St[MaxSize],*p=NULL; int top=-1,k,j=0; char ch; b=NULL; ch=str[j]; while (ch!='\0') { switch(ch) { case '(':top++;St[top]=p;k=1; break; case ')':top--;break; case ',':k=2; break; default:p=(BTNode *)malloc(sizeof(BTNode)); p->data=ch;p->lchild=p->rchild=NULL; if (b==NULL) b=p; else { switch(k) { case 1:St[top]->lchild=p;break; case 2:St[top]->rchild=p;break; } } } j++; ch=str[j]; }

《数据结构》习题集:_树和叉树

第6章树和二叉树 一、选择题 1.有一“遗传”关系,设x是y的父亲,则x可以把它的属性遗传给y,表示该遗传关系最适合的数据结构是( B ) A、向量 B、树 C、图 D、二叉树 2.树最适合用来表示( B ) A、有序数据元素 B、元素之间具有分支层次关系的数据 C、无序数据元素 D、元素之间无联系的数据 3.树B 的层号表示为1a,2b,3d,3e,2c,对应于下面选择的( C ) A、1a(2b(3d,3e),2c) B、a(b(D,e),c) C、a(b(d,e),c) D、a(b,d(e),c) 4.对二叉树的结点从1 开始连续编号,要求每个结点的编号大于其左、右孩子的编号,同一结点的左右孩子中, 其左孩子的编号小于其右孩子的编号,则可采用( C )次序的遍历实现二叉树的结点编号。 A、先序 B、中序 C、后序 D、从根开始按层次遍历 5.按照二叉树的定义,具有3 个结点的二叉树有(C )种。 A、3 B、4 C、5 D、6 6.在一棵有n个结点的二叉树中,若度为2的结点数为n2,度为1的结点数为n1,度为0的结点数为n0,则树的最大高 度为( E ),其叶结点数为( H );树的最小高度为( B ),其叶结点数为( G );若采用链表存储结构,则有( I )个空链域。 log+1 C、log2n D、n A、n/2 B、??n2 E、n0+n1+n2 F、n1+n2 G、n2+1 H、1 I、n+1 J、n1K、n2L、n1+1 7.对一棵满二叉树,m 个树叶,n 个结点,深度为h,则( D ) A、n=m+h B、h+m=2n C、m=h-1 D、n=2h-1 8.设高度为h 的二叉树中只有度为0 和度为2 的结点,则此类二叉树中所包含的结点数至少为( B ),至多 为(D )。 A、2h B、2h-1 C、2h-1 D、2h-1 9.在一棵二叉树上第5 层的结点数最多为(B)(假设根结点的层数为1) A、8 B、16 C、15 D、32 10.深度为5 的二叉树至多有( C )个结点。 A、16 B、32 C、31 D、10 11.一棵有124 个叶结点的完全二叉树,最多有(B )个结点 A、247 B、248 C、249 D、250 12.含有129 个叶子结点的完全二叉树,最少有( D )个结点 A、254 B、255 C、256 D、257 13.假定有一棵二叉树,双分支结点数为15,单分支结点数为30,则叶子结点数为( B )个。 A、15 B、16 C、17 D、47 14.用顺序存储的方法将完全二叉树中所有结点逐层存放在数组R[1…n]中,结点R[i]若有左子树,则左子树是结 点( B )。 A、R[2i+1] B、R[2i] C、R[i/2] D、R[2i-1]

数据结构与算法习题及答案

第1章绪论 习题 1.简述下列概念:数据、数据元素、数据项、数据对象、数据结构、逻辑结构、存储结构、抽象数据类型。2.试举一个数据结构的例子,叙述其逻辑结构和存储结构两方面的含义和相互关系。 3.简述逻辑结构的四种基本关系并画出它们的关系图。 4.存储结构由哪两种基本的存储方法实现 5.选择题 (1)在数据结构中,从逻辑上可以把数据结构分成()。 A.动态结构和静态结构B.紧凑结构和非紧凑结构 C.线性结构和非线性结构D.内部结构和外部结构 (2)与数据元素本身的形式、内容、相对位置、个数无关的是数据的()。 A.存储结构B.存储实现 C.逻辑结构D.运算实现 (3)通常要求同一逻辑结构中的所有数据元素具有相同的特性,这意味着()。 A.数据具有同一特点 B.不仅数据元素所包含的数据项的个数要相同,而且对应数据项的类型要一致 C.每个数据元素都一样 D.数据元素所包含的数据项的个数要相等 (4)以下说法正确的是()。 A.数据元素是数据的最小单位 B.数据项是数据的基本单位 C.数据结构是带有结构的各数据项的集合 D.一些表面上很不相同的数据可以有相同的逻辑结构 (5)以下与数据的存储结构无关的术语是()。 A.顺序队列B.链表C.有序表D.链栈 (6)以下数据结构中,()是非线性数据结构 A.树B.字符串C.队D.栈 6.试分析下面各程序段的时间复杂度。 (1)x=90;y=100; while(y>0) if(x>100) {x=x-10;y--;} elsex++; (2)for(i=0;i

[第1题-60题汇总]微软数据结构+算法面试100题

精选微软等公司数据结构 精选微软等公司数据结构++算法面试100题 -----[第1题-60题总] 资源说明: 此份,是为微软等公司数据结构+算法面试100题,之前60题的汇总。 总结整理了前第1题-第60题。特此并作此一份上传。以飨各位。:)。 -------------------------------- 相关资源,包括答案,下载地址: [答案V0.2版]精选微软数据结构+算法面试100题[前20题]--答案修正 https://www.doczj.com/doc/0910418157.html,/source/2813890 //此份答案是针对最初的V0.1版本,进行的校正与修正。 [答案V0.1版]精选微软数据结构+算法面试100题[前25题] https://www.doczj.com/doc/0910418157.html,/source/2796735 [第二部分]精选微软等公司结构+算法面试100题[前41-60题]: https://www.doczj.com/doc/0910418157.html,/source/2811703 [第一部分]精选微软等公司数据结构+算法经典面试100题[1-40题] https://www.doczj.com/doc/0910418157.html,/source/2778852 更多资源,下载地址: http://v_july_https://www.doczj.com/doc/0910418157.html,/ 很快,我将公布第21-40题的答案,敬请期待。:).. 如果你对以下的前第1-60题,有好的思路,和算法,欢迎跟帖回复, 或者,联系我,发至我的邮箱, zhoulei0907@https://www.doczj.com/doc/0910418157.html,。 My CSDN Blog:https://www.doczj.com/doc/0910418157.html,/v_JULY_v My sina Blog:https://www.doczj.com/doc/0910418157.html,/shitou009 帖子维护地址: [整理]算法面试:精选微软经典的算法面试100题[前1-60题] https://www.doczj.com/doc/0910418157.html,/u/20101023/20/5652ccd7-d510-4c10-9671-307a56006e6d.html -------------------------------------- July、2010、/11.12.请享用。:)。 1

第六章树和二叉树习题数据结构

习题六树和二叉树 一、单项选择题 1.以下说法错误的是 ( ) A.树形结构的特点是一个结点可以有多个直接前趋 B.线性结构中的一个结点至多只有一个直接后继 C.树形结构可以表达(组织)更复杂的数据 D.树(及一切树形结构)是一种"分支层次"结构 E.任何只含一个结点的集合是一棵树 2.下列说法中正确的是 ( ) A.任何一棵二叉树中至少有一个结点的度为2 B.任何一棵二叉树中每个结点的度都为2 C.任何一棵二叉树中的度肯定等于2 D.任何一棵二叉树中的度可以小于2 3.讨论树、森林和二叉树的关系,目的是为了() A.借助二叉树上的运算方法去实现对树的一些运算 B.将树、森林按二叉树的存储方式进行存储 C.将树、森林转换成二叉树 D.体现一种技巧,没有什么实际意义 4.树最适合用来表示 ( ) A.有序数据元素 B.无序数据元素 C.元素之间具有分支层次关系的数据 D.元素之间无联系的数据 5.若一棵二叉树具有10个度为2的结点,5个度为1的结点,则度为0的结点个数是()A.9 B.11 C.15 D.不确定 6.设森林F中有三棵树,第一,第二,第三棵树的结点个数分别为M1,M2和M3。与森林F对应的二叉树根结点的右子树上的结点个数是()。 A.M1 B.M1+M2 C.M3 D.M2+M3 7.一棵完全二叉树上有1001个结点,其中叶子结点的个数是() A. 250 B. 500 C.254 D.505 E.以上答案都不对 8. 设给定权值总数有n 个,其哈夫曼树的结点总数为( ) A.不确定 B.2n C.2n+1 D.2n-1 9.二叉树的第I层上最多含有结点数为() A.2I B. 2I-1-1 C. 2I-1 D.2I -1 10.一棵二叉树高度为h,所有结点的度或为0,或为2,则这棵二叉树最少有( )结点A.2h B.2h-1 C.2h+1 D.h+1 11. 利用二叉链表存储树,则根结点的右指针是()。 A.指向最左孩子 B.指向最右孩子 C.空 D.非空 14.在二叉树结点的先序序列,中序序列和后序序列中,所有叶子结点的先后顺序()A.都不相同 B.完全相同 C.先序和中序相同,而与后序不同 D.中序和后序相同,而与先序不同 15.在完全二叉树中,若一个结点是叶结点,则它没()。 A.左子结点 B.右子结点 C.左子结点和右子结点 D.左子结点,右子结点和兄弟结点 16.在下列情况中,可称为二叉树的是()

目前最完整的数据结构1800题包括完整答案树和二叉树答案

第6章树和二叉树 部分答案解释如下。 12. 由二叉树结点的公式:n=n0+n1+n2=n0+n1+(n0-1)=2n0+n1-1,因为n=1001,所以1002=2n0+n1,在完全二叉树树中,n1只能取0或1,在本题中只能取0,故n=501,因此选E。 42.前序序列是“根左右”,后序序列是“左右根”,若要这两个序列相反,只有单支树,所以本题的A和B均对,单支树的特点是只有一个叶子结点,故C是最合适的,选C。A或B 都不全。由本题可解答44题。 47. 左子树为空的二叉树的根结点的左线索为空(无前驱),先序序列的最后结点的右线索为空(无后继),共2个空链域。 52.线索二叉树是利用二叉树的空链域加上线索,n个结点的二叉树有n+1个空链域。 部分答案解释如下。 6.只有在确定何序(前序、中序、后序或层次)遍历后,遍历结果才唯一。 19.任何结点至多只有左子树的二叉树的遍历就不需要栈。 24. 只对完全二叉树适用,编号为i的结点的左儿子的编号为2i(2i<=n),右儿子是2i+1(2i+1<=n) 37. 其中序前驱是其左子树上按中序遍历的最右边的结点(叶子或无右子女),该结点无右孩子。 38 . 新插入的结点都是叶子结点。 42. 在二叉树上,对有左右子女的结点,其中序前驱是其左子树上按中序遍历的最右边的结点(该结点的后继指针指向祖先),中序后继是其右子树上按中序遍历的最左边的结点(该结点的前驱指针指向祖先)。 44.非空二叉树中序遍历第一个结点无前驱,最后一个结点无后继,这两个结点的前驱线索和后继线索为空指针。 三.填空题

1.(1)根结点(2)左子树(3)右子树 2.(1)双亲链表表示法(2)孩子链表表示法(3)孩 子兄弟表示法 3.p->lchild==null && p->rchlid==null 4.(1) ++a*b3*4-cd (2)18 5.平衡 因子 6. 9 7. 12 8.(1)2k-1 (2)2k-1 9.(1)2H-1 (2)2H-1 (3)H=?log2N?+1 10. 用顺序存储二叉树时,要按完全二叉树的形式存储,非完全二叉树存储时,要加“虚结 点”。设编号为i和j的结点在顺序存储中的下标为s 和t ,则结点i和j在同一层上的条 件是?log2s?=?log2t?。 11. ?log2i?=?log2j?12.(1)0 (2)(n-1)/2 (3)(n+1)/2 (4) ?log2n?+1 13.n 14. N2+1 15.(1) 2K+1-1 (2) k+1 16. ?N/2? 17. 2k-2 18. 64 19. 99 20. 11 21.(1) n1-1 (2)n2+n3 22.(1)2k-2+1(第k层1个结点,总结点个数是2H-1,其双亲是2H-1/2=2k-2)(2) ?log2i?+1 23.69 24. 4 25.3h-1 26. ?n/2? 27. ?log2k?+1 28.(1)完全二叉树 (2)单枝树,树中任一结点(除最后一个结点是叶子外),只有左子女或 只有右子女。 29.N+1 30.(1) 128(第七层满,加第八层1个) (2) 7 31. 0至多个。任意二叉树,度为1的结点个数没限制。只有完全二叉树,度为1的结点个 数才至多为1。 32.21 33.(1)2 (2) n-1 (3) 1 (4) n (5) 1 (6) n-1 34.(1) FEGHDCB (2)BEF(该二叉树转换成森林,含三棵树,其第一棵树的先根次序是 BEF) 35.(1)先序(2)中序 36. (1)EACBDGF (2)2 37.任何结点至多只有右子女 的二叉树。 38.(1)a (2) dbe (3) hfcg 39.(1) . (2) ...GD.B...HE..FCA 40.DGEBFCA 41.(1)5 (2)略 42.二叉排序树 43.二叉树 44. 前序 45.(1)先根次序(2)中根次序46.双亲的右子树中最左下的叶子结点47.2 48.(n+1)/2 49.31(x的后继是经x的双亲y的右子树中最左下的叶结点) 50.(1)前驱 (2)后 继 51.(1)1 (2)y^.lchild (3)0 (4)x (5)1 (6) y (7)x(编者注:本题按 中序线索化) 52.带权路径长度最小的二叉树,又称最优二叉树 53.69 54.(1)6 (2)261 55.(1)80 (2)001(不唯一)56.2n0-1 57.本题①是表达式求值,②是在二叉排序树中删除值为x的结点。首先查找x,若没有x, 则结束。否则分成四种情况讨论:x结点有左右子树;只有左子树;只有右子树和本身是叶 子。 (1)Postoder_eval(t^.Lchild) (2) Postorder_eval(t^.Rchild) (3)ERROR(无此运 算符)(4)A (5)tempA^.Lchild (6)tempA=NULL(7)q^.Rchild (8)q (9)tempA^.Rchild (10)tempA^.Item

阿里校园招聘历年经典面试题汇总:算法工程师

阿里校园招聘历年经典面试题汇总:算法工程师 (1)、jvm 原理 (2)、minor GC 与 Full GC (3)、HashMap 实现原理 (4)、java.util.concurrent 包下使用过哪些 (5)、concurrentMap 和 HashMap 区别 (6)、信号量是什么,怎么使用? (7)、阻塞队列了解吗?怎么使用? (8)、JAVA NIO 是什么? (9)、类加载机制是怎样的 (10)、什么是幂等性 (11)、有哪些 JVM 调优经验 (12)、分布式 CAP 了解吗? (13)、hdfs怎么添加Datanode,添加后hdfs会有什么操作? (14)、Hbase 跟关系数据库对比优缺点?为什么 Hbase 索引速度快 (15)、Hbase 大压缩与小压缩区别 (16)、Hive 与 Hbase 的使用场景 (17)、简单说说Spark功能,spark 与hive有无依赖关系? (18)、zookeeper 有什么应用场景,怎么选举的?3 个节点挂掉一个能正常工作吗? (19)、Hbase 中 zookeaper 作用 (20)、Hbase 写操作什么时候返回 (21)、mysql 有哪些存储引擎?各自特点 (22)、用过哪些设计模式?怎样实现线程安全单例模式? (23)、用过哪些RPC框架? (24)、什么是AOP? (25)、决策树算法怎么实现的? (26)、java垃圾回收会出现不可回收的对象吗?怎么解决内存泄露问题?怎么

定位问题源? (27)、终止线程有几种方式?终止线程标记变量为什么是 valotile 类型?(28)、用过哪些并发的数据结构? cyclicBarrier 什么功能?信号量作用?数据库读写阻塞怎么解决? (29)、乐观锁与悲观锁,怎么实现乐观锁? (30)、开发过分布式框架?怎么实现分布式事务? (31)、spark streaming与storm区别? (32)、找到最大子数组的 start,和end下标 (33)、用过 CDH中什么任务调度? (34)、spark streaming时间间隔设置很小会出现什么状况? (35)、搜索引擎了解多少?你认为搜索引擎的难点在哪里? (36)、RPC 了解吗?怎么监控 RPC 状态,找出出现问题的 RPC 连接?(37)、spring 框架了解多少? (38)、flume应用场景 (39)、找出一串字符中第一个不重复字符的下标。 点击查看详细面经〉〉〉〉〉〉〉〉〉〉〉〉 更多精品干货>>>>>>>>>>> 更多阿里机器学习/数据挖掘经典面试题 其他名企机器学习/数据挖掘经典面试题

数据结构树和二叉树习题

树与二叉树 一.选择题 1.假定在一棵二叉树中,双分支结点数为15,单分支结点数为30个,则叶子结 点数为()个。 A.15B.16C.17D.47 2.按照二叉树的定义,具有3个结点的不同形状的二叉树有()种。 A. 3 B. 4 C. 5 D. 6 3.按照二叉树的定义,具有3个不同数据结点的不同的二叉树有()种。 A. 5 B. 6 C. 30 D. 32 4.深度为5的二叉树至多有()个结点。1 A. 16 B. 32 C. 31 D. 10 5.设高度为h的二叉树上只有度为0和度为2的结点,则此类二叉树中所包含的 结点数至少为()。 A. 2h B. 2h-1 C. 2h+1 D. h+1 6.对一个满二叉树2,m个树叶,n个结点,深度为h,则()。 A. n=h+m3 B. h+m=2n C. m=h-1 D. n=2 h-1 1深度为n的二叉树结点至多有2n-1 2满二叉树是除最后一层无任何子节点外,每一层上的所有结点都有两个子结点的二叉树7.任何一棵二叉树的叶结点在先序.中序和后序遍历序列中的相对次序()。 A.不发生改变 B.发生改变 C.不能确定 D.以上都不对 8.如果某二叉树的前根次序遍历结果为stuwv,中序遍历为uwtvs,那么该二叉 树的后序为()。 A. uwvts B. vwuts C. wuvts D. wutsv 9.某二叉树的前序遍历结点访问顺序是abdgcefh,中序遍历的结点访问顺序是 dgbaechf,则其后序遍历的结点访问顺序是()。 A. bdgcefha B. gdbecfha C. bdgaechf D. gdbehfca 10.在一非空二叉树的中序遍历序列中,根结点的右边()。 A. 只有右子树上的所有结点 B. 只有右子树上的部分结点 C. 只有左子树上的部分结点 D. 只有左子树上的所有结点 11.树的基本遍历策略可分为先根遍历和后根遍历;二叉树的基本遍历策略可分为 先序遍历.中序遍历和后序遍历。这里,我们把由树转化得到的二叉树4叫做这棵数对应的二叉树。结论()是正确的。 A.树的先根遍历序列与其对应的二叉树的先序遍历序列相同 B.树的后根遍历序列与其对应的二叉树的后序遍历序列相同 3对于深度为h的满二叉树,n=20+21+…+2h-1=2h-1,m=2h-1。故而n=h+m。 4树转化为二叉树的基本方法是把所有兄弟结点都用线连起来,然后去掉双亲到子女的连线,只留下双亲到第一个子女的连线。因此原来的兄弟关系就变为双亲与右孩子的关系。 1/ 9

数据结构与算法分析习题与参考答案

大学 《数据结构与算法分析》课程 习题及参考答案 模拟试卷一 一、单选题(每题 2 分,共20分) 1.以下数据结构中哪一个是线性结构?( ) A. 有向图 B. 队列 C. 线索二叉树 D. B树 2.在一个单链表HL中,若要在当前由指针p指向的结点后面插入一个由q指向的结点, 则执行如下( )语句序列。 A. p=q; p->next=q; B. p->next=q; q->next=p; C. p->next=q->next; p=q; D. q->next=p->next; p->next=q; 3.以下哪一个不是队列的基本运算?() A. 在队列第i个元素之后插入一个元素 B. 从队头删除一个元素 C. 判断一个队列是否为空 D.读取队头元素的值 4.字符A、B、C依次进入一个栈,按出栈的先后顺序组成不同的字符串,至多可以组成( ) 个不同的字符串? A.14 B.5 C.6 D.8 5.由权值分别为3,8,6,2的叶子生成一棵哈夫曼树,它的带权路径长度为( )。 以下6-8题基于图1。 6.该二叉树结点的前序遍历的序列为( )。 A.E、G、F、A、C、D、B B.E、A、G、C、F、B、D C.E、A、C、B、D、G、F D.E、G、A、C、D、F、B 7.该二叉树结点的中序遍历的序列为( )。 A. A、B、C、D、E、G、F B. E、A、G、C、F、B、D C. E、A、C、B、D、G、F E.B、D、C、A、F、G、E 8.该二叉树的按层遍历的序列为( )。

A.E、G、F、A、C、D、B B. E、A、C、B、D、G、F C. E、A、G、C、F、B、D D. E、G、A、C、D、F、B 9.下面关于图的存储的叙述中正确的是( )。 A.用邻接表法存储图,占用的存储空间大小只与图中边数有关,而与结点个数无关 B.用邻接表法存储图,占用的存储空间大小与图中边数和结点个数都有关 C. 用邻接矩阵法存储图,占用的存储空间大小与图中结点个数和边数都有关 D.用邻接矩阵法存储图,占用的存储空间大小只与图中边数有关,而与结点个数无关 10.设有关键码序列(q,g,m,z,a,n,p,x,h),下面哪一个序列是从上述序列出发建 堆的结果?( ) A. a,g,h,m,n,p,q,x,z B. a,g,m,h,q,n,p,x,z C. g,m,q,a,n,p,x,h,z D. h,g,m,p,a,n,q,x,z 二、填空题(每空1分,共26分) 1.数据的物理结构被分为_________、________、__________和___________四种。 2.对于一个长度为n的顺序存储的线性表,在表头插入元素的时间复杂度为_________, 在表尾插入元素的时间复杂度为____________。 3.向一个由HS指向的链栈中插入一个结点时p时,需要执行的操作是________________; 删除一个结点时,需要执行的操作是______________________________(假设栈不空而 且无需回收被删除结点)。 4.对于一棵具有n个结点的二叉树,一个结点的编号为i(1≤i≤n),若它有左孩子则左 孩子结点的编号为________,若它有右孩子,则右孩子结点的编号为________,若它有 双亲,则双亲结点的编号为________。 5.当向一个大根堆插入一个具有最大值的元素时,需要逐层_________调整,直到被调整 到____________位置为止。 6.以二分查找方法从长度为10的有序表中查找一个元素时,平均查找长度为________。 7.表示图的三种常用的存储结构为_____________、____________和_______________。 8.对于线性表(70,34,55,23,65,41,20)进行散列存储时,若选用H(K)=K %7 作为散列函数,则散列地址为0的元素有________个,散列地址为6的有_______个。 9.在归并排序中,进行每趟归并的时间复杂度为______,整个排序过程的时间复杂度为 ____________,空间复杂度为___________。 10.在一棵m阶B_树上,每个非树根结点的关键字数目最少为________个,最多为________ 个,其子树数目最少为________,最多为________。 三、运算题(每题 6 分,共24分) 1.写出下列中缀表达式的后缀形式: (1)3X/(Y-2)+1 (2)2+X*(Y+3) 2.试对图2中的二叉树画出其: (1)顺序存储表示的示意图; (2)二叉链表存储表示的示意图。 3.判断以下序列是否是小根堆? 如果不是, 将它调 图2 整为小根堆。 (1){ 12, 70, 33, 65, 24, 56, 48, 92, 86, 33 } (2){ 05, 23, 20, 28, 40, 38, 29, 61, 35, 76, 47, 100 } 4.已知一个图的顶点集V和边集E分别为: V={1,2,3,4,5,6,7};

数据结构算法面试100题

数据结构+算法面试100题~~~摘自CSDN,作者July 1.把二元查找树转变成排序的双向链表(树) 题目: 输入一棵二元查找树,将该二元查找树转换成一个排序的双向链表。 要求不能创建任何新的结点,只调整指针的指向。 10 / / 6 14 / / / / 4 8 12 16 转换成双向链表 4=6=8=10=12=14=16。 首先我们定义的二元查找树节点的数据结构如下: struct BSTreeNode { int m_nValue; // value of node BSTreeNode *m_pLeft; // left child of node BSTreeNode *m_pRight; // right child of node }; 2.设计包含min函数的栈(栈) 定义栈的数据结构,要求添加一个min函数,能够得到栈的最小元素。 要求函数min、push以及pop的时间复杂度都是O(1)。 参见C:\Users\Administrator\Desktop\demo\Stack 分析:min时间复杂度要达到O(1),需要我们在栈中存储最小元素 3.求子数组的最大和(数组) 题目: 输入一个整形数组,数组里有正数也有负数。 数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和。求所有子数组的和的最大值。要求时间复杂度为O(n)。 例如输入的数组为1, -2, 3, 10, -4, 7, 2, -5,和最大的子数组为3, 10, -4, 7, 2,因此输出为该子数组的和18。 分析:根据dp思想 #include #define N 8 int main() { int i, a[N] = {1, -2, 3, 10, -4, 7, 2, -5}; int from[N], result[N], max;

数据结构与算法试题

数据结构与算法试题 一、单选题 1、在数据结构的讨论中把数据结构从逻辑上分为 (C ) A 内部结构与外部结构 B 静态结构与动态结构 C 线性结构与非线性结构 D 紧凑结构与非紧凑结构。 2、采用线性链表表示一个向量时,要求占用的存储空间地址(D ) A 必须就是连续的 B 部分地址必须就是连续的 C 一定就是不连续的 D 可连续可不连续 3、采用顺序搜索方法查找长度为n的顺序表时,搜索成功的平均搜索长度为( D )。 A n B n/2 C (n-1)/2 D (n+1)/2 4、在一个单链表中,若q结点就是p结点的前驱结点,若在q与p之间插入结点s,则执行( D )。 A s→link = p→link;p→link = s; B p→link = s; s→link = q; C p→link = s→link;s→link = p; D q→link = s;s→link = p; 5、如果想在4092个数据中只需要选择其中最小的5个,采用( C )方法最好。 A 起泡排序 B 堆排序 C 锦标赛排序 D 快速排序 6、设有两个串t与p,求p在t中首次出现的位置的运算叫做( B )。 A 求子串 B 模式匹配 C 串替换 D 串连接 7、在数组A中,每一个数组元素A[i][j]占用3个存储字,行下标i从1到8,列下标j从1到10。所有数组元素相继存放于一个连续的存储空间中,则存放该数

组至少需要的存储字数就是( C )。 A 80 B 100 C 240 D 270 8、将一个递归算法改为对应的非递归算法时,通常需要使用( A )。 A 栈 B 队列 C 循环队列 D 优先队列 9、一个队列的进队列顺序就是1, 2, 3, 4,则出队列顺序为( C )。 10、在循环队列中用数组A[0、、m-1] 存放队列元素,其队头与队尾指针分别为front与rear,则当前队列中的元素个数就是( D )。 A ( front - rear + 1) % m B ( rear - front + 1) % m C ( front - rear + m) % m D ( rear - front + m) % m 11、一个数组元素a[i]与( A )的表示等价。 A *(a+i) B a+i C *a+i D &a+i 12、若需要利用形参直接访问实参,则应把形参变量说明为( B )参数。 A 指针 B 引用 C 值 D 变量 13、下面程序段的时间复杂度为( C ) for (int i=0;i

典型数据结构面试题

数据结构 1?在一个单链表中p所指结点之前插入一个s (值为e)所指结点时,可执行如下操作: q=head; while (q->next!=p)q=q->next; s= newNode;s->data=e; q->next=;// 填空 s->next=;// 填空 2.线性表的顺序存储结构是一种的存储结构,而链式存储结构是一种___的 存储结构。 A.随机存取 B.索引存取 C.顺序存取 D.散列存取 3.线性表若采用链式存储结构时,要求内存中可用存储单元的地址___。 A.必须是连续的 B.部分地址必须是连续的 C.一定是不连续的 D.连续或不连续都可以 4?在一个单链表中,已知q所指结点是p所指结点的前驱结点,若在q和p 之间插入s结点,则执行_。 A.s->next=p->next;p->next=s; B.p->next=s->next;s->next=p;

C.q->next=s;s->next=p; D.p->next=s;s->next=q; 5.在一个单链表中,若p 所指结点不是最后结点,在p 之后插入s 所指结点,则执行__。 A.s->next=p;p->next=s; B.s->next=p->next;p->next=s; C.s->next=p->next;p=s; C. p->next=s;s->next=p; 6.在一个单链表中,若删除p 所指结点的后续结点,则执行__。 A.p->next= p->next->next; B.p= p->next;p->next= p->next->nex;t C.p->next= p->next; D.p= p->next->next; 7.链表不具备的特点是__。 A 可随机访问任何一个元素 B 插入、删除操作不需要移动元素 C无需事先估计存储空间大小D所需存储空间与线性表长度成正比 8.以下关于线性表的说法不正确的是。 A 线性表中的数据元素可以是数字、字符、记录等不同类型。 B 线性表中包含的数据元素个数不是任意的。 C 线性表中的每个结点都有且只有一个直接前趋和直接后继。 D 存在这样的线性表:表中各结点都没有直接前趋和直接后继。 9?在一个长度为n的顺序表中删除第i个元素,要移动个元素。如果要在第 i 个元素前插入一个元素,要后移()个元素。N-I N-I+1

国家二级ACCESS机试选择题(数据结构与算法)模拟试卷15

国家二级ACCESS机试选择题(数据结构与算法)模拟试卷15 (总分:64.00,做题时间:90分钟) 一、选择题(总题数:32,分数:64.00) 1.设循环队列为Q(1:m),其初始状态为front=rear=m。经过一系列入队与退队运算后,front=15,rear=20。现要在该循环队列中寻找最大值的元素,最坏情况下需要比较的次数为 (分数:2.00) A.4 √ B.6 C.m-5 D.m-6 解析:解析:初始状态为:front=rear=m,rear-front=0,此时队列为空。经过一系列入队与退队运算后,front=15,rear=20。队尾大于队头,则队尾rear减队头front等于5个元素。此时队列中有5个元素,而查找最大项至少要比较n.1次,就是4次。因此选项A正确。 2.下列叙述中正确的是 (分数:2.00) A.循环队列属于队列的链式存储结构 B.双向链表是二叉树的链式存储结构 C.非线性结构只能采用链式存储结构 D.有的非线性结构也可以采用顺序存储结构√ 解析:解析:顺序存储方式不仅能用于存储线性结构,还可以用来存放非线性结构。例如,完全二叉树是属于非线性结构,但其最佳存储方式是顺序存储方式。 3.某二叉树中有n个叶子结点,则该二叉树中度为2l的结点数为 (分数:2.00) A.n+1 B.n-1 √ C.2n D.n/2 解析:解析:任意一棵二叉树,如果叶结点数为N 0,而度数为2的结点总数为N 2,则N 0 =N 2 +1;N 2 =N 0 -1。所以如果二叉树中有n个叶子结点,则该二叉树中度为2的结点数为n-1。因此选项B正确。4.下列叙述中错误的是 (分数:2.00) A.算法的时间复杂度与算法所处理数据的存储结构有直接关系 B.算法的空间复杂度与算法所处理数据的存储结构有直接关系 C.算法的时间复杂度与空间复杂度有直接关系√ D.算法的时间复杂度与空间复杂度没有必然的联系 解析:解析:算法的时间复杂度,是指执行算法所需要的计算工作量。算法的空间复杂度,是指执行这个算法所需要的内存空间。两者与算法所处理数据的存储结构都有直接关系,但两者之间没有直接关系,因此选项C错误。 5.设栈的顺序存储空间为S(0:49),栈底指针bottom=49,栈顶指针top=30(指向栈顶元素)。则栈中的元素个数为 (分数:2.00) A.30 B.29 C.20 √ D.19

22道数据结构算法面试题

微软的22道数据结构算法面试题(含答案)1、反转一个链表。循环算法。 1 List reverse(List l) { 2 if(!l) return l; 3 list cur = l.next; 4 list pre = l; 5 list tmp; 6 pre.next = null; 7 while ( cur ) { 8 tmp = cur; 9 cur = cur.next; 10 tmp.next = pre; 11 pre = tmp; 12 } 13 return tmp; 14 } 2、反转一个链表。递归算法。 1 List resverse(list l) { 2 if(!l || !l.next) return l; 3 4 List n = reverse(l.next); 5 l.next.next = l; 6 l.next=null; 7 } 8 return n; 9 } 3、广度优先遍历二叉树。 1 void BST(Tree t) { 2 Queue q = new Queue(); 3 q.enque(t); 4 Tree t = q.deque(); 5 while(t) { 6 System.out.println(t.value); 7 q.enque(t.left);

9 t = q.deque(); 10 } 11 } ---------------------- 1class Node { 2 Tree t; 3 Node next; 4 } 5class Queue { 6 Node head; 7 Node tail; 8 public void enque(Tree t){ 9 Node n = new Node(); 10 n.t = t; 11 if(!tail){ 12 tail = head = n; 13 } else { 14 tail.next = n; 15 tail = n; 16 } 17 } 18 public Tree deque() { 19 if (!head) { 20 return null; 21 } else { 22 Node n = head; 23 head = head.next; 24 return n.t; 25 } 26} 4、输出一个字符串所有排列。注意有重复字符。 1char[] p; 2void perm(char s[], int i, int n){ 3 int j; 4 char temp; 5 for(j=0;j

相关主题
文本预览
相关文档 最新文档