数据结构常见笔试题

简介:

反转一个无符号整数的比特位

Reverse the bits of an unsigned integer.

For example, x is 0x00001234, then reverse(x) is 0x2C480000.

复制代码
复制代码
static uint Reverse(uint x)
{
  uint y = 0;
  for (int i = 0; i < 32; ++i)
  {
    y <<= 1;
    y |= (x & 1);
    x >>= 1;
  }
  return y;
}
复制代码
复制代码

 删除数组中的重复元素

复制代码
复制代码
void remove_duplicate(int *a, int len)
{
  int i = 0;
  int j = 0;
  for (j = 0; j < len; j++) {
    if (a[i] == a[j])
      continue;
    else
      a[++i] = a[j];
  }
  printf("NEW LEN = %d\n", i + 1);
}
复制代码
复制代码

 插入排序

复制代码
复制代码
/* decreasing */
void insert_sort(int *a, int len)
{
  int i;
  int j;
  int key;
  for (i = 1; i < len; i++) {
    j = i;
    key = a[j];
    while (j > 0 && key > a[j-1]) {
      a[j] = a[j-1];
      j--;
    }
    a[j] = key;
  }
}
复制代码
复制代码

冒泡排序

复制代码
复制代码
for(int i =0; i < LEN; i++)
  for(int j = LEN -1; j > i; j--)
  {
    if(a[j] > a[j-1])
    {
      int temp = a[j];
      a[j] = a[j-1];
      a[j-1] = temp;
    }
  }
复制代码
复制代码

合并排序

复制代码
复制代码
void sort(int* &a, int p, int q, int r)
{
   int* left =new int[q - p +1];
   int* right =new int[r - q];
   for(int i =0; i < q - p +1; i++)
     left[i] = a[p + i];
   for(int i =0; i < r - q; i++)
     right[i] = a[q + i +1];

   int m =0;
   int n =0;

   for(int i = p; i <= r; i++) {
     if(left[m] <= right[n]) {
       a[i] = left[m];
       if(m++== q-p) {
         for(int j = i +1; j <= r; j++)
           a[j] = right[n++];
         break;
       }
     } else {
       a[i] = right[n];
       if(n++== r-q-1) {
         for(int j = i +1; j <= r; j++)
           a[j] = left[m++];
         break;
       }
     }
   }
   
   delete[] left;
   delete[] right;
}
void merge(int* &a, int m, int n)
{
  if(m < n) {
     int mid = (m + n)/2;
     merge(a, m, mid);
     merge(a, mid+1, n);
     sort(a, m, mid, n);
  }
}
复制代码
复制代码

堆排序

复制代码
复制代码
 static void max_heapify(int*&a, int i, int length)
 {
     int largest = i;
     while(largest <= length -1) {
         int left =2*largest +1;
         int right =2*largest +2;
         int temp = largest;
         if(left <= length -1&& a[left] > a[largest]) {
             largest = left;
         }
         if(right <= length -1&& a[right] > a[largest]) {
             largest = right;
         }
         if(largest != temp) {
             int exchange = a[largest];
             a[largest] = a[temp];
             a[temp] = exchange;
         } else {
             break;
         }
     }
 }
 
 void build_max_heap(int*&a, int length)
 {
     int root = length/2-1;
     for(int i = root; i >=0; i--)
         max_heapify(a, i, length);
 }
 
 void heap_sort(int*&a, int length)
 {
     build_max_heap(a, length);
     for(int i = length -1; i >=1; i--) {
         int temp = a[0];
         a[0] = a[i];
         a[i] = temp;
         max_heapify(a, 0, i);
     }
 }
 
 void heap_delete(int*&a, int i, int length)
 {
     if(i != length -1) {
         a[i] = a[length -1];
         max_heapify(a, i, length); 
     }
 }
 
 void heap_insert(int*&a, int x, int length)
 {
     int* temp = a;
     a = new int[length +1];
     for(int i =0; i < length; i++)
         a[i] = temp[i];
     delete temp;
     //用-10000000代替负无穷
     a[length] =-10000000;
     increase_key(a, length, x);
 }
 
 void increase_key(int*&a, int i, int key)
 {
     if(a[i] > key) {
         cout<<"key should be larger than a[i]"<<endl;
     } else {
         int parent = (i -1)/2;
         a[i] = key;
         while(parent >= 0 && a[parent] < key) {
             int temp = a[parent];
             a[parent] = key;
             a[i] = temp;
             i = parent;
             parent = (i -1)/2;
         }
     }
 }
