当前位置:   article > 正文

剑指Offer --- C++ 栈,队列,排序算法_剑指offer 深度优先 堆栈

剑指offer 深度优先 堆栈

1.用两个栈实现队列

思路:一个栈用来负责入队,一个栈用来负责出队

  1. //入队
  2. void appendTail(int value)
  3. {
  4. st1.push(value);
  5. }
  6. //出队
  7. int deleteHead()
  8. {
  9. if(st2.empty() && !st1.empty())
  10. {
  11. while(!st1.empty())
  12. {
  13. st2.push(st1.top());
  14. st1.pop();
  15. }
  16. }
  17. if(!st2.empty())
  18. {
  19. int val = st2.top();
  20. st2.pop();
  21. return val;
  22. }
  23. return -1;
  24. }
  25. private:
  26. stack<int> st1;
  27. stack<int> st2;

2.包含min函数的栈

思路:借助辅助栈,辅助栈存放当前栈里的最小值,与栈进行同步操作,同时入,同时出

如果入栈元素,大于辅助栈的栈顶元素,则将将自己的栈顶元素再入一次,否则直接入要

入栈的元素

  1. void push(int x)
  2. {
  3. if(st.empty())
  4. {
  5. st.push(x);
  6. min_st.push(x);
  7. return;
  8. }
  9. st.push(x);
  10. if(x>min_st.top())
  11. {
  12. min_st.push(min_st.top());
  13. }
  14. else
  15. {
  16. min_st.push(x);
  17. }
  18. }
  19. void pop()
  20. {
  21. st.pop();
  22. min_st.pop();
  23. }
  24. int top()
  25. {
  26. return st.top();
  27. }
  28. int min()
  29. {
  30. return min_st.top();
  31. }
  32. stack<int> st;
  33. stack<int> min_st;

3.冒泡排序 O(n^2)   交换次数太多   稳点排序

  1. for(int i = 0; i < size-1; ++i)
  2. {
  3. int tag = true;
  4. for(int j = 0; j<size-1-i; ++j)
  5. {
  6. if(arr[j] > arr[j+1])
  7. {
  8. swap(arr[j],arr[j+1]);
  9. tag = false;
  10. }
  11. }
  12. if(tag) break;
  13. }

4.选择排序 O(n^2)  交换次数少  不稳定的排序

  1. for(int i = 0; i < size-1; ++i)
  2. {
  3. int min = nums[i];
  4. int idx = i;
  5. for(int j = i+1; j < size; ++j)
  6. {
  7. //记录一趟中最小的元素和下标
  8. if(nums[j] < min)
  9. {
  10. min = nums[j];
  11. idx = j;
  12. }
  13. }
  14. if(idx != i)
  15. {
  16. swap(nums[idx],nums[i]);
  17. }
  18. }

5.插入排序 (数据越有序,效率越高)

  1. //认为只有1个元素时,有序
  2. for(int i = 1; i < size; ++i)
  3. {
  4. int val = arr[i]; //要插入的元素
  5. int j = i - 1; //0---i-1 中插入
  6. //如果比第一个位置的元素还要小,则退出
  7. for(; j>=0; --j)
  8. {
  9. //已经找到合适的位置
  10. if(arr[j] >= val)
  11. {
  12. break;
  13. }
  14. arr[j+1] = arr[j]; //向后移动
  15. }
  16. arr[j+1] = val;
  17. }

插入排序  > 选择排序 > 冒泡排序

插入排序:没有交换,比较次数比较少,稳定的排序

6.希尔排序

  1. for(int gap = size/2; gap != 0; gap/=2)
  2. {
  3. for(int i = gap; i<size; i++)
  4. {
  5. int j = i-gap;
  6. int val = arr[i];
  7. for(; j>=0; j -= gap)
  8. {
  9. if(arr[j] >= val)
  10. {
  11. break;
  12. }
  13. arr[j+gap] = arr[j];
  14. }
  15. arr[j+gap] = val;
  16. }
  17. }

7.快排(n*log(n)  不稳定)

  1. void QuickSort(int arr[],int begin,int end)
  2. {
  3. if(begin >= end)
  4. {
  5. return;
  6. }
  7. //优化
  8. if(begin - end <= 50)
  9. {
  10. Insert(arr,begin,end);
  11. return;
  12. }
  13. int pos = Partation(arr,begin,end);
  14. QuickSort(arr,begin,pos-1);
  15. QuickSort(arr,pos+1,end);
  16. }
  17. int Partation(int arr[],int left,int right)
  18. {
  19. //三数取中
  20. //arr[left] arr[right] arr[(left+right)/2]
  21. int val = arr[left];
  22. while(left < right)
  23. {
  24. while(left < right && arr[right] > val)
  25. {
  26. --right;
  27. }
  28. if(left < right)
  29. {
  30. arr[left] = arr[right];
  31. ++left;
  32. }
  33. while(left < right && arr[left] < val)
  34. {
  35. ++left;
  36. }
  37. if(left < right)
  38. {
  39. arr[right] = arr[left];
  40. --right;
  41. }
  42. }
  43. arr[left] = val;
  44. return left;
  45. }
  46. void InsertSort(int arr[],int left,int right)
  47. {
  48. for(int i = left+1; i < right; ++i)
  49. {
  50. int val = arr[i];
  51. int j = i - 1;
  52. for(;j>=0;--j)
  53. {
  54. if(arr[j]>=val)
  55. break;
  56. arr[j+1] = arr[j];
  57. }
  58. arr[j+1] = val;
  59. }
  60. }

