线性表之顺序表的实现
来源:互联网 发布:前端软件外包交易平台 编辑:程序博客网 时间:2024/06/16 12:27
本文针对顺序表,总结其相应的常用操作。主要是给出代码实现。
结构、常量声明
common.h
#ifndef common_H#define common_H/* 函数结果状态码 */#define TRUE 1#define FALSE 0#define OK 1#define ERROR 0#define INFEASIBLE -1//#define OVERFLOW -2/* 类型定义 */typedef int Status; // Status是函数的类型,其值是函数结果状态码typedef int ElemType; // ElemType是数据类型#endif
顺序表常用操作接口声明
SeqList.h
#ifndef SeqList_H#define SeqList_H#include "common.h"Status print( const ElemType* arr, int n ); // 顺序表打印Status find_x( const ElemType* arr, int n, ElemType x );// 顺序表查找Status insert_x( ElemType* arr, int& n, ElemType x ); // 有序顺序表插入Status delete_x( ElemType* arr, int& n, ElemType x ); // 顺序表删除Status delete_allx( ElemType* arr, int& n, ElemType x );// 删除顺序表所有x元素 Status delete_allxy( ElemType* arr, int& n, ElemType x, ElemType y ); // // 删除顺序表所有位于x与y之间的元素 O(n)实现Status delete_same( ElemType* arr, int& n ); // 删除顺序表中的重复元素Status reverse( ElemType* arr, int n ); // 置逆Status is_palindrome( const ElemType* arr, int n ); // 判断回文Status move_left( ElemType* arr, int n, int k ); // 循环左移k位Status move_left1( ElemType* arr, int n, int k ); // 循环左移k位Status move_right( ElemType* arr, int n, int k ); // 循环右移k位Status move_right1( ElemType* arr, int n, int k ); // 循环右移k位Status move_right2( ElemType* arr, int n, int k ); // 循环右移k位Status adjust( ElemType* arr, int n, Status (*compare)(ElemType) ); // 将满足compare()的元素调整到数组的前面,不满足的调整到数组的后面ElemType* merge( ElemType* arr1, int n1, ElemType* arr2, int n2 ); // 归并两个有序表ElemType* merge1( ElemType* arr1, int n1, ElemType* arr2, int n2 ); // 归并两个有序表,不含重复元素#endif
顺序表常用操作实现(SeqList.cpp)
- 打印
思路:枚举
Status print( const ElemType* arr, int n ){ if( NULL == arr || n <= 0 ) { std::cerr << "Invalid arguments !" << std::endl; return ERROR; } for( int i = 0; i < n; ++i ) { std::cout << arr[i] << std::endl; } return OK;}
- 查找
思路:枚举
int find( const ElemType* arr, int n, ElemType x ){ if( NULL == arr || n <= 0 ) { std::cerr << "Invalid arguments !" << std::endl; return ERROR; } for( int i = 0; i < n; ++i ) { if( arr[i] == x ) return i; } return OK;}
- 有序表插入
思路:寻找插入位置,向后移动,插入元素值
Status insert_x( ElemType* arr, int& n, ElemType x ){ if( NULL == arr || n <= 0 ) { std::cerr << "Invalid arguments!" << std::endl; return ERROR; } int loc = 0; while( loc<n && arr[loc] < x ) ++loc; if( loc < n ) { for( int i = n-1; i >= loc; --i ) arr[i+1] = arr[i]; arr[loc] = x; } else arr[loc] = x; ++n; return OK;}
- 顺序表删除
思路:查找删除元素,移动后面元素向前一个位置覆盖
Status delete_x( ElemType* arr, int& n, ElemType x ){ if( NULL == arr || n <= 0 ) { std::cerr << "Invalid arguments!" << std::endl; return ERROR; } int loc = 0; while( loc < n && arr[loc] != x ) ++loc; if( loc < n ) { for( int i = loc+1; i < n; ++i ) arr[i-1] = arr[i]; --n; return OK; } else { std::cerr << x << " not in the SeqList" << std::endl; return ERROR; }}
- 顺序表删除所有值为x的元素
思路:枚举顺序表,cnt_x记录元素值为x的出现次数。对于不是x的元素,向前移动cnt_x的位置。O(n)复杂度。
Status delete_allx( ElemType* arr, int& n, ElemType x ){ if( NULL == arr || n <= 0 ) { std::cerr << "Invalid arguments!" << std::endl; return ERROR; } int cnt_x = 0; // 元素值为x的数量 for( int i = 0; i < n; ++i ) { if( arr[i] == x ) { ++cnt_x; continue; } arr[i - cnt_x] = arr[i]; } n -= cnt_x; return OK;}
- 删除顺序表所有位于x与y之间的元素
思路:方法同上。cnt_xy记录值在x与y之间的元素个数,向前移动即可。
Status delete_allxy( ElemType* arr, int& n, ElemType x, ElemType y ){ if( NULL == arr || n <= 0 || x > y ) { std::cerr << "Invalid arguments!" << std::endl; return ERROR; } int cnt_xy = 0; for( int i = 0; i < n; ++i ) { if( x <= arr[i] && arr[i] <= y ) { ++cnt_xy; continue; } arr[i - cnt_xy] = arr[i]; } n -= cnt_xy; return OK;}
- 删除顺序表中重复元素
思路:方法大致同上。需要O(N)的空间复杂度。用hash表做。设置cnt_same记录重复元素的格式。如果不是重复元素,向前移动cnt_same个位置。
Status delete_same( ElemType* arr, int& n ){ if( NULL == arr || n <= 0 ) { std::cerr << "Invalid arguments!" << std::endl; return ERROR; } std::map< ElemType, bool > hash ; int cnt_same = 0; for( int i = 0; i < n; ++i ) { if( hash.find( arr[i] ) == hash.end() ) { hash[arr[i]] = true; arr[i - cnt_same] = arr[i]; } else { ++cnt_same; continue; } } n -= cnt_same; return OK;}
- 置逆
思路:枚举,中轴
Status reverse( ElemType* arr, int n ){ if( NULL == arr || n <= 0 ) { std::cerr << "Invalid arguments !" << std::endl; return ERROR; } int mid = n/2; // 中轴 for( int i = 0; i < mid; ++i ) { ElemType t = arr[i]; arr[i] = arr[n - 1 - i]; arr[n - 1 - i] = t; } return OK;}
- 判断回文
思路:枚举,中轴
Status move_left( ElemType* arr, int n, int k ){ if( NULL == arr || n <= 0 || k < 0 || k >= n ) { std::cerr << "Invalid arguments!" << std::endl; return ERROR; } ElemType* tmp = new ElemType[k]; if( NULL == tmp ) { std::cout << "Not enough space!" << std::endl; return ERROR; } for( int i = 0; i < k; ++i ) { tmp[i] = arr[i]; } for( int i = k; i < n; ++i ) { arr[i-k] = arr[i]; } for( int i = n - 1, j = k - 1; i >= n-k; --i, --j ) { arr[i] = tmp[j]; } delete tmp; return OK;}
- 循环左移k位
思路:保留左侧k位,将右侧n-k位依次左移,然后将保留的左侧k位放置的右侧k位
Status move_left( ElemType* arr, int n, int k ){ if( NULL == arr || n <= 0 || k < 0 || k >= n ) { std::cerr << "Invalid arguments!" << std::endl; return ERROR; } ElemType* tmp = new ElemType[k]; if( NULL == tmp ) { std::cerr << "Not enough space!" << std::endl; return ERROR; } for( int i = 0; i < k; ++i ) { tmp[i] = arr[i]; } for( int i = k; i < n; ++i ) { arr[i-k] = arr[i]; } for( int i = n - 1, j = k - 1; i >= n-k; --i, --j ) { arr[i] = tmp[j]; } delete tmp; return OK;}
改进算法:
这个问题可以看做把数组ab转换为数组ba(a代表前k个元素,b代表后n-k个元素)
arr[k|n-k] 转化为 arr[ n-k|k ]
1.a置逆得到
2.b置逆得到
3.最后将整个数组置逆得到 ba
本质是公式:
Status move_left1( ElemType* arr, int n, int k ){ if( NULL == arr || n <= 0 || k < 0 || k >= n ) { std::cout << "Invalid arguments!" << std::endl; return ERROR; } reverse( arr, k ); reverse( arr + k, n-k ); reverse( arr, n ); return OK;}
- 循环右移k位(本质是循环左移n-k位)
思路:同上面的第一种办法。先保留右侧k位,将左侧n-k位向右移动k位。最后将保留的k位顺序填充到左侧。
Status move_right( ElemType* arr, int n, int k ){ if( NULL == arr || n <= 0 || k >= n ) { std::cerr << "Invalid arguments!" << std::endl; return -1; } ElemType* tmp = new ElemType[k]; if( NULL == tmp ) { std::cerr << "Not enough space!" << std::endl; return ERROR; } for( int i = n-k, j = 0; i < n; ++i, ++j ) { tmp[j] = arr[i]; } for( int i = n-k-1; i >= 0; --i ) { arr[i+k] = arr[i]; } for( int i = 0, j = 0; i < k; ++i, ++j ) { arr[i] = tmp[j]; } delete tmp; return OK;}
思路:
右移k位本质是左移n-k位,方法和上面第二种一样。不做过多说明。
Status move_right1( ElemType* arr, int n, int k ){ if( NULL == arr || n <= 0 || k >= n ) { std::cerr << "Invalid arguments!" << std::endl; return -1; } reverse( arr, n-k ); reverse( arr + n-k, k ); reverse( arr, n ); return OK;}
思路:直接调用左移算法
Status move_right2( ElemType* arr, int n, int k ){ if( NULL == arr || n <= 0 || k >= n ) { std::cerr << "Invalid arguments!" << std::endl; return ERROR; } Status ret = move_right( arr, n, n-k ); return ret;}
- 将满足compare()的元素调整到数组的前面,不满足的调整到数组的后面
思路:类似partition算法,分别从前,后寻找mismatch,找到一个发生交换即可。
Status adjust( ElemType* arr, int n, Status (*compare)(ElemType) ){ if( NULL == arr || n <=0 || NULL == compare ) { std::cerr << "Invalid arguments!" << std::endl; return ERROR; } int i = 0; int j = n - 1; while( i < j ) // 调整没有结束 { while( i < j && compare(arr[i]) ) ++i; while( i < j && !compare(arr[j]) ) --j; if( i < j ) { ElemType t = arr[i]; arr[i] = arr[j]; arr[j] = t; ++i; --j; } } return OK;}
- 归并操作
思路:每次取较小结果存入归并结果。
ElemType* merge( ElemType* arr1, int n1, ElemType* arr2, int n2 ){ if( NULL == arr1 || n1 <= 0 || NULL == arr2 || n2 <= 0 ) { std::cerr << "Invalid arguments!" << std::endl; return NULL; } ElemType* arr3 = new ElemType[ n1 + n2 ]; if( NULL == arr3 ) { std::cerr << "Not enough space!" << std::endl; return NULL; } int i = 0; int j = 0; int k = 0; while( i < n1 && j < n2 ) { if( arr1[i] < arr2[j] ) { arr3[k++] = arr1[i++]; } else { arr3[k++] = arr2[j++]; } } while( i < n1 ) arr3[k++] = arr1[i++]; while( j < n2 ) arr3[k++] = arr2[j++]; return arr3;}
- 归并操作,不含重复元素
ElemType* merge1( ElemType* arr1, int n1, ElemType* arr2, int n2 ){ if( NULL == arr1 || n1 <= 0 || NULL == arr2 || n2 <= 0 ) { std::cerr << "Invalid arguments!" << std::endl; return NULL; } ElemType* arr3 = new ElemType[ n1 + n2 ]; if( NULL == arr3 ) { std::cerr << "Not enough space!" << std::endl; return NULL; } int i = 0; int j = 0; int k = 0; while( i < n1 && j < n2 ) { if( arr1[i] < arr2[j] ) { arr3[k++] = arr1[i++]; } else if( arr1[i] > arr2[j] ) { arr3[k++] = arr2[j++]; } else { arr3[k++] = arr1[i++]; j++; } } while( i < n1 ) arr3[k++] = arr1[i++]; while( j < n2 ) arr3[k++] = arr2[j++]; return arr3;}
0 0
- 线性表之顺序表的实现
- 线性表的顺序实现
- 线性表的顺序实现
- 线性表的顺序实现
- 线性表的顺序实现
- 线性表的顺序实现
- 顺序线性表的实现
- 线性表的顺序实现
- 线性顺序表的实现
- 线性表的顺序实现
- 数据结构学习之线性表的顺序实现(python 实现)
- 线性表之顺序表的结构与实现
- 数据结构之---c语言实现线性表的顺序表
- [数据结构]线性表之顺序表的类模板实现
- 数据结构之:线性表的顺序表示和实现
- 数据结构之线性表的顺序表示和实现
- 线性表之栈的顺序存储实现
- 数据结构线性表之顺序表实现
- 【leetcode题解】412. Fizz Buzz【E】
- HDU 1200 To and Fro
- Android基础Alert相关
- openstack安装部署6——网络服务(控制节点&计算节点)
- 目标特征提取(一):全局特征
- 线性表之顺序表的实现
- 基于数组的实现网页中的页面切换效果
- 关于Caffe之Contrastive + Softmax在CASIA-WebFace上的实验
- 问题记录一
- C++每日一练(异常)
- 采用循环队列或链队列实现病人看病的模拟程序
- 用U盘centos的注意事项
- MySQL优化之varchar与char选择
- 自考-C++—第六章继承和派生