复制代码
复制代码

快排

复制代码
复制代码
void quick_sort(int*&a, int p, int r)
{
    if(p < r)
    {
        int q = partition(a, p, r);
        quick_sort(a, p, q -1);
        quick_sort(a, q +1, r);
    }
}
int partition(int*&a, int p, int r)
{
    int j = p;
    for(int i = p; i < r; i++)
    {
        if(a[i] >= a[r])
        {
            if(i != j)
            {
                int temp = a[i];
                a[i] = a[j];
                a[j] = temp;
            }
            j++;
        }
    }
    int ex = a[j];
    a[j] = a[r];
    a[r] = ex;
    
    return j;
}
复制代码
复制代码

找第k小的数

复制代码
复制代码
#include <iostream>
#include <time.h>
using namespace std;
//随机化分割
int randomized_partition(int* a, int p, int r);
int randomized_select(int* a, int p, int r, int i);
int main()
{
    int arr[10] = {4, 34, 21, 8, 3, 10, 453, 32, 1, 400};
    int n;
    while(true)
    {
        cout<<"输入第n小的数:"<<endl;
        cin>>n;
        cout<<randomized_select(arr, 0, 9, n - 1)<<endl;
    }
    return 0;
}
//下标为[p, r]之间的元素
int randomized_partition(int* a, int p, int r)
{
    srand(time(NULL));
    int q = rand()%(r - p + 1) + p;
    int temp = a[q];
    a[q] = a[r];
    a[r] = temp;
    int j = p;
    for(int i = p; i < r; i++)
    {
        if(a[i] < a[r])
        {
            if(i != j)
            {
                int temp2 = a[i];
                a[i] = a[j];
                a[j] = temp2;
            }
            j++;
        }
    }
     
    temp = a[j];
    a[j] = a[r];
    a[r] = temp;
    return j;
}

int randomized_select(int* a, int p, int r, int i)
{
    int q = randomized_partition(a, p, r);
    while(p != r)
    {
        if(i == q)
            return a[q];
        else if(i < q)
        {
            r = q - 1;
            q = randomized_partition(a, p, r);
        }
        else
        {
            p = q + 1;
            q = randomized_partition(a, p, r);
        }
    }
    return a[p];
}
复制代码
复制代码

 树的表示

复制代码
复制代码
typedef struct CTNode { // 孩子结点
  int child;
  struct CTNode *next;
} *ChildPtr;
typedef struct {
  ElemType data; // 结点的数据元素
  ChildPtr firstchild; // 孩子链表头指针
} CTBox;
typedef struct {
  CTBox nodes[MAX_TREE_SIZE];
  int n, r; // 结点数和根结点的位置
} CTree;
复制代码
复制代码

 找二叉搜索树中的第K大的结点

复制代码
复制代码
/* Posted in Career Cup, I used showell30@yahoo.com's code to create the BST, thanks. */

#include <stdlib.h>
#include <stdio.h>
#include <assert.h>

struct Node {
    int val;
    struct Node *left;
    struct Node *right;
};
typedef struct Node node_t;

/* Core function 
 * Inorder, from right first.
 */
