数据结构编程

1、数组部分

哈希表思想:

哈希表也称为散列表,是算法终于时间和空间作出权衡的经典例子。

    当一个表所有的键都是小整数时,便可以使用一个数组来实现无序的符号表,将键作为数组的索引而数组i中所存储的值就是该键所对应的键值,即key-value对应。

哈希表的思想也是这样子的,只是哈希表的键的类型更为复杂而已。

使用哈希表(散列查找)分为两步:

  1. 用散列函数将被查找的键转换为数组的一个索引。理想情况下,不同的键值都会转换成为不同的索引值,但是一般情况下我们会遇到多个键对应相同的索引值,这也就是所谓的散列冲突。
  2. 处理碰撞冲突的情况,常用得方法有两种:拉链法(链地址法)和线性探测法。

(1)拉链法(链地址法):遇到冲突时,在原地址新建一个空间,然后以链表节点的形式插入到该空间;

(2)开放地址法(开放地址散列表):该方法是指用大小为M的数组保存N的键值对,其中,M>N。这样可以通过依靠数组M中的空位解决碰撞冲突。

C++数组自动扩容(动态数组)、有序数组动态增删改

public class MyArray {
    int Size=0;
    int capacity=0;
    int[] p=null;

    public  MyArray(int len)
    {
        p=new int[len];
        capacity=len;
    }
    public void add(int index,int num)
    {
        if(index<0||index>Size)
            return ;
        if(Size>=capacity)
            resize(p);
 
        p[index]=num;
        Size++;
    }
    public void update(int index,int num)
    {
        if(index<0||index>Size)
            return ;
        p[index]=num;
    }
    public void resize(int[] p){
        int[]temp=new int[capacity];
        for(int i=0;i<capacity;i++){
            temp[i]=p[i];
        }
        capacity=2*capacity;
        p=new int[capacity];
        for(int i=0;i<capacity/2;i++){
            p[i]=temp[i];
        }
    }
    public void delete(int index,int num)
    {
        if(index<0||index>Size)
            return ;
        for(int i=index+1;i<capacity;i++){
            p[i]=p[i+1];
        }
        Size--;
    }
    public  static void main(String[] args){
        MyArray ma=new MyArray(3);
        ma.add(0,0);
        ma.add(1,1);
        ma.add(2,2);
        ma.add(3,3);
 
    }
}

实现两个有序数组合并为一个有序数组


#include<iostream>
 
using namespace std;
 
//两个有序数组进行排序,A有足够的空间容纳B,把和A融入到一起
 
void MergeArray(int a[], int b[], int la, int lb)//输入A和B的数组和两个长度
{
    if (la <= 0 || lb <= 0)
        return;  //return false;或者return 0 
 
    int index=la+lb-1;
    int ida = la - 1;
    int idb = lb - 1;
    
    while (index >= 0)
    {
        if (a[ida] > b[idb]||idb<0)  //注意边界条件,当一个数组中没有元素时,也要移动
            a[index--] = a[ida--];
        else if (a[ida]<=b[idb]||ida<0)
            a[index--] = b[idb--];
    }    
}
 
int main()
{
 
    int a[10] = { 3, 5, 7, 10, 15 };
    int b[] = { 4, 8, 16 };
 
    MergeArray(a, b, 5, 3);
 
    for (int i = 0; i < 3 + 5; i++)
    {
        cout << a[i] << endl;
    }
    
    return 0;
}

leetcode的两数之和(1)和happy Number(202)

happy number(202)

Description

Write an algorithm to determine if a number is "happy".A happy number is a number defined by the following process: Starting with any positive integer, replace the number by the sum of the squares of its digits, and repeat the process until the number equals 1 (where it will stay), or it loops endlessly in a cycle which does not include 1. Those numbers for which this process ends in 1 are happy numbers.

Example:

Input: 19
Output: true
Explanation: 
12 + 92 = 82
82 + 22 = 68
62 + 82 = 100
12 + 02 + 02 = 1escription
  • Solution
class Solution {
public:
  

    bool isHappy(int n) {
        unordered_map<int,int>map_test;
        
        while(n != 1)
        {
            if (map_test[n] == 0)
                map_test[n]++;
            else
                return false;
            
            int sum = 0;
            while(n)
            {
                
                sum = sum+ pow(n%10,2);
                n = n/10;   
            }
            n = sum;
        }
        
        return true;
        
        
    }
};

2、字符串部分

Trie字典树的基本概念

Trie树是一种哈希树的变种,又称字典树,单词查找树或者前缀树,用于保存大量的字符串,是一种用于快速检索的多叉树结构(如英文字母的字典树是一个26叉树,数字的字典树是一个10叉树)。

Trie字典树主要用于存储字符串,Trie 的每个 Node 保存一个字符。用链表来描述的话,就是一个字符串就是一个链表。每个Node都保存了它的所有子节点。

// Trie.cpp : 定义控制台应用程序的入口点。
//Trie 称为字典树,单词查找树或者前缀树
#include "stdafx.h"
#include <iostream>
#include <assert.h>
using namespace std;
 
