C++数据结构面试题

原文:http://1527zhaobin.iteye.com/blog/1537110

一.判断链表是否存在环型链表问题:

  说明:判断一个链表是否存在环,例如下面这个链表就存在环,n1-->n2-->n3-->n4-->n5-->n2,环的开始结点是n5

解法:这里有个比较简单的解法:设两个指针p1,p2,每次循环p1向前走一步,之向前走两步,直到p2碰到NULL指针(无环)或两个指针相等结束循环算法(有环),即如果两个指针相等则说明存在环。

代码如下:

[cpp] view plaincopyprint?

  1. /*节点数据结构*/
  2. struct link{
  3. int data;
  4. link * next;
  5. };
  6. /*
  7. *判断是否有环的方法
  8. *
  9. *参数来头节点的指针
  10. */
  11. bool isLoop(link * head){
  12. //p1步长为1;p2步长为2
  13. link* p1 = head,*p2 = head;
  14. //如果只有一个节点或两个节点,直接return false
  15. if(head == NULL || head->next == NULL){
  16. return false;
  17. }
  18. //循环前进,直到p2走到NULL或p2追上p1
  19. do{
  20. p1 = p1->next;
  21. p2 = p2->next->next;
  22. }while(p2 && p2->next && p1!=p2);
  23. //如果有环
  24. if(p1 == p2){
  25. return true;
  26. else
  27. return false;
  28. }

Cpp代码

  1. /*节点数据结构*/
  2. struct link{
  3. int data;
  4. link * next;
  5. };
  6. /*
  7. *判断是否有环的方法
  8. *
  9. *参数来头节点的指针
  10. */
  11. bool isLoop(link * head){
  12. //p1步长为1;p2步长为2
  13. link* p1 = head,*p2 = head;
  14. //如果只有一个节点或两个节点,直接return false
  15. if(head == NULL || head->next == NULL){
  16. return false;
  17. }
  18. //循环前进,直到p2走到NULL或p2追上p1
  19. do{
  20. p1 = p1->next;
  21. p2 = p2->next->next;
  22. }while(p2 && p2->next && p1!=p2);
  23. //如果有环
  24. if(p1 == p2){
  25. return true;
  26. else
  27. return false;
  28. }

二.链表反转:

说明:链表反转,比如原链表是1-->2-->3-->4-->5 通过反转后成为5-->4-->3-->2-->1

解法一:利用三个指针,指向当前要反转的节点的指针,这个当前节点之前的节点指针,这个当前节点之后的节点指针;反转后再向后继续遍历

代码如下:

[cpp] view plaincopyprint?

  1. /*节点数据结构*/
  2. struct linka{
  3. int data;
  4. link * next;
  5. };
  6. /*
  7. *反转
  8. *
  9. *参数:头节点的指针的引用
  10. */
  11. bool reverse(link * &head){
  12. //只有一个节点,即不用反转,直接返回
  13. if(head == NULL)
  14. return;
  15. //定义3个辅助指针,pre指向当前要反转的节点的前一个节点;cur为当前要反转的节点;ne指向当前反转的节点的下一个节点
  16. linka * pre,*cur,*ne;
  17. //初始化指针
  18. pre = head;
  19. cur = head->next;
  20. //循环,直到cur为NULL
  21. while(cur){
  22. ne = cur->next;
  23. cur->next = pre;
  24. pre = cur;
  25. cur = ne;
  26. }
  27. //反转到最后,设置头节点指针
  28. head->next = NULL;
  29. head = pre;
  30. }

Cpp代码

  1. /*节点数据结构*/
  2. struct linka{
  3. int data;
  4. link * next;
  5. };
  6. /*
  7. *反转
  8. *
  9. *参数:头节点的指针的引用
  10. */
  11. bool reverse(link * &head){
  12. //只有一个节点,即不用反转,直接返回
  13. if(head == NULL)
  14. return;
  15. //定义3个辅助指针,pre指向当前要反转的节点的前一个节点;cur为当前要反转的节点;ne指向当前反转的节点的下一个节点
  16. linka * pre,*cur,*ne;
  17. //初始化指针
  18. pre = head;
  19. cur = head->next;
  20. //循环,直到cur为NULL
  21. while(cur){
  22. ne = cur->next;
  23. cur->next = pre;
  24. pre = cur;
  25. cur = ne;
  26. }
  27. //反转到最后,设置头节点指针
  28. head->next = NULL;
  29. head = pre;
  30. }

解法二:利用递归。这种方法的基本思想是在反转当前节点之前先调用递归函数反转后续节点。不过,这个方法有个缺点:在反转后的最后一个节点会形成一个环,所以必须将函数的返回节点的next设为NULL.因为要改变head指针,所以我用了引用

代码如下:

[cpp] view plaincopyprint?

  1. /*节点数据结构*/
  2. struct linka{
  3. int data;
  4. link * next;
  5. };
  6. /*
  7. *反转
  8. *
  9. *参数:头节点的指针的引用
  10. */
  11. linka * reverse(linka * p,link * &head){
  12. if(p == NULL || p->next == NULL){
  13. head = p;
  14. return p;
  15. }else {
  16. linka* tmp = reverse(p->next,head);
  17. tmp->next = p;
  18. return p;
  19. }
  20. }

Cpp代码

  1. /*节点数据结构*/
  2. struct linka{
  3. int data;
  4. link * next;
  5. };
  6. /*
  7. *反转
  8. *
  9. *参数:头节点的指针的引用
  10. */
  11. linka * reverse(linka * p,link * &head){
  12. if(p == NULL || p->next == NULL){
  13. head = p;
  14. return p;
  15. }else {
  16. linka* tmp = reverse(p->next,head);
  17. tmp->next = p;
  18. return p;
  19. }
  20. }

三.链表的合并:

说明:递增有序的2个单链表合并成一个递增有序的单链表,不用任何库函数调用

代码如下:

[cpp] view plaincopyprint?

  1. <pre name="code" class="cpp">#include <iostream>
  2. using namespace std;
  3. /* 单链表节点 */
  4. struct node{
  5. int value;
  6. node* next;
  7. };
  8. /* 给单链表添加节点 */
  9. void insertNode(node* head, int value){
  10. node* p = head->next;
  11. if ( p == NULL ){
  12. p = new node;
  13. p->value = value;
  14. p->next = NULL;
  15. head->next = p;
  16. return;
  17. }
  18. while ( p->next != NULL ){
  19. p = p->next;
  20. }
  21. node* tmp = new node;
  22. tmp->value = value;
  23. tmp->next = NULL;
  24. p->next = tmp;
  25. }
  26. /* 遍历输出链表节点 */
  27. void print(node* head){
  28. node* p = head->next;
  29. while ( p != NULL ){
  30. cout << p->value << " ";
  31. p = p->next;
  32. }
  33. cout << endl;
  34. }
  35. /* 下面实现不使用任何库函数, 利用交换的方法在原空间实现整体有序。 方法是先确定哪一个链表
  36. 的第一个节点的值小,把这个链表的头结点作为合并后链表的头结点,然后比较2个有序链表的当前节点
  37. 的值,如果代表最后合并链表的值小,则不用交换,否则把两个值交换,最后合并链表始终保持两个值中
  38. 的小值。另一个链表由于交换了一个元素,当前元素可能影响该链表的有序递增,对其进行调整使其保持
  39. 递增有序,然后重复上述动作,直到一个链表遍历结束,然后把剩余的链表连接起来就行。*/
  40. /* 调整链表的第一个节点,使其变成递增有序 */
  41. void chg2sort(node* head, node* &p){
  42. if (head->next == NULL ){ //没有节点,直接返回
  43. return;
  44. }
  45. node* s = head;
  46. while ( s->next != p ){ //s指向p的前一个节点
  47. s = s->next;
  48. }
  49. //下面的一段找到第一个大于p节点值的节点
  50. node* q = p;
  51. node* r = q;
  52. while ( q != NULL ){
  53. if ( q->value <= p->value ){
  54. r = q; //r始终指向q的前一个节点
  55. q = q->next;
  56. }else {
  57. break;
  58. }
  59. }
  60. //下面调整指针,其实可以统一写出来,为了阅读清晰把q为NULL和非NULL分开写出来
  61. if ( q == NULL ){
  62. r->next = p;
  63. s->next = p->next;
  64. p->next = NULL;
  65. }else if ( q != NULL ){
  66. s->next = p->next;
  67. r->next = p;
  68. p->next = q;
  69. }
  70. //由于链表进行了调换,当前链表指针也需要改变
  71. p = s->next;
  72. }
  73. /* 两个有序链表进行合并 */
  74. node* merge(node* head1, node* head2){
  75. node* head; //合并后的头指针
  76. node* p = head1->next;
  77. node* q = head2->next;
  78. //有一个链表为空的情况,直接返回另一个链表
  79. if ( p == NULL ){
  80. head = head2;
  81. return head;
  82. }else if ( q == NULL ){
  83. head = head1;
  84. return head;
  85. }
  86. //两个都不为空,先确定哪个链表作为合并后的链表
  87. if ( (p != NULL) && (q != NULL) ){
  88. if ( p->value < q->value ){
  89. head = head1;
  90. }else{
  91. head = head2;
  92. }
  93. }
  94. node* p_prior; //始终指向p节点的前一个节点
  95. node* q_prior;
  96. while ( (p != NULL) && (q != NULL) ){
  97. if ( p ->value < q->value ){
  98. if ( head == head1 ){//如果链表1的值小于链表2的值,链表1的指针向下指
  99. p_prior = p;
  100. p = p->next;
  101. }else if ( head == head2 ){
  102. //进行当前节点值的交换
  103. int tmp = p->value;
  104. p->value = q->value;
  105. q->value = tmp;
  106. chg2sort(head1, p); //交换元素后的调整
  107. q_prior = q;
  108. q = q->next;
  109. }
  110. }else if ( p->value == q->value ){//链表1的值等于链表2时,两链表指针都向下指
  111. p_prior = p;
  112. p = p->next;
  113. q_prior = q;
  114. q = q->next;
  115. }else if ( p->value > q->value ){
  116. if ( head == head1 ){//如果链表1的值大于链表2的值,交接两节点的值后,排序链表2后,再下指
  117. int tmp = p->value;
  118. p->value = q->value;
  119. q->value = tmp;
  120. chg2sort(head2, q);
  121. p_prior = p;
  122. p = p->next;
  123. }else if ( head == head2 ){
  124. q_prior = q;
  125. q = q->next;
  126. }
  127. }
  128. }
  129. if ( p != NULL ){
  130. q_prior->next = p;
  131. }
  132. if ( q != NULL ){
  133. p_prior->next = q;
  134. }
  135. return head;
  136. }
  137. int main(){
  138. /* 建立有序链表A */
  139. int a[5] = {1, 5, 8, 10, 20};
  140. node* headA = new node;
  141. headA->next = NULL;
  142. for (int i = 0; i < 5; ++i){
  143. insertNode(headA, a[i]);
  144. }
  145. print(headA);
  146. /* 建立有序链表B */
  147. int b[3] = {3, 4, 9};
  148. node* headB = new node;
  149. headB->next = NULL;
  150. for (int i = 0; i < 3; ++i){
  151. insertNode(headB, b[i]);
  152. }
  153. print(headB);
  154. head = merge(headA, headB);
  155. print(head);
  156. return 0;
  157. }

Cpp代码

  1. <pre name="code" class="cpp">#include <iostream>
  2. using namespace std;
  3. /* 单链表节点 */
  4. struct node{
  5. int value;
  6. node* next;
  7. };
  8. /* 给单链表添加节点 */
  9. void insertNode(node* head, int value){
  10. node* p = head->next;
  11. if ( p == NULL ){
  12. p = new node;
  13. p->value = value;
  14. p->next = NULL;
  15. head->next = p;
  16. return;
  17. }
  18. while ( p->next != NULL ){
  19. p = p->next;
  20. }
  21. node* tmp = new node;
  22. tmp->value = value;
  23. tmp->next = NULL;
  24. p->next = tmp;
  25. }
  26. /* 遍历输出链表节点 */
  27. void print(node* head){
  28. node* p = head->next;
  29. while ( p != NULL ){
  30. cout << p->value << " ";
  31. p = p->next;
  32. }
  33. cout << endl;
  34. }
  35. /* 下面实现不使用任何库函数, 利用交换的方法在原空间实现整体有序。 方法是先确定哪一个链表
  36. 的第一个节点的值小,把这个链表的头结点作为合并后链表的头结点,然后比较2个有序链表的当前节点
  37. 的值,如果代表最后合并链表的值小,则不用交换,否则把两个值交换,最后合并链表始终保持两个值中
  38. 的小值。另一个链表由于交换了一个元素,当前元素可能影响该链表的有序递增,对其进行调整使其保持
  39. 递增有序,然后重复上述动作,直到一个链表遍历结束,然后把剩余的链表连接起来就行。*/
  40. /* 调整链表的第一个节点,使其变成递增有序 */
  41. void chg2sort(node* head, node* &p){
  42. if (head->next == NULL ){ //没有节点,直接返回
  43. return;
  44. }
  45. node* s = head;
  46. while ( s->next != p ){ //s指向p的前一个节点
  47. s = s->next;
  48. }
  49. //下面的一段找到第一个大于p节点值的节点
  50. node* q = p;
  51. node* r = q;
  52. while ( q != NULL ){
  53. if ( q->value <= p->value ){
  54. r = q; //r始终指向q的前一个节点
  55. q = q->next;
  56. }else {
  57. break;
  58. }
  59. }
  60. //下面调整指针,其实可以统一写出来,为了阅读清晰把q为NULL和非NULL分开写出来
  61. if ( q == NULL ){
  62. r->next = p;
  63. s->next = p->next;
  64. p->next = NULL;
  65. }else if ( q != NULL ){
  66. s->next = p->next;
  67. r->next = p;
  68. p->next = q;
  69. }
  70. //由于链表进行了调换,当前链表指针也需要改变
  71. p = s->next;
  72. }
  73. /* 两个有序链表进行合并 */
  74. node* merge(node* head1, node* head2){
  75. node* head; //合并后的头指针
  76. node* p = head1->next;
  77. node* q = head2->next;
  78. //有一个链表为空的情况,直接返回另一个链表
  79. if ( p == NULL ){
  80. head = head2;
  81. return head;
  82. }else if ( q == NULL ){
  83. head = head1;
  84. return head;
  85. }
  86. //两个都不为空,先确定哪个链表作为合并后的链表
  87. if ( (p != NULL) && (q != NULL) ){
  88. if ( p->value < q->value ){
  89. head = head1;
  90. }else{
  91. head = head2;
  92. }
  93. }
  94. node* p_prior; //始终指向p节点的前一个节点
  95. node* q_prior;
  96. while ( (p != NULL) && (q != NULL) ){
  97. if ( p ->value < q->value ){
  98. if ( head == head1 ){//如果链表1的值小于链表2的值,链表1的指针向下指
  99. p_prior = p;
  100. p = p->next;
  101. }else if ( head == head2 ){
  102. //进行当前节点值的交换
  103. int tmp = p->value;
  104. p->value = q->value;
  105. q->value = tmp;
  106. chg2sort(head1, p); //交换元素后的调整
  107. q_prior = q;
  108. q = q->next;
  109. }
  110. }else if ( p->value == q->value ){//链表1的值等于链表2时,两链表指针都向下指
  111. p_prior = p;
  112. p = p->next;
  113. q_prior = q;
  114. q = q->next;
  115. }else if ( p->value > q->value ){
  116. if ( head == head1 ){//如果链表1的值大于链表2的值,交接两节点的值后,排序链表2后,再下指
  117. int tmp = p->value;
  118. p->value = q->value;
  119. q->value = tmp;
  120. chg2sort(head2, q);
  121. p_prior = p;
  122. p = p->next;
  123. }else if ( head == head2 ){
  124. q_prior = q;
  125. q = q->next;
  126. }
  127. }
  128. }
  129. if ( p != NULL ){
  130. q_prior->next = p;
  131. }
  132. if ( q != NULL ){
  133. p_prior->next = q;
  134. }
  135. return head;
  136. }
  137. int main(){
  138. /* 建立有序链表A */
  139. int a[5] = {1, 5, 8, 10, 20};
  140. node* headA = new node;
  141. headA->next = NULL;
  142. for (int i = 0; i < 5; ++i){
  143. insertNode(headA, a[i]);
  144. }
  145. print(headA);
  146. /* 建立有序链表B */
  147. int b[3] = {3, 4, 9};
  148. node* headB = new node;
  149. headB->next = NULL;
  150. for (int i = 0; i < 3; ++i){
  151. insertNode(headB, b[i]);
  152. }
  153. print(headB);
  154. head = merge(headA, headB);
  155. print(head);
  156. return 0;
  157. }

如果可以用库函数合并的话:代码如下:

[cpp] view plaincopyprint?

  1. Node* mergeAction(Node* head1, Node* head2){
  2. //两个链表的合并操作
  3. Node* head=(Node*)malloc(sizeof(Node));
  4. Node* q=head; //q指向合并后的链表的最后一个
  5. while(head1 && head2){ //
  6. if(head1->data<=head2->data){
  7. Node* p=(Node*)malloc(sizeof(Node)); //p是新生节点的指针
  8. p->data=head1->data;
  9. p->next=NULL;
  10. q->next=p;
  11. q=q->next;
  12. head1=head1->next;
  13. }
  14. else if(head1->data > head2->data){
  15. Node* p=(Node*)malloc(sizeof(Node));
  16. p->data=head2->data;
  17. p->next=NULL;
  18. q->next=p;
  19. q=q->next;
  20. head2=head2->next;
  21. }
  22. }
  23. return head->next;
  24. }

Cpp代码

  1. Node* mergeAction(Node* head1, Node* head2){
  2. //两个链表的合并操作
  3. Node* head=(Node*)malloc(sizeof(Node));
  4. Node* q=head; //q指向合并后的链表的最后一个
  5. while(head1 && head2){ //
  6. if(head1->data<=head2->data){
  7. Node* p=(Node*)malloc(sizeof(Node)); //p是新生节点的指针
  8. p->data=head1->data;
  9. p->next=NULL;
  10. q->next=p;
  11. q=q->next;
  12. head1=head1->next;
  13. }
  14. else if(head1->data > head2->data){
  15. Node* p=(Node*)malloc(sizeof(Node));
  16. p->data=head2->data;
  17. p->next=NULL;
  18. q->next=p;
  19. q=q->next;
  20. head2=head2->next;
  21. }
  22. }
  23. return head->next;
  24. }

四.判断两个数组中是否存在相同的数字,给定两个排好序的数据,怎么高效得判断这两个数组中存在相同的数字:

说明:O(n)算法,因为两个数组都是排序好的,所以只要一次遍历就行了,首先设两个下标,分别初始化为两个数
组的起始地址,依次向前推进,推进的规则是比较两个数组中的数字,小的那个数组的下标各前推进一步,直到任何一个数组的下标到达数组末尾时,如果这时还没
碰到相同的数字,说明数组中没有相同的数字。

代码如下:

[cpp] view plaincopyprint?

  1. bool findcommon2(int a[], int size1,int b[],int size2){
  2. int i = 0, j = 0;
  3. while(i<size1 && j<size2){
  4. if(a[i]==b[j])
  5. return true;
  6. if(a[i]>b[j])
  7. j++;//j标记b数组
  8. if(a[i]<b[j])
  9. i++;//i标记a数组
  10. }
  11. return false;
  12. }

Cpp代码

  1. bool findcommon2(int a[], int size1,int b[],int size2){
  2. int i = 0, j = 0;
  3. while(i<size1 && j<size2){
  4. if(a[i]==b[j])
  5. return true;
  6. if(a[i]>b[j])
  7. j++;//j标记b数组
  8. if(a[i]<b[j])
  9. i++;//i标记a数组
  10. }
  11. return false;
  12. }

五.按单词反转字符串:

说明:单词用空格分开,如,Here is blog.csdn.net/wufenglong
经过反转后变为:blog.csdn.net/wufenglong is
Here如果只是简单的将所有字符串翻转的话,可以遍历字符串,将第一个字符和最后一个交换,第二个和倒数第二个交换,依次循环。其实按照单词反转的话可
以在第一遍遍历的基础上,再遍历一遍字符串,对每一个单词再反转一次,这样每个单词又恢复了原来的顺序

代码如下:

[cpp] view plaincopyprint?

  1. char * reverse_word(const char *str){
  2. int len = strlen(str);
  3. char * restr = new char[len+1];
  4. strcpy(restr,str);
  5. //首尾交换,i是首的索引 j是尾的索引
  6. for(int i=0,j=len-1;i<j;i++,j--){
  7. char tmp = restr[i];
  8. restr[i] = restr[j];
  9. restr[j] = tmp;
  10. }
  11. //再把每个单词反转
  12. int i,j,k = 0;
  13. while(k<len){
  14. i=j=k;
  15. while(restr[j]!=‘ ‘ && restr[j]!=‘\0‘)
  16. j++;//j为空格的索引
  17. k = j+1;//k为
  18. j--;
  19. //反转单词
  20. for(;i<j;i++,j--){
  21. char tmp = restr[i];
  22. restr[i] = restr[j];
  23. restr[j] = tmp;
  24. }
  25. }
  26. return restr;
  27. }

Cpp代码

  1. char * reverse_word(const char *str){
  2. int len = strlen(str);
  3. char * restr = new char[len+1];
  4. strcpy(restr,str);
  5. //首尾交换,i是首的索引 j是尾的索引
  6. for(int i=0,j=len-1;i<j;i++,j--){
  7. char tmp = restr[i];
  8. restr[i] = restr[j];
  9. restr[j] = tmp;
  10. }
  11. //再把每个单词反转
  12. int i,j,k = 0;
  13. while(k<len){
  14. i=j=k;
  15. while(restr[j]!=‘ ‘ && restr[j]!=‘\0‘)
  16. j++;//j为空格的索引
  17. k = j+1;//k为
  18. j--;
  19. //反转单词
  20. for(;i<j;i++,j--){
  21. char tmp = restr[i];
  22. restr[i] = restr[j];
  23. restr[j] = tmp;
  24. }
  25. }
  26. return restr;
  27. }

六.字符串反转:

题意:给定一个字符串,一个这个字符串的子串,将第一个字符串反转,但保留子串的顺序不变。

例如:输入 每一个串 “this is wufl‘s Chinese site: http://blog.csdn.net/wufenglong”

子串:“wufl”

输出: gnolgnefuw/tne.ndsc/golb//:ptth:eits esenihC s‘wufl si siht

说明:一般的方法是先扫描一边第一个字符串,然后用stack把它反转,同时记录下子串出现的位置。然后再扫描一遍把记录下来的子串再用stack反转,我用的方法是用一遍扫描数组的方法,扫描中如果发现子串,就将子串倒过来压入堆栈。

代码如下:

[cpp] view plaincopyprint?

  1. #include <stack>
  2. using namespace std;
  3. //reverse the string ‘s1‘ ,the substring ‘token‘
  4. const char * reverse(const char * s1, const char * token){
  5. assert(s1 && token);
  6. stack<char> stack1;
  7. const char * ptoken = token, *head = s1, *rear =s1;
  8. while(*head !=‘‘){
  9. while(*head !=‘‘ && *ptoken == *head){
  10. ptoken++;
  11. head++;
  12. }
  13. if(*ptoken==‘‘){
  14. const char *p;
  15. for(p=head-1;p>=rear;p--){
  16. stark1.push(*p);
  17. }
  18. ptoken = token;
  19. rear = head;
  20. }else{
  21. stack1.push(*rear);
  22. head = ++rear;
  23. ptoken = token;
  24. }
  25. }
  26. char * returnV = new char[strlen(s1)+1];
  27. int i=0;
  28. while(!stack1.empty()){
  29. returnV[i++] = stack1.top();
  30. stack1.top();
  31. }
  32. returnV[i]="";
  33. return returnV;
  34. }

Cpp代码

    1. #include <stack>
    2. using namespace std;
    3. //reverse the string ‘s1‘ ,the substring ‘token‘
    4. const char * reverse(const char * s1, const char * token){
    5. assert(s1 && token);
    6. stack<char> stack1;
    7. const char * ptoken = token, *head = s1, *rear =s1;
    8. while(*head !=‘‘){
    9. while(*head !=‘‘ && *ptoken == *head){
    10. ptoken++;
    11. head++;
    12. }
    13. if(*ptoken==‘‘){
    14. const char *p;
    15. for(p=head-1;p>=rear;p--){
    16. stark1.push(*p);
    17. }
    18. ptoken = token;
    19. rear = head;
    20. }else{
    21. stack1.push(*rear);
    22. head = ++rear;
    23. ptoken = token;
    24. }
    25. }
    26. char * returnV = new char[strlen(s1)+1];
    27. int i=0;
    28. while(!stack1.empty()){
    29. returnV[i++] = stack1.top();
    30. stack1.top();
    31. }
    32. returnV[i]="";
    33. return returnV;
    34. }

1.    在一个单链表中p所指结点之前插入一个s (值为e)所指结点时,可执行如下操作:
q=head;
while (q->next!=p)   q=q->next;
s= new   Node; 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->next;
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

--------------------------------------------------------------------------------------------------
1.    栈操作数据的原则是( ),队列操作数据的原则是 ( ) 。

2.    在栈中,可进行插入和删除操作的一端称    。

3.    栈和队列都是____结构;对于栈只能在____插入和删除元素;对于队列只能在____插入元素和____删除元素。

4.    栈结构通常采用的两种存储结构是    和    。

5.    计算机在运行递归程序时,要用到    提供的栈。

6.    一个栈的入栈序列a,b,c,d,e,则栈的不可能的输出序列是____。
A. edcba B. decba C. dceab D. abcde

7.    一个队列的数据入列序列是1,2,3,4,则队列的出队时输出序列是____ 。
A. 4,3,2,1        B. 1,2,3,4 C. 1,4,3,2        D. 3,2,4,1

8.    判断一个表达式中左右括号是否匹配,采用 ____ 实现较为方便。
A 线性表的顺序存储        B 队列        C 线性表的链式存储        D 栈

9.    栈与一般线性表区别主要在方面    。
A 元素个数        B 元素类型        C 逻辑结构        D 插入、删除元素的位置

10.    “假上溢”现象会出现在     中。  
A   循环队列             B 队列             C 链队列             D 顺序队列

11.    在一个链队中,假设F和R分别是队首和队尾指针,则删除一个结点的运算是 。  
A   R=F->next;       B   R=R->next;       C   F=F->next;             D   F=R->next;

12.    表达式a*(b+c)-d的后缀表达式是 。
A.abcd*+-             B. abc+*d-             C. abc*+d-             D. -+*abcd

C++数据结构面试题

时间: 2024-10-09 19:53:38

C++数据结构面试题的相关文章

Java数据结构面试题

1.栈和队列的共同特点是(只允许在端点处插入和删除元素) 4.栈通常采用的两种存储结构是(线性存储结构和链表存储结构) 5.下列关于栈的叙述正确的是(D)      A.栈是非线性结构B.栈是一种树状结构C.栈具有先进先出的特征D.栈有后进先出的特征 6.链表不具有的特点是(B)A.不必事先估计存储空间       B.可随机访问任一元素 C.插入删除不需要移动元素      D.所需空间与线性表长度成正比 7.用链表表示线性表的优点是(便于插入和删除操作) 8.在单链表中,增加头结点的目的是(

算法与数据结构面试题 网盘下载

网盘下载地址:点击下载 网盘下载地址:点击下载 更多面试题下载地址:https://www.zy139.cn/content/2019/2/11/182.html 原文地址:https://www.cnblogs.com/xuanxuan2015/p/10664004.html

算法和数据结构面试题

1.求子数组的最大和 例如输入的数组为1, -2, 3, 10, -4, 7, 2, -5,和最大的子数组为3, 10, -4, 7, 2,因此输出为该子数组的和18. 因为是O(N)的复杂度,因此需采用的DP的思想,记录下当前元素之和(为其最优状态,既最大),将其与目前所得的最大和比较,若大于则更新,否则继续.状态的累加遵循这个过程:如果当前和小于0,则放弃该状态,将其归零. //求子数组的最大和//利用的是dp的思想,依次遍历数组中的每个元素,把他们相加,如果加起来小于0,则//把当前元素之

数据库面试题(转)

数据库面试题(转) 基础: 1. 数据抽象:物理抽象.概念抽象.视图级抽象,内模式.模式.外模式 2. SQL语言包括数据定义.数据操纵(Data Manipulation),数据控制(Data Control) 数据定义:Create Table,Alter Table,Drop Table, Craete/Drop Index等 数据操纵:Select ,insert,update,delete, 数据控制:grant,revoke 3. SQL常用命令: CREATE TABLE Stud

数据库面试题(一)

在面试应聘的SQL Server数据库开发人员时,我运用了一套标准的基准技术问题.下面这些问题是我觉得能够真正有助于淘汰不合格应聘者的问题.它们按照从易到难的顺序排列.当你问到关于主键和外键的问题时,后面的问题都十分有难度,因为答案可能会更难解释和说明,尤其是在面试的情形下. 你能向我简要叙述一下SQL Server 2000中使用的一些数据库对象吗? 你希望听到的答案包括这样一些对象:表格.视图.用户定义的函数,以及存储过程;如果他们还能够提到像触发器这样的对象就更好了.如果应聘者不能回答这个

Shell在大数据的魅力时代:从一点点思路百度大数据面试题

供Linux开发中的同学们,Shell这可以说是一个基本功. 对于同学们的操作和维护.Shell也可以说是一种必要的技能,Shell.对于Release Team,软件配置管理的同学来说.Shell也起到了非常关键的数据.尤其是分布式系统发展的如火如荼,非常多开源项目都开展的如火如荼(好像不是分布式的系统都不好意思拿出来说事).分布式系统的配置.管理,Shell也起到了非常关键的数据,尽管仅仅是简单的文件拷贝,可是谁让Shell天生是做这些的呢? 当然了,以上不是本文的主题.本文的主题是Shel

大数据面试题汇总(不断更新中)

结合自身面试经历,包括BAT.SF.中信等等公司所做的面试题汇总.主要包括以下几大类: 一.spark相关 1.Spark的Shuffle原理及调优? 2.hadoop和spark使用场景? 3.spark如何保证宕机迅速恢复? 4.hadoop和spark的相同点和不同点? 5.RDD持久化原理? 6.checkpoint检查点机制? 7.checkpoint和持久化机制的区别? 8.Spark Streaming和Storm有何区别?  9.RDD机制?  10.Spark streamin

2018年大数据面试题总结

目前面试了多家大数据开发工程师,成长了很多,也知道了很多知识,下面和大家分享一下我遇到的面试题和答案. 1.kafka集群的规模,消费速度是多少. 答:一般中小型公司是10个节点,每秒20M左右. 2.hdfs上传文件的流程. 答:这里描述的 是一个256M的文件上传过程 ① 由客户端 向 NameNode节点节点 发出请求 ②NameNode 向Client返回可以可以存数据的 DataNode 这里遵循机架感应原则 ③客户端 首先 根据返回的信息 先将 文件分块(Hadoop2.X版本 每一

117道有关大数据面试题解析,希望对你有所帮助

一 .简述如何安装配置apache 的一个开源的hadoop 使用root账户登陆 2.修改ip 3.修改host主机名 4.配置ssh 免密登陆 5.关闭防火墙 6.安装JDK 7.解压hadoop安装包 8.配置hadoop的核心配置文件 hadoop-env.sh? core-site.xml? mapred-site.xml yarn-site.xml hdfs-site.xml 9.配置hadoop 的环境变量 10 .格式化hadoop namenode-format 启动节点sta