void find_by_inorder(node_t *root, int *count, node_t **result, int k)
{
    if (root != NULL) {
        find_by_inorder(root->right, count, result, k);
        (*count)++;
        if (*count == k) {
            *result = root;
return;
}    find_by_inorder(root
->left, count, result, k); } } node_t *make_node(int n) { node_t *node = malloc(sizeof(node_t)); node->left = NULL; node->right = NULL; node->val = n; return node; } int main(int argc, char **argv) { node_t *node; node_t *t1 = make_node(1); node_t *t2 = make_node(2); node_t *t3 = make_node(3); node_t *t4 = make_node(4); node_t *t5 = make_node(5); node_t *t6 = make_node(6); t2->left = t1; t2->right = t3; t4->left = t2; t4->right = t5; t5->right = t6; node_t *result = NULL; int count = 0; int i; /* Test */ for (i = 0; i < 10; i++) { find_by_inorder(t4, &count, &result, i); if (result != NULL) printf("%dth: %d\n", i, result->val); result = NULL; count = 0; } return 0; }
复制代码
复制代码

 判断一棵二叉树是否为二叉搜索树

 如果一上来直接判断一个结点的左孩子是否小于它,右孩子是否大于它,貌似正确,其实不然。下图就是反例。

 

 方法一:递归

复制代码
复制代码
// macros for comparison
#define greater(a,b) (a > b ? true:false)
#define between(a,b,c) ((a > b)&&(a < c) ? true:false)

// recursive function to which we pass root node and 
// the limits of the root node, if only positive numbers
// then we can pass 0 and  INFINITY

bool isBST(node* Node, int left_limit,int right_limit)
{
     // the node's value must be greater than its
     // left child
     if(!greater(Node->value,Node->left->value))
        return false;

     // the node's value must be smaller than its
     // right child
     if(!greater(Node->right->value,Node-> value))
        return false;

     // the node's value must be lie between it's
     // left and right limit
     if(!between(Node->value,left_limit,right_limit))
        return false;

     // to the left child pass the node's left limit as
     // as left limit and node's value as right limit
     bool left = isBST(Node-> left,left_limit,Node->value);

     // to the right child pass the node's value as left limit 
     // and node's right limit as right limit
     bool right = isBST(Node-> right,Node->value,right_limit);

     return left && right;
}
复制代码
复制代码

方法二:中序遍历,每个结点必须大于之前的结点。