const int MAX_NUM = 26;
//Trie 树的结点类型
struct Node
{
      bool COMPLETED ;//COMPLETED为 true时表示目前产生的一个字符串
      char ch ;
      struct Node * child[ MAX_NUM]; //26-tree->a, b ,c, .....z
};
//Trie 树类型
class Trie
{
public :
      Trie();
     ~ Trie();
      Node* CreateNewNode (char ch);// 创建一个新结点
      void InitTrie ();//初始化 Trie树
      int CharToindex (char ch);// 找到字母对应的数组下标
      int Find (const char chars [], int len);// 找到长度为 len的字符串
      void Insert (const char chars [], int len);// 插入长度为 len的字符串
      void Delete ();//删除整棵树
 
private :
      void DeleteTree (Node *& root);
      Node* root ; //根结点
};
 
 
Trie::Trie ()
{
    root = NULL ;
}
 
Trie::~Trie ()
{
 
}
 
Node* Trie ::CreateNewNode( char ch )//创建一个新的结点
{    
      Node *new_node = new Node;
      new_node->ch = ch;
      new_node->COMPLETED = false;
 
      for(int i=0; i<MAX_NUM ; i++)
     {
        new_node->child [i] = NULL;
     }         
      return new_node ;
}
 
void Trie ::InitTrie() //构建一棵空树
{    
      root = CreateNewNode (' ');
}
 
int Trie ::CharToindex( char ch )
{
      return ch - 'a';
}
 
int Trie ::Find( const char chars[], int len )
{
      if (root == NULL)
     {
           cout<<" 树为空!"<< endl;
           return 0;
     }
 
      Node* ptr = root;
      int i = 0;
      while(i < len)
     {
           if(ptr ->child[ CharToindex(chars [i])] == NULL)
          {
               break;
          }
           ptr = ptr ->child[ CharToindex(chars [i])];
           i++;
     }
      return (i == len) && ( ptr->COMPLETED == true);
}
 
void Trie ::Insert( const char chars[], int len ) //向 Trie树中插入长度为len的字符串
{
      Node* ptr = root;
     
      for(int i = 0; i < len ; i++)
     {
           if(ptr ->child[ CharToindex(chars [i])] == NULL)
          {
               ptr->child [CharToindex( chars[i ])] = CreateNewNode (chars[ i]);
          }
           ptr = ptr ->child[ CharToindex(chars [i])];
     }
      ptr->COMPLETED = true;
}
 
void Trie ::Delete() //利用递归删除整棵树
{
   DeleteTree(root );
}
 
void Trie ::DeleteTree( Node *&Root )//利用递归删除整棵树 注意此处应该加上应用
{
      if (Root == NULL) //递归出口
     {
           return;
     }
     
      for (int i=0; i<MAX_NUM ; i++)
     {
           if (Root ->child[ i] != NULL )
          {
               DeleteTree(Root ->child[ i]);
          }
     }
//   if(Root->ch == ' ')
//   {
//        cout<<"zha'"<<endl;
//   }
      delete Root ;
      Root = NULL ;       
}
 
int _tmain (int argc, _TCHAR * argv[])
{
      char *a = "ten";
      char *b = "tea";
      Trie trie ;
      trie.InitTrie ();
      trie.Insert (a, 3);
      trie.Insert (b, 3);
      cout<<trie .Find( a,3)<<endl ;
      trie.Delete ();
    cout<<trie .Find( b,3)<<endl ;
 
      system("pause" );
      return 0;
}

2.2实现朴素的字符串匹配算法

//在主串s中找子串t,若找到返回字串在主串中的索引;若没找到返回-1
#include <iostream>
#include <string>

using namespace std;

int Index(string s, string t){
    int lens = s.length();//计算串s、t的长度
    int lent = t.length();
    int i = 0;
    int j = 0;
    while (i < lens&&j < lent){//如果i、j都各自小于lens和lent
        if (t[j] == s[i]){//如果子串的t[j]和主串的s[i]相等
            ++i;//各自索引都自增
            ++j;
        }
        else{//否则,主串的索引比刚开始后移一个;子串的索引变为0
            i = i - j + 1;
            j = 0;
        }
    }
    if (j == lent){//如果最j和lent的大小一样,证明找到了,返回子串在主串中的索引
        return i - lent;
    }
    else{//否则返回-1
        return -1;
    }
}

int main(){
    string s = "goodgoogle";
    string t = "google";
    int pos = Index(s, t);
    if (pos != -1){
        cout << "find " << t << " at the index " << pos << " of " << s << endl;
    }
    else{
        cout << "can't find " << t << " in " << s << endl;
    }
    return 0;
}
 

本文参考及学习资料:

【1】https://github.com/Sly-Guo/learngit/blob/master/数据结构编程学习/

【2】哈希表设计思想及实现:https://songwell1024.github.io/2018/07/01/HashTable/

【3】数据结构与算法(十一)Trie字典树https://blog.csdn.net/johnny901114/article/details/80711441 

【4】https://blog.csdn.net/sinat_36053757/article/details/71023766 

猜你喜欢

转载自blog.csdn.net/xiu351084315/article/details/89219624
今日推荐