8.归并排序(稳定排序,O(n) + log(n))

  1. vec.resize(sizeof(arr),0);
  2. void MerageSort(int arr[],int begin,int end)
  3. {
  4. if(begin <= end)
  5. {
  6. return;
  7. }
  8. int mid = begin + ((end - begin)>>1);
  9. MerageSort(arr,begin,mid);
  10. MerageSort(arr,mid+1,end);
  11. Merage(arr,begin,mid,end);
  12. }
  13. void Merage(int arr[],int begin,int mid,int end)
  14. {
  15. int i = begin;
  16. int j = mid+1;
  17. int idx = 0;
  18. while(i<=mid && j<=end)
  19. {
  20. if(arr[i] <= arr[j])
  21. {
  22. vec[idx] = arr[i];
  23. ++i;
  24. }
  25. else
  26. {
  27. vec[idx] = arr[j];
  28. ++j;
  29. }
  30. ++idx;
  31. }
  32. while(i<=mid)
  33. {
  34. vec[idx] = arr[i];
  35. ++i;
  36. ++idx;
  37. }
  38. while(j<=end)
  39. {
  40. vec[idx] = arr[j];
  41. ++j;
  42. ++idx;
  43. }
  44. idx = 0;
  45. for(;begin <= end; ++begin,++idx)
  46. {
  47. arr[begin] = vec[idx];
  48. }
  49. }
  50. private:
  51. vector<int> vec;

9. 优先级队列

思路:将数组中存储的元素看成一个完全二叉树

第一个非叶节点下标:(n-1)/2     n表示数组最后一个元素的下标

0 <= i  && i <= (n-1)/2   所有的非叶子结点 

小根堆:arr[i] < arr[2i+1]  && arr[i] < arr[2i+2]

大根堆:arr[i] > arr[2i+1]  && arr[i] > arr[2i+2]

求一个结点的双亲结点:(chid-1)/2 

  1. //大根堆
  2. //size_ 表示数组中已有元素的个数
  3. int top()
  4. {
  5. if(size_ == 0)
  6. throw "container is empty";
  7. return arr[0];
  8. }
  9. bool empty()
  10. {
  11. return size_ == 0;
  12. }
  13. void push(int val)
  14. {
  15. if(size_ == 0)
  16. {
  17. arr[size_] = val;
  18. }
  19. else
  20. {
  21. //要插入元素的下标和值
  22. upShift(size_,val);
  23. }
  24. ++size_;
  25. }
  26. void pop()
  27. {
  28. if(empty())
  29. {
  30. return;
  31. }
  32. else
  33. {
  34. --size_;
  35. //删除元素后,最后一个元素的下标,和第一个元素的值
  36. downShift(0,arr[size_]);
  37. }
  38. }
  39. private:
  40. void upShift(int i,int val)
  41. {
  42. while(i>0)
  43. {
  44. int parent = (i-1)/2;
  45. if(arr[parent] < val)
  46. {
  47. arr[i] = arr[parent];
  48. }
  49. else
  50. break;
  51. i = parent;
  52. }
  53. arr[i] = val;
  54. }
  55. void downShift(int i,int val)
  56. {
  57. while(i <= (size_-1-1)/2)
  58. {
  59. int child = 2*i+1;
  60. if(child+1 < size_ && arr[child] < arr[child+1])
  61. {
  62. child = child + 1;
  63. }
  64. if(val < arr[child])
  65. {
  66. arr[i] = arr[child];
  67. }
  68. else
  69. {
  70. break;
  71. }
  72. i = child;
  73. }
  74. arr[i] = val;
  75. }



10.堆排   O(logn)*O(n)  不稳定

1.从第一个非叶子节点开始,把二叉堆调整成一个大根堆

从(n-1)/2号位元素开始到堆顶元素(0),进行下沉操作

将数组的元素调整成一个大根堆

2.每次将堆顶元素与最后一个叶子结点交换,每次排出一个堆内的最大值

  1. void HeapSort(int arr[],int size)
  2. {
  3. //调整成大根堆
  4. for(int i = (size-1-1)/2; i >=0 ; --i)
  5. {
  6. downShift(arr,i,size);
  7. }
  8. //交换堆顶和最后一个叶子结点,进行调整
  9. for(int n = size-1; n>0; --n)
  10. {
  11. swap(arr[n],arr[0]);
  12. downShift(arr,0,n);
  13. }
  14. }
  15. void downShift(int arr[],int i,int size)
  16. {
  17. int val = arr[i];
  18. while(i<=(size-1-1)/2)
  19. {
  20. int child = 2*i+1;
  21. if(child + 1 < size && arr[child] < arr[child+1])
  22. {
  23. child = child+1;
  24. }
  25. if(arr[child] > val)
  26. {
  27. arr[i] = arr[child];
  28. i = child;
  29. }
  30. else
  31. {
  32. break;
  33. }
  34. }
  35. arr[i] = val;
  36. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/article/detail/43719
推荐阅读
相关标签
  

闽ICP备14008679号