复制代码
复制代码
stack< node* > S;
bool(node* root)
{
 prev,curr
 p = root 
 do 
 { 
   prev = curr;
   while ( p != null) // traverse LST
   { 
        S.push(p);
        p = p-> left; 
   }
   if (!S.empty())
   { 
        p = S.top();
        S.pop();
        curr=p->info; // visit root
        if(curr < prev)
           return false;
        p = p-> right; 
   } // traverse RST
 } while(!S.empty() || p != null)
}
复制代码
复制代码

 N皇后问题

 递归解法(转载自http://blog.csdn.net/hackbuteer1/article/details/6657109)

复制代码
复制代码
#include <stdio.h>
#include <stdlib.h>

/*
 * 把棋盘存储为一个N维数组a[N],数组中第i个元素的值代表第i行的皇后位置,
 * 这样便可以把问题的空间规模压缩维O(N),在判断是否冲突时也很简单,首先每行只有
 * 一个皇后,且在数组中只占据一个元素的位置,行冲突就不存在了,其次是列冲突,
 * 判断一下是否有a[i]与当前要放置皇后的列j相等即可。至于斜线冲突,通过观察可以
 * 发现所有在斜线上冲突的皇后的位置都有规律即它们所在的行列互减得绝对值相等,
 * 即| row – i | = | col – a[i] | 。这样某个位置是否可以放置皇后的问题已经解决。
 */

#define N 20   //最多放皇后的个数
int q[N];         //各皇后所在的行号
int count = 0;     //统计解得个数
//输出一个解
void print(int n)
{
    int i,j;
    count++;
    printf("第%d个解:",count);
    for(i=1;i<=n;i++)
        printf("(%d,%d) ",i,q[i]);
    printf("\n");
    for(i=1;i<=n;i++)        //
    {                
        for(j=1;j<=n;j++)    //
        {
            if(q[i]!=j)
                printf("x ");
            else 
                printf("Q "); 
        }
        printf("\n");
    }
}

//检验第i行的k列上是否可以摆放皇后
int find(int i,int k)  
{
    int j=1;
    while(j<i)  //j=1~i-1是已经放置了皇后的行
    {
        //第j行的皇后是否在k列或(j,q[j])与(i,k)是否在斜线上
        if(q[j]==k || abs(j-i)==abs(q[j]-k)) 
            return 0;
        j++;
    }
    return 1;
}

//放置皇后到棋盘上
void place(int k,int n)  
{
    int j;
    if(k>n)
        print(n);
    else
    {
        for(j=1;j<=n;j++)   //试探第k行的每一个列
        {
            if(find(k,j))
            {
                q[k] = j;
                place(k+1,n);  //递归总是在成功完成了上次的任务的时候才做下一个任务
            }
        }
    }
}

int main(void)
{
    int n;
    printf("请输入皇后的个数(n<=20),n=:");
    scanf("%d",&n);
    if(n>20)
        printf("n值太大,不能求解!\n");
    else
    {
        printf("%d皇后问题求解如下(每列的皇后所在的行数):\n",n);
        place(1,n);        //问题从最初状态解起
        printf("\n");
    }
    return 0;
}
复制代码
复制代码

非递归解法:(http://blog.csdn.net/pinkrobin/article/details/5378702)

复制代码
复制代码
/**
 * n皇后问题
 * date  : 2010-3-12
 * author: lee
 */

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#define QUEEN 8    // the number of the queen
#define INITIAL -10000  //defines the initial value of the board 

//container
int a[QUEEN];

//check if the queen can be placed on the position
int valid(int row, int col);
//initialize the board
void clear();
//print the result
void print();
//run the n-queen program 
void queen();

int main(void)
{
    clear();
    queen();
    return 0;
}

void clear()
{
    int *p;
    for (p = a; p < a + QUEEN; ++p) {
        *p = INITIAL;
    }
}

void print()
{
    int i, j;
    for (i = 0; i < QUEEN; ++i) {
        for (j = 0; j < QUEEN; ++j) {
            if (a[i] != j) 
                printf("%c ", '.');
            else 
                printf("%c ", '#');
        }
        printf("\n");
    }
    printf("--------------------------------------------\n");
}

int valid(int row, int col)
{
    int i;
    for (i = 0; i < QUEEN; ++i) {
        if (a[i] == col || abs(i - row) == abs(a[i] - col)) 
            return 0;
    }
    
    return 1;
}

void queen()
{
    int n = 0;
    int i = 0, j = 0;
    while (i < QUEEN) {    
        while (j < QUEEN) {
            if (valid(i, j)) { //test if the queen can be placed on the position
                a[i] = j;     //place the queen on the next line
                j = 0;
                break;
            } else {         // if not, check the next position
                ++j;
            }
        }
        
        if (a[i] == INITIAL) {   //if the current queen can't find its place
            if (i == 0)        // and this is the first line ,then program end
                break;
            else  {           //else   backtrack
                --i;
                j = a[i] + 1;
                a[i] = INITIAL;
                continue;
            }
        }
        
        if (i == QUEEN - 1) {  //already got a solution, print the result
            printf("answer %d : \n", ++n);
            print();
            j = a[i] + 1;
            a[i] = INITIAL;
            continue;
        } 

        ++i;      // go on to place the queen on the next line if has any more 
    }
}
复制代码
复制代码

 正方形判断问题

 给出四个点,它们的坐标都是整数,判断这四个点是否构成一个正方形

1. 选取第一个点p1,计算p1p2, p1p3, p1p4之间的距离大小。
2. 若三个距离中,有两个相等,且其中一个大于它们,则继续,否则返回false
3. 若两个向量相与,即(p1 - p2) & (p1 - p3)为零,则p1p2与p1p3垂直,继续。
    否则返回false
4. 若p2p3的中间点与p1p4的中间点相同,则是正方形,否则false

 LCA(Lowest Common Ancestor) 最低公共祖先

 情况一:二叉树

复制代码
复制代码
Node *LCA(Node *root, Node *p, Node *q)
{
    if (!root) 
        return NULL;
    if (root == p || root == q) 
        return root;
    Node *L = LCA(root->left, p, q);
    Node *R = LCA(root->right, p, q);
    if (L && R) 
        return root;      // 如果p和q位于不同的子树  
    return L ? L : R;     //p和q在相同的子树,或者p和q不在子树中
}
复制代码
复制代码

情况二:二叉搜索树

复制代码
复制代码
Node *LCA(Node *root, Node *p, Node *q) 
{
    if (!root || !p || !q) 
        return NULL;
    if (max(p->data, q->data) < root->data) 
        return LCA(root->left, p, q);
    else if (min(p->data, q->data) > root->data)
        return LCA(root->right, p, q);
    else
        return root;
}
复制代码
复制代码

 罐子问题

 10个罐子,每个中有一百个珠子,其中一个罐子中的珠子是每个 1.1g,另外九个罐子中的珠子都是每个1g,现在有一个秤,几次能够找出那个每个珠子1.1g的那个罐子?

 答:一次。

 把十个罐子按顺序摆放,一次从第n个罐子中取出n个珠子,然后把这55个珠子拿到秤上称重,得到重量为W。

 假设要找的罐子是第X个罐子,那么

 1 + 2 + ... + 10 + (1.1 - 1)*X = W,即55 + 0.1X = W,求出X即可。

最小公倍数和最大公约数的算法

复制代码
复制代码
//return the greatest common divisor
int gcd(int v1, int v2)
{
    while (v2) {
        int tmp = v2;
        v2 = v1 % v2;
        v1 = tmp;
    }
    return v1;
}
//递归方法
int rgcd(int v1, int v2)
{
if (v2 != 0)
return rgcd(v2, v1%v2);
return v1;
}
//least common multiple lcm(v1, v2) = (v1 * v2) / gcd(v1, v2);
复制代码
复制代码

 

来源:http://www.cnblogs.com/shuaiwhu/archive/2013/02/07/2908578.html#commentform





本文转自夏雪冬日博客园博客,原文链接:http://www.cnblogs.com/heyonggang/p/3310112.html,如需转载请自行联系原作者

目录
相关文章
|
缓存 算法 C语言
【数据结构与算法篇】栈与队列(详解)附加Leetcode经典笔试题
【数据结构与算法篇】栈与队列(详解)附加Leetcode经典笔试题
135 0
数据结构转换,笔试题系列
今天分享一道面试手写笔试题,主要是考察数据结构处理,以及数据引用问题
178 0
数据结构转换,笔试题系列
|
11月前
|
C语言
【数据结构】栈和队列(c语言实现)(附源码)
本文介绍了栈和队列两种数据结构。栈是一种只能在一端进行插入和删除操作的线性表,遵循“先进后出”原则;队列则在一端插入、另一端删除,遵循“先进先出”原则。文章详细讲解了栈和队列的结构定义、方法声明及实现,并提供了完整的代码示例。栈和队列在实际应用中非常广泛,如二叉树的层序遍历和快速排序的非递归实现等。
932 9
|
11月前
|
存储 算法
非递归实现后序遍历时,如何避免栈溢出?
后序遍历的递归实现和非递归实现各有优缺点,在实际应用中需要根据具体的问题需求、二叉树的特点以及性能和空间的限制等因素来选择合适的实现方式。
239 59
|
4月前
|
编译器 C语言 C++
栈区的非法访问导致的死循环(x64)
这段内容主要分析了一段C语言代码在VS2022中形成死循环的原因,涉及栈区内存布局和数组越界问题。代码中`arr[15]`越界访问,修改了变量`i`的值,导致`for`循环条件始终为真,形成死循环。原因是VS2022栈区从低地址到高地址分配内存,`arr`数组与`i`相邻,`arr[15]`恰好覆盖`i`的地址。而在VS2019中,栈区先分配高地址再分配低地址,因此相同代码表现不同。这说明编译器对栈区内存分配顺序的实现差异会导致程序行为不一致,需避免数组越界以确保代码健壮性。
76 0
栈区的非法访问导致的死循环(x64)
232.用栈实现队列,225. 用队列实现栈
在232题中,通过两个栈(`stIn`和`stOut`)模拟队列的先入先出(FIFO)行为。`push`操作将元素压入`stIn`,`pop`和`peek`操作则通过将`stIn`的元素转移到`stOut`来实现队列的顺序访问。 225题则是利用单个队列(`que`)模拟栈的后入先出(LIFO)特性。通过多次调整队列头部元素的位置,确保弹出顺序符合栈的要求。`top`操作直接返回队列尾部元素,`empty`判断队列是否为空。 两题均仅使用基础数据结构操作,展示了栈与队列之间的转换逻辑。
|
9月前
|
存储 C语言 C++
【C++数据结构——栈与队列】顺序栈的基本运算(头歌实践教学平台习题)【合集】
本关任务:编写一个程序实现顺序栈的基本运算。开始你的任务吧,祝你成功!​ 相关知识 初始化栈 销毁栈 判断栈是否为空 进栈 出栈 取栈顶元素 1.初始化栈 概念:初始化栈是为栈的使用做准备,包括分配内存空间(如果是动态分配)和设置栈的初始状态。栈有顺序栈和链式栈两种常见形式。对于顺序栈,通常需要定义一个数组来存储栈元素,并设置一个变量来记录栈顶位置;对于链式栈,需要定义节点结构,包含数据域和指针域,同时初始化栈顶指针。 示例(顺序栈): 以下是一个简单的顺序栈初始化示例,假设用C语言实现,栈中存储
371 77
|
8月前
|
算法 调度 C++
STL——栈和队列和优先队列
通过以上对栈、队列和优先队列的详细解释和示例,希望能帮助读者更好地理解和应用这些重要的数据结构。
191 11
|
8月前
|
DataX
☀☀☀☀☀☀☀有关栈和队列应用的oj题讲解☼☼☼☼☼☼☼
### 简介 本文介绍了三种数据结构的实现方法:用两个队列实现栈、用两个栈实现队列以及设计循环队列。具体思路如下: 1. **用两个队列实现栈**: - 插入元素时,选择非空队列进行插入。 - 移除栈顶元素时,将非空队列中的元素依次转移到另一个队列,直到只剩下一个元素,然后弹出该元素。 - 判空条件为两个队列均为空。 2. **用两个栈实现队列**: - 插入元素时,选择非空栈进行插入。 - 移除队首元素时,将非空栈中的元素依次转移到另一个栈,再将这些元素重新放回原栈以保持顺序。 - 判空条件为两个栈均为空。
|
9月前
|
存储 C++ 索引
【C++数据结构——栈与队列】环形队列的基本运算(头歌实践教学平台习题)【合集】
【数据结构——栈与队列】环形队列的基本运算(头歌实践教学平台习题)【合集】初始化队列、销毁队列、判断队列是否为空、进队列、出队列等。本关任务:编写一个程序实现环形队列的基本运算。(6)出队列序列:yzopq2*(5)依次进队列元素:opq2*(6)出队列序列:bcdef。(2)依次进队列元素:abc。(5)依次进队列元素:def。(2)依次进队列元素:xyz。开始你的任务吧,祝你成功!(4)出队一个元素a。(4)出队一个元素x。
295 13
【C++数据结构——栈与队列】环形队列的基本运算(头歌实践教学平台习题)【合集】

热门文章

